"use client"; require("../polyfill"); import { useState, useEffect } from "react"; import styles from "./home.module.scss"; import BotIcon from "../icons/bot.svg"; import LoadingIcon from "../icons/three-dots.svg"; import { getCSSVar, useMobileScreen } from "../utils"; import dynamic from "next/dynamic"; import { Path, SlotID } from "../constant"; import { ErrorBoundary } from "./error"; import { getISOLang, getLang } from "../locales"; import { HashRouter as Router, Routes, Route, useLocation, } from "react-router-dom"; import { SideBar } from "./sidebar"; import { useAppConfig } from "../store/config"; import { AuthPage } from "./auth"; import { getClientConfig } from "../config/client"; import { type ClientApi, getClientApi } from "../client/api"; import { useAccessStore } from "../store"; // Loading组件用于显示加载状态 export function Loading(props: { noLogo?: boolean }) { return ( // 使用styles["loading-content"]类名来应用样式,"no-dark"类用于防止暗色主题影响
{/* 如果noLogo属性为false,则显示BotIcon */} {!props.noLogo && } {/* 显示LoadingIcon表示正在加载 */}
); } const Artifacts = dynamic(async () => (await import("./artifacts")).Artifacts, { loading: () => , }); const Settings = dynamic(async () => (await import("./settings")).Settings, { loading: () => , }); const Chat = dynamic(async () => (await import("./chat")).Chat, { loading: () => , }); const NewChat = dynamic(async () => (await import("./new-chat")).NewChat, { loading: () => , }); const MaskPage = dynamic(async () => (await import("./mask")).MaskPage, { loading: () => , }); const Sd = dynamic(async () => (await import("./sd")).Sd, { loading: () => , }); export function useSwitchTheme() { const config = useAppConfig(); useEffect(() => { document.body.classList.remove("light"); document.body.classList.remove("dark"); if (config.theme === "dark") { document.body.classList.add("dark"); } else if (config.theme === "light") { document.body.classList.add("light"); } const metaDescriptionDark = document.querySelector( 'meta[name="theme-color"][media*="dark"]', ); const metaDescriptionLight = document.querySelector( 'meta[name="theme-color"][media*="light"]', ); if (config.theme === "auto") { metaDescriptionDark?.setAttribute("content", "#151515"); metaDescriptionLight?.setAttribute("content", "#fafafa"); } else { const themeColor = getCSSVar("--theme-color"); metaDescriptionDark?.setAttribute("content", themeColor); metaDescriptionLight?.setAttribute("content", themeColor); } }, [config.theme]); } function useHtmlLang() { useEffect(() => { const lang = getISOLang(); const htmlLang = document.documentElement.lang; if (lang !== htmlLang) { document.documentElement.lang = lang; } }, []); } // 定义一个自定义Hook:useHasHydrated const useHasHydrated = () => { // 使用useState初始化hasHydrated状态为false const [hasHydrated, setHasHydrated] = useState(false); // 使用useEffect在组件挂载后将hasHydrated设置为true useEffect(() => { setHasHydrated(true); }, []); // 返回hasHydrated的当前值 return hasHydrated; }; const loadAsyncGoogleFont = () => { const linkEl = document.createElement("link"); const proxyFontUrl = "/google-fonts"; const remoteFontUrl = "https://fonts.googleapis.com"; const googleFontUrl = getClientConfig()?.buildMode === "export" ? remoteFontUrl : proxyFontUrl; linkEl.rel = "stylesheet"; linkEl.href = googleFontUrl + "/css2?family=" + encodeURIComponent("Noto Sans:wght@300;400;700;900") + "&display=swap"; document.head.appendChild(linkEl); }; export function WindowContent(props: { children: React.ReactNode }) { return (
{props?.children}
); } // Screen 组件:负责渲染应用的主要内容 function Screen() { // 获取应用配置 const config = useAppConfig(); // 获取当前路由位置 const location = useLocation(); // 判断当前路径是否为特定页面 const isArtifact = location.pathname.includes(Path.Artifacts); const isHome = location.pathname === Path.Home; const isAuth = location.pathname === Path.Auth; const isSd = location.pathname === Path.Sd; const isSdNew = location.pathname === Path.SdNew; // 检查是否为移动屏幕 const isMobileScreen = useMobileScreen(); // 决定是否使用紧凑边框 const shouldTightBorder = getClientConfig()?.isApp || (config.tightBorder && !isMobileScreen); // 加载Google字体 useEffect(() => { loadAsyncGoogleFont(); }, []); // 如果是Artifacts页面,渲染特定路由 if (isArtifact) { return ( } /> ); } // 渲染主要内容的函数 const renderContent = () => { if (isAuth) return ; if (isSd) return ; if (isSdNew) return ; return ( <> {/* 侧边栏 */} {/* 主区域 */} } /> } /> } /> } /> } /> ); }; // 返回最终的渲染结果 return (
{renderContent()}
); } // 定义一个自定义Hook:useLoadData export function useLoadData() { // 获取应用配置 const config = useAppConfig(); // 根据配置中的提供商名称获取客户端API const api: ClientApi = getClientApi(config.modelConfig.providerName); // 使用useEffect钩子在组件挂载时加载数据 useEffect(() => { // 定义一个异步函数来获取模型 (async () => { // 从API获取模型列表 const models = await api.llm.models(); // 将获取到的模型合并到配置中 config.mergeModels(models); })(); // eslint-disable-next-line react-hooks/exhaustive-deps }, []); } export function Home() { // 切换主题 useSwitchTheme(); // 加载数据 useLoadData(); // 设置HTML语言 useHtmlLang(); useEffect(() => { // 从构建时获取配置并打印日志 console.log("[Config] got config from build time", getClientConfig()); // 获取访问权限 useAccessStore.getState().fetch(); }, []); // 如果组件还未水合,显示加载中 if (!useHasHydrated()) { return ; } // 渲染主要内容 return ( ); }