import { Component, useEffect, useState } from "react"; import MainShell from "./components/MainShell"; import AnnotationPage from "./pages/AnnotationPage"; import SecondaryWindow from "./windows/SecondaryWindow"; function AppErrorFallback({ error }) { return (
应用渲染失败
href: {window.location.href}
hash: {window.location.hash}
error: {String(error?.message || error)}
); } class AppErrorBoundary extends Component { state = { error: null }; componentDidCatch(error) { this.setState({ error }); } render() { if (this.state.error) { return ; } return this.props.children; } } function App() { const [theme, setTheme] = useState(() => localStorage.getItem("theme") || "light"); const [activeTab, setActiveTab] = useState("clone"); const [activeKnowledge, setActiveKnowledge] = useState("全部"); const [activeSkill, setActiveSkill] = useState("全部"); const [settingSection, setSettingSection] = useState("基础配置"); const [route, setRoute] = useState(() => window.location.hash.replace("#", "") || "/"); useEffect(() => { document.documentElement.dataset.theme = theme; localStorage.setItem("theme", theme); }, [theme]); useEffect(() => { const onStorage = (event) => { if (event.key === "theme" && event.newValue) { setTheme(event.newValue); } }; window.addEventListener("storage", onStorage); return () => window.removeEventListener("storage", onStorage); }, []); useEffect(() => { const timers = new WeakMap(); const revealScrollbar = (event) => { const target = event.target instanceof Element ? event.target : document.scrollingElement; if (!target) return; target.classList.add("scrollbar-active"); window.clearTimeout(timers.get(target)); timers.set(target, window.setTimeout(() => target.classList.remove("scrollbar-active"), 700)); }; document.addEventListener("scroll", revealScrollbar, true); return () => document.removeEventListener("scroll", revealScrollbar, true); }, []); useEffect(() => { const onHashChange = () => setRoute(window.location.hash.replace("#", "") || "/"); window.addEventListener("hashchange", onHashChange); return () => window.removeEventListener("hashchange", onHashChange); }, []); const isWindowRoute = route.startsWith("/window/"); const isAnnotationRoute = route === "/annotate"; return (
{isAnnotationRoute ? ( ) : isWindowRoute ? ( ) : ( )}
); } export default App;