2023-03-09 17:01:40 +00:00
|
|
|
"use client";
|
|
|
|
|
2023-07-17 03:33:19 +00:00
|
|
|
require("../polyfill");
|
2023-04-03 05:29:37 +00:00
|
|
|
|
2023-04-21 17:13:23 +00:00
|
|
|
import { useState, useEffect } from "react";
|
2023-03-11 17:14:07 +00:00
|
|
|
|
2023-03-12 19:06:21 +00:00
|
|
|
import styles from "./home.module.scss";
|
2023-03-09 17:01:40 +00:00
|
|
|
|
|
|
|
import BotIcon from "../icons/bot.svg";
|
2023-03-10 18:25:33 +00:00
|
|
|
import LoadingIcon from "../icons/three-dots.svg";
|
|
|
|
|
2023-04-20 15:20:25 +00:00
|
|
|
import { getCSSVar, useMobileScreen } from "../utils";
|
2023-03-13 16:25:07 +00:00
|
|
|
|
2023-03-20 15:11:04 +00:00
|
|
|
import dynamic from "next/dynamic";
|
2023-04-23 17:15:44 +00:00
|
|
|
import { Path, SlotID } from "../constant";
|
2023-04-03 05:29:37 +00:00
|
|
|
import { ErrorBoundary } from "./error";
|
2023-03-20 15:11:04 +00:00
|
|
|
|
2023-08-14 13:55:18 +00:00
|
|
|
import { getISOLang, getLang } from "../locales";
|
2023-06-24 05:10:34 +00:00
|
|
|
|
2023-04-20 17:12:39 +00:00
|
|
|
import {
|
|
|
|
HashRouter as Router,
|
|
|
|
Routes,
|
|
|
|
Route,
|
|
|
|
useLocation,
|
|
|
|
} from "react-router-dom";
|
2023-04-21 15:37:25 +00:00
|
|
|
import { SideBar } from "./sidebar";
|
2023-04-21 16:12:07 +00:00
|
|
|
import { useAppConfig } from "../store/config";
|
2023-06-06 18:18:24 +00:00
|
|
|
import { AuthPage } from "./auth";
|
2023-06-13 16:37:42 +00:00
|
|
|
import { getClientConfig } from "../config/client";
|
2023-07-04 15:16:24 +00:00
|
|
|
import { api } from "../client/api";
|
2023-07-10 15:19:43 +00:00
|
|
|
import { useAccessStore } from "../store";
|
2023-04-20 17:12:39 +00:00
|
|
|
|
2023-03-21 14:56:27 +00:00
|
|
|
export function Loading(props: { noLogo?: boolean }) {
|
|
|
|
return (
|
2023-04-20 17:12:39 +00:00
|
|
|
<div className={styles["loading-content"] + " no-dark"}>
|
2023-03-21 14:56:27 +00:00
|
|
|
{!props.noLogo && <BotIcon />}
|
|
|
|
<LoadingIcon />
|
|
|
|
</div>
|
|
|
|
);
|
2023-03-20 15:11:04 +00:00
|
|
|
}
|
|
|
|
|
2023-03-21 14:56:27 +00:00
|
|
|
const Settings = dynamic(async () => (await import("./settings")).Settings, {
|
|
|
|
loading: () => <Loading noLogo />,
|
|
|
|
});
|
2023-03-20 15:11:04 +00:00
|
|
|
|
2023-04-21 17:13:23 +00:00
|
|
|
const Chat = dynamic(async () => (await import("./chat")).Chat, {
|
|
|
|
loading: () => <Loading noLogo />,
|
|
|
|
});
|
|
|
|
|
2023-04-23 17:17:28 +00:00
|
|
|
const NewChat = dynamic(async () => (await import("./new-chat")).NewChat, {
|
|
|
|
loading: () => <Loading noLogo />,
|
|
|
|
});
|
|
|
|
|
2023-04-24 16:49:27 +00:00
|
|
|
const MaskPage = dynamic(async () => (await import("./mask")).MaskPage, {
|
|
|
|
loading: () => <Loading noLogo />,
|
|
|
|
});
|
|
|
|
|
2023-04-20 18:52:53 +00:00
|
|
|
export function useSwitchTheme() {
|
2023-04-21 16:12:07 +00:00
|
|
|
const config = useAppConfig();
|
2023-03-12 19:06:21 +00:00
|
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
document.body.classList.remove("light");
|
|
|
|
document.body.classList.remove("dark");
|
2023-03-27 09:04:11 +00:00
|
|
|
|
2023-03-12 19:06:21 +00:00
|
|
|
if (config.theme === "dark") {
|
|
|
|
document.body.classList.add("dark");
|
|
|
|
} else if (config.theme === "light") {
|
|
|
|
document.body.classList.add("light");
|
|
|
|
}
|
2023-03-27 09:04:11 +00:00
|
|
|
|
2023-04-03 16:24:59 +00:00
|
|
|
const metaDescriptionDark = document.querySelector(
|
2023-05-12 10:47:41 +00:00
|
|
|
'meta[name="theme-color"][media*="dark"]',
|
2023-04-03 16:24:59 +00:00
|
|
|
);
|
|
|
|
const metaDescriptionLight = document.querySelector(
|
2023-05-12 10:47:41 +00:00
|
|
|
'meta[name="theme-color"][media*="light"]',
|
2023-04-03 16:24:59 +00:00
|
|
|
);
|
2023-03-15 17:24:03 +00:00
|
|
|
|
2023-04-03 16:24:59 +00:00
|
|
|
if (config.theme === "auto") {
|
|
|
|
metaDescriptionDark?.setAttribute("content", "#151515");
|
|
|
|
metaDescriptionLight?.setAttribute("content", "#fafafa");
|
|
|
|
} else {
|
2023-05-12 10:47:41 +00:00
|
|
|
const themeColor = getCSSVar("--theme-color");
|
2023-04-03 16:24:59 +00:00
|
|
|
metaDescriptionDark?.setAttribute("content", themeColor);
|
|
|
|
metaDescriptionLight?.setAttribute("content", themeColor);
|
|
|
|
}
|
2023-03-27 09:04:11 +00:00
|
|
|
}, [config.theme]);
|
2023-03-19 15:13:10 +00:00
|
|
|
}
|
|
|
|
|
2023-08-14 13:55:18 +00:00
|
|
|
function useHtmlLang() {
|
|
|
|
useEffect(() => {
|
|
|
|
const lang = getISOLang();
|
|
|
|
const htmlLang = document.documentElement.lang;
|
|
|
|
|
|
|
|
if (lang !== htmlLang) {
|
|
|
|
document.documentElement.lang = lang;
|
|
|
|
}
|
|
|
|
}, []);
|
|
|
|
}
|
|
|
|
|
2023-03-27 08:58:53 +00:00
|
|
|
const useHasHydrated = () => {
|
|
|
|
const [hasHydrated, setHasHydrated] = useState<boolean>(false);
|
|
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
setHasHydrated(true);
|
|
|
|
}, []);
|
|
|
|
|
|
|
|
return hasHydrated;
|
|
|
|
};
|
|
|
|
|
2023-05-14 15:25:22 +00:00
|
|
|
const loadAsyncGoogleFont = () => {
|
|
|
|
const linkEl = document.createElement("link");
|
2023-06-14 17:48:56 +00:00
|
|
|
const proxyFontUrl = "/google-fonts";
|
|
|
|
const remoteFontUrl = "https://fonts.googleapis.com";
|
|
|
|
const googleFontUrl =
|
|
|
|
getClientConfig()?.buildMode === "export" ? remoteFontUrl : proxyFontUrl;
|
2023-05-14 15:25:22 +00:00
|
|
|
linkEl.rel = "stylesheet";
|
|
|
|
linkEl.href =
|
2023-09-19 15:26:52 +00:00
|
|
|
googleFontUrl +
|
|
|
|
"/css2?family=" +
|
|
|
|
encodeURIComponent("Noto Sans:wght@300;400;700;900") +
|
|
|
|
"&display=swap";
|
2023-05-14 15:25:22 +00:00
|
|
|
document.head.appendChild(linkEl);
|
|
|
|
};
|
|
|
|
|
2023-04-23 17:15:44 +00:00
|
|
|
function Screen() {
|
2023-04-21 16:12:07 +00:00
|
|
|
const config = useAppConfig();
|
2023-04-20 17:12:39 +00:00
|
|
|
const location = useLocation();
|
|
|
|
const isHome = location.pathname === Path.Home;
|
2023-06-06 18:18:24 +00:00
|
|
|
const isAuth = location.pathname === Path.Auth;
|
2023-04-23 17:15:44 +00:00
|
|
|
const isMobileScreen = useMobileScreen();
|
2023-09-19 15:26:52 +00:00
|
|
|
const shouldTightBorder =
|
2023-10-09 10:50:10 +00:00
|
|
|
config.tightBorder && !isMobileScreen && getClientConfig()?.isApp;
|
2023-04-10 18:56:48 +00:00
|
|
|
|
2023-05-14 15:25:22 +00:00
|
|
|
useEffect(() => {
|
|
|
|
loadAsyncGoogleFont();
|
|
|
|
}, []);
|
|
|
|
|
2023-04-20 17:12:39 +00:00
|
|
|
return (
|
2023-04-23 17:15:44 +00:00
|
|
|
<div
|
|
|
|
className={
|
|
|
|
styles.container +
|
2023-09-19 15:26:52 +00:00
|
|
|
` ${shouldTightBorder ? styles["tight-container"] : styles.container} ${
|
|
|
|
getLang() === "ar" ? styles["rtl-screen"] : ""
|
|
|
|
}`
|
2023-04-23 17:15:44 +00:00
|
|
|
}
|
|
|
|
>
|
2023-06-06 18:18:24 +00:00
|
|
|
{isAuth ? (
|
|
|
|
<>
|
|
|
|
<AuthPage />
|
|
|
|
</>
|
|
|
|
) : (
|
|
|
|
<>
|
|
|
|
<SideBar className={isHome ? styles["sidebar-show"] : ""} />
|
|
|
|
|
|
|
|
<div className={styles["window-content"]} id={SlotID.AppBody}>
|
|
|
|
<Routes>
|
|
|
|
<Route path={Path.Home} element={<Chat />} />
|
|
|
|
<Route path={Path.NewChat} element={<NewChat />} />
|
|
|
|
<Route path={Path.Masks} element={<MaskPage />} />
|
|
|
|
<Route path={Path.Chat} element={<Chat />} />
|
|
|
|
<Route path={Path.Settings} element={<Settings />} />
|
|
|
|
</Routes>
|
|
|
|
</div>
|
|
|
|
</>
|
|
|
|
)}
|
2023-04-10 18:56:48 +00:00
|
|
|
</div>
|
2023-03-09 17:01:40 +00:00
|
|
|
);
|
|
|
|
}
|
2023-04-03 05:29:37 +00:00
|
|
|
|
2023-07-04 15:16:24 +00:00
|
|
|
export function useLoadData() {
|
|
|
|
const config = useAppConfig();
|
|
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
(async () => {
|
|
|
|
const models = await api.llm.models();
|
|
|
|
config.mergeModels(models);
|
|
|
|
})();
|
|
|
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
|
|
}, []);
|
|
|
|
}
|
|
|
|
|
2023-04-03 05:29:37 +00:00
|
|
|
export function Home() {
|
2023-04-20 18:52:53 +00:00
|
|
|
useSwitchTheme();
|
2023-07-04 15:16:24 +00:00
|
|
|
useLoadData();
|
2023-08-14 13:55:18 +00:00
|
|
|
useHtmlLang();
|
2023-04-20 17:12:39 +00:00
|
|
|
|
2023-06-13 16:37:42 +00:00
|
|
|
useEffect(() => {
|
|
|
|
console.log("[Config] got config from build time", getClientConfig());
|
2023-07-10 15:19:43 +00:00
|
|
|
useAccessStore.getState().fetch();
|
2023-06-13 16:37:42 +00:00
|
|
|
}, []);
|
|
|
|
|
2023-04-20 17:12:39 +00:00
|
|
|
if (!useHasHydrated()) {
|
|
|
|
return <Loading />;
|
|
|
|
}
|
|
|
|
|
2023-04-03 05:29:37 +00:00
|
|
|
return (
|
|
|
|
<ErrorBoundary>
|
2023-04-23 17:15:44 +00:00
|
|
|
<Router>
|
|
|
|
<Screen />
|
|
|
|
</Router>
|
2023-04-03 05:29:37 +00:00
|
|
|
</ErrorBoundary>
|
|
|
|
);
|
|
|
|
}
|