import clsx from 'clsx'; import dynamic from 'next/dynamic'; import { useEffect, useState } from 'react'; import { Route, HashRouter as Router, Routes, useLocation, } from 'react-router-dom'; import { type ClientApi, getClientApi } from '../client/api'; import { getClientConfig } from '../config/client'; import { Path, SlotID } from '../constant'; import BotIcon from '../icons/bot.svg'; import LoadingIcon from '../icons/three-dots.svg'; import { getISOLang, getLang } from '../locales'; import { useAccessStore } from '../store'; import { useAppConfig } from '../store/config'; import { getCSSVar, useMobileScreen } from '../utils'; import { AuthPage } from './auth'; import { ErrorBoundary } from './error'; import styles from './home.module.scss'; import { SideBar } from './sidebar'; 'use client'; require('../polyfill'); export function Loading(props: { noLogo?: boolean }) { return (
{!props.noLogo && }
); } 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 PluginPage = dynamic(async () => (await import('./plugin')).PluginPage, { loading: () => , }); const SearchChat = dynamic( async () => (await import('./search-chat')).SearchChatPage, { 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; } }, []); } function useHasHydrated() { const [hasHydrated, setHasHydrated] = useState(false); useEffect(() => { setHasHydrated(true); }, []); return hasHydrated; } function 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}
); } 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); useEffect(() => { loadAsyncGoogleFont(); }, []); if (isArtifact) { return ( } /> ); } const renderContent = () => { if (isAuth) { return ; } if (isSd) { return ; } if (isSdNew) { return ; } return ( <> } /> } /> } /> } /> } /> } /> } /> ); }; return (
{renderContent()}
); } export function useLoadData() { const config = useAppConfig(); const api: ClientApi = getClientApi(config.modelConfig.providerName); useEffect(() => { (async () => { const models = await api.llm.models(); config.mergeModels(models); })(); // eslint-disable-next-line react-hooks/exhaustive-deps }, []); } export function Home() { useSwitchTheme(); useLoadData(); useHtmlLang(); useEffect(() => { console.log('[Config] got config from build time', getClientConfig()); useAccessStore.getState().fetch(); }, []); if (!useHasHydrated()) { return ; } return ( ); }