/**
* App — routes, the shell and the theme bootstrap.
*
* The daemon serves the console and the API from one origin, so a real
* BrowserRouter works as long as the Go handler falls back to index.html (it
* does). `useThemeInit` runs the stored theme onto `` before the first
* paint; `ThemeToggle` inside AppShell keeps it in sync afterwards.
*/
import { useEffect } from 'react'
import { BrowserRouter, Route, Routes } from 'react-router-dom'
import { ToastProvider } from './components/ui'
import { AppShell } from './components/layout'
import Blocklists from './pages/Blocklists.tsx'
import Cache from './pages/Cache.tsx'
import Clients from './pages/Clients.tsx'
import Dashboard from './pages/Dashboard.tsx'
import Domains from './pages/Domains.tsx'
import Login from './pages/Login.tsx'
import Logs from './pages/Logs.tsx'
import LocalZones from './pages/LocalZones.tsx'
import NotFound from './pages/NotFound.tsx'
import Settings from './pages/Settings.tsx'
import Upstreams from './pages/Upstreams.tsx'
import Zones from './pages/Zones.tsx'
const THEME_KEY = 'fancydns.theme'
/** Applies the stored theme to `` before anything paints. */
function useThemeInit(): void {
useEffect(() => {
if (typeof document === 'undefined') return
if (document.documentElement.dataset.theme !== undefined) return
let stored: string | null = null
try {
stored = localStorage.getItem(THEME_KEY)
} catch {
// Storage disabled: fall back to the system preference.
stored = null
}
if (stored === 'light' || stored === 'dark') {
document.documentElement.dataset.theme = stored
}
}, [])
}
/** Everything that lives inside the shell. */
function AppRoutes() {
return (
} />
} />
} />
} />
} />
} />
} />
} />
} />
} />
} />
)
}
export default function App() {
useThemeInit()
return (
{/* Bare: no shell, no header, no nav. */}
} />
} />
}
/>
)
}