overhaul settings: split into routed sub-tabs, add server logs, changelog, reusable setting components

- Rename Server tab to Settings with horizontal sub-tab navigation (General, Generation, GPU, Logs, Changelog)
- All sub-tabs are proper routes under /settings/* with /server redirect for backwards compat
- General: connection settings, link cards (docs + discord), API reference card, app updates
- Generation: auto-chunking, crossfade, normalize, autoplay as SettingRow components
- GPU: info card with platform-aware icons (Apple logo for MPS), CUDA management, explainer text
- Logs: real-time server log viewer piped from Tauri sidecar via event system (Tauri-only)
- Changelog: parsed from CHANGELOG.md at build time via Vite virtual module plugin
- New reusable SettingRow/SettingSection components for consistent settings layout
- New Toggle (switch) UI component replacing checkboxes in settings
- Toast viewport now offsets when audio player is open
- Sidebar stays active on settings sub-routes (fuzzy matching)
This commit is contained in:
James Pine
2026-03-16 09:31:14 -07:00
parent e0a798dc0d
commit 2c63dfff25
30 changed files with 1879 additions and 60 deletions
+64 -6
View File
@@ -1,10 +1,21 @@
import { createRootRoute, createRoute, createRouter, Outlet } from '@tanstack/react-router';
import {
createRootRoute,
createRoute,
createRouter,
Outlet,
redirect,
} from '@tanstack/react-router';
import { AppFrame } from '@/components/AppFrame/AppFrame';
import { AudioTab } from '@/components/AudioTab/AudioTab';
import { EffectsTab } from '@/components/EffectsTab/EffectsTab';
import { MainEditor } from '@/components/MainEditor/MainEditor';
import { ModelsTab } from '@/components/ModelsTab/ModelsTab';
import { ServerTab } from '@/components/ServerTab/ServerTab';
import { ChangelogPage } from '@/components/ServerTab/ChangelogPage';
import { GeneralPage } from '@/components/ServerTab/GeneralPage';
import { GenerationPage } from '@/components/ServerTab/GenerationPage';
import { GpuPage } from '@/components/ServerTab/GpuPage';
import { LogsPage } from '@/components/ServerTab/LogsPage';
import { SettingsLayout } from '@/components/ServerTab/ServerTab';
import { Sidebar } from '@/components/Sidebar';
import { StoriesTab } from '@/components/StoriesTab/StoriesTab';
import { Toaster } from '@/components/ui/toaster';
@@ -120,11 +131,51 @@ const modelsRoute = createRoute({
component: ModelsTab,
});
// Server route
const serverRoute = createRoute({
// Settings layout route (parent for sub-tabs)
const settingsRoute = createRoute({
getParentRoute: () => rootRoute,
path: '/settings',
component: SettingsLayout,
});
// Settings sub-routes
const settingsGeneralRoute = createRoute({
getParentRoute: () => settingsRoute,
path: '/',
component: GeneralPage,
});
const settingsGenerationRoute = createRoute({
getParentRoute: () => settingsRoute,
path: '/generation',
component: GenerationPage,
});
const settingsGpuRoute = createRoute({
getParentRoute: () => settingsRoute,
path: '/gpu',
component: GpuPage,
});
const settingsChangelogRoute = createRoute({
getParentRoute: () => settingsRoute,
path: '/changelog',
component: ChangelogPage,
});
const settingsLogsRoute = createRoute({
getParentRoute: () => settingsRoute,
path: '/logs',
component: LogsPage,
});
// Redirect old /server path to /settings
const serverRedirectRoute = createRoute({
getParentRoute: () => rootRoute,
path: '/server',
component: ServerTab,
beforeLoad: () => {
throw redirect({ to: '/settings' });
},
});
// Route tree
@@ -135,7 +186,14 @@ const routeTree = rootRoute.addChildren([
audioRoute,
effectsRoute,
modelsRoute,
serverRoute,
settingsRoute.addChildren([
settingsGeneralRoute,
settingsGenerationRoute,
settingsGpuRoute,
settingsLogsRoute,
settingsChangelogRoute,
]),
serverRedirectRoute,
]);
// Create router