import { lazy, Suspense } from 'react'; import { HashRouter, Navigate, Outlet, Route, Routes } from 'react-router-dom'; import { AppShell } from './components/AppShell'; import { CrashToast } from './components/CrashToast'; import { ErrorBoundary } from './components/ErrorBoundary'; import { RemoteRevokedScreen } from './components/RemoteRevokedScreen'; import { SpinnerIcon } from './components/icons'; import { UpdateToast } from './components/UpdateToast'; import { RequireAdmin, RequireAuth, RequireDevice } from './components/guards'; import { AuthProvider } from './context/AuthContext'; import { CallProvider } from './context/CallContext'; import { ConversationsProvider } from './context/ConversationsContext'; import { FriendshipsProvider } from './context/FriendshipsContext'; import { ThemeProvider } from './context/ThemeContext'; import { AuthPage } from './pages/AuthPage'; import { ChatsEmptyState, ChatsPage } from './pages/ChatsPage'; import { ConversationPage } from './pages/ConversationPage'; // Routes rarely visited on first render are pulled out of the initial bundle. // AuthPage stays eager because it's the first screen unauthenticated users // see; ChatsPage + ConversationPage stay eager because every authenticated // session renders them immediately. const AdminPage = lazy(() => import('./pages/AdminPage').then((m) => ({ default: m.AdminPage }))); const AuthCallbackPage = lazy(() => import('./pages/AuthCallbackPage').then((m) => ({ default: m.AuthCallbackPage })), ); const DevicePage = lazy(() => import('./pages/DevicePage').then((m) => ({ default: m.DevicePage }))); const FriendsPage = lazy(() => import('./pages/FriendsPage').then((m) => ({ default: m.FriendsPage })), ); const SettingsPage = lazy(() => import('./pages/SettingsPage').then((m) => ({ default: m.SettingsPage })), ); const ChangelogPage = lazy(() => import('./pages/ChangelogPage').then((m) => ({ default: m.ChangelogPage })), ); function RouteSuspense({ children }: { children: React.ReactNode }) { return ( } > {children} ); } // Isolates each top-level route so a crash in one page doesn't take the whole // shell down. The boundary auto-retries via `ErrorBoundary`'s backoff schedule. function RouteBoundary({ scope }: { scope: string }) { return ( ); } export function App() { return ( }> } /> } /> }> }> } /> }> }> } /> }> }> } /> } /> }> } /> }> } /> }> } /> }> }> } /> } /> ); }