import { lazy, Suspense, useEffect, useState } from "react"; import { connectEvents, get, setUnauthorizedHandler } from "./api"; import { useT } from "./i18n"; import { navigate, useRoute } from "./router"; import { applyEvent, loadSessions, resync, setState } from "./store"; import type { Info } from "./types"; import { Sidebar } from "./components/Sidebar"; import { Login } from "./components/Login"; import { ChatView } from "./components/ChatView"; import { NewSession } from "./components/NewSession"; import { Settings } from "./components/Settings"; import { Stats } from "./components/Stats"; import { Images } from "./components/Images"; import { Spinner, useTitleActivity } from "./components/Activity"; // The file manager (editor, git) is loaded on demand to keep the chat small. const Files = lazy(() => import("./components/Files").then((m) => ({ default: m.Files }))); export function App() { const t = useT(); const route = useRoute(); const [info, setInfo] = useState(); const [error, setError] = useState(); const [menuOpen, setMenuOpen] = useState(false); useTitleActivity(); const refresh = async () => { try { const i = await get("/info"); setState(() => ({ me: i.user })); if (i.user) await loadSessions(); setInfo(i); } catch (e: any) { setError(e.message); } }; useEffect(() => { setUnauthorizedHandler(() => setInfo((i) => (i ? { ...i, user: null } : i))); void refresh(); }, []); const signedIn = !!info?.user; useEffect(() => { if (!signedIn) return; return connectEvents({ onEvent: applyEvent, onOpen: () => { setState(() => ({ connected: true })); void resync().catch(() => undefined); }, onClose: () => setState(() => ({ connected: false })), }); }, [signedIn]); // Close the mobile menu on navigation. useEffect(() => setMenuOpen(false), [route.join("/")]); if (error) return
{error}
; if (!info) return
{t("common.loading")}
; if (!info.user) return ; const [section, arg] = route; let content; if (section === "s" && arg) content = setMenuOpen(true)} />; else if (section === "settings") content = setMenuOpen(true)} />; else if (section === "stats") content = setMenuOpen(true)} />; else if (section === "images") content = setMenuOpen(true)} />; else if (section === "files") content = ( }> setMenuOpen(true)} /> ); else content = setMenuOpen(true)} onCreated={(id) => navigate(`/s/${id}`)} />; return (
{menuOpen &&
setMenuOpen(false)} />}
{content}
); }