import { useEffect, useMemo, useState } from "react"; import { Alert, Box, CssBaseline, LinearProgress, Snackbar, ThemeProvider, useMediaQuery } from "@mui/material"; import { Navigate, Route, Routes } from "react-router-dom"; import AppShell from "./components/AppShell"; import { AuthProvider, useAuth } from "./lib/auth"; import { SettingsProvider, useSettings } from "./lib/settings"; import { buildTheme, type ThemeMode } from "./theme"; import BlockerPage from "./pages/BlockerPage"; import LoginPage from "./pages/LoginPage"; import ReportPage from "./pages/ReportPage"; import SettingsPage from "./pages/SettingsPage"; import TasksPage from "./pages/TasksPage"; import TimerPage from "./pages/TimerPage"; function Shell() { const { settings, loading, error } = useSettings(); const prefersDark = useMediaQuery("(prefers-color-scheme: dark)"); const [toast, setToast] = useState(null); const mode: ThemeMode = useMemo(() => { const preference = settings?.appearance.theme ?? "system"; if (preference === "system") return prefersDark ? "dark" : "light"; return preference; }, [settings?.appearance.theme, prefersDark]); const theme = useMemo( () => buildTheme(mode, settings?.appearance.compact ?? false), [mode, settings?.appearance.compact], ); // Keep the browser chrome in step with the app's surface. useEffect(() => { document.documentElement.dataset.theme = mode; document.body.style.backgroundColor = theme.palette.background.default; }, [mode, theme]); return ( {loading && } {error && ( The backend is not reachable ({error}). Start it with{" "} docker compose up or check the API token in Settings. )} } /> } /> } /> } /> } /> } /> setToast(null)} message={toast ?? ""} anchorOrigin={{ vertical: "bottom", horizontal: "center" }} /> ); } function Gate() { const { me, loading } = useAuth(); const prefersDark = useMediaQuery("(prefers-color-scheme: dark)"); if (loading || !me) { // The paper theme, so the blank moment before `/api/auth/me` answers // doesn't flash a default MUI white. const theme = buildTheme(prefersDark ? "dark" : "light", false); return ( ); } if (!me.authenticated) { const theme = buildTheme(prefersDark ? "dark" : "light", false); return ( ); } return ( ); } export default function App() { return ( ); }