返回 oh-my-ppt
App.tsx
根目录 / src / renderer / src / App.tsx
1 import { useEffect, useState } from 'react'
2 import { Routes, Route, Navigate, useLocation, matchPath } from 'react-router-dom'
3 import { Sidebar } from './components/layout/Sidebar'
4 import { WindowControls } from './components/layout/WindowControls'
5 import { HomePage } from './pages/home'
6 import { SessionCreatePage } from './pages/session-create'
7 import { ThinkingDetailPage } from './pages/thinking-detail'
8 import { SessionsPage } from './pages/sessions'
9 import { SessionDetailPage } from './pages/session-detail'
10 import { SessionGeneratingPage } from './pages/session-generating'
11 import { TemplateSessionsGeneratingPage } from './pages/template-sessions-generating'
12 import { SettingsPage } from './pages/settings'
13 import { StylesPage } from './pages/styles'
14 import { FontsPage } from './pages/fonts'
15 import { StyleEditorPage } from './pages/style-editor'
16 import { TemplatesPage } from './pages/templates'
17 import { TokenUsagePage } from './pages/token-usage'
18 import { EditHtmlPage } from './pages/edit-html'
19 import { EditHtmlListPage } from './pages/edit-html-list'
20 import { AppToaster } from './components/AppToaster'
21 import { UpdateAvailableDialog } from './components/UpdateAvailableDialog'
22 import { ScrollArea } from './components/ui/ScrollArea'
23 import { ipc } from './lib/ipc'
24 import type { UpdateAvailablePayload } from '@shared/app-update.js'
25 import { useGenerationNotifications } from './hooks/useGenerationNotifications'
26
27 function App(): React.JSX.Element {
28 const location = useLocation()
29 useGenerationNotifications()
30 const isSessionDetailRoute = Boolean(matchPath('/sessions/:id/*', location.pathname))
31 const isHtmlEditorRoute = Boolean(matchPath('/edit-html/:id/*', location.pathname))
32 const isThinkingRoute = Boolean(matchPath('/thinking', location.pathname))
33 const [availableUpdate, setAvailableUpdate] = useState<UpdateAvailablePayload | null>(null)
34
35 useEffect(() => {
36 const unsubscribe = ipc.onUpdateAvailable((update) => {
37 setAvailableUpdate(update)
38 })
39 return () => {
40 unsubscribe?.()
41 }
42 }, [])
43
44 if (isSessionDetailRoute || isHtmlEditorRoute) {
45 return (
46 <>
47 <div className="flex h-full min-h-0 flex-col overflow-hidden bg-background text-foreground">
48 <Routes>
49 <Route path="/sessions/:id/template-generating" element={<TemplateSessionsGeneratingPage />} />
50 <Route path="/sessions/:id/generating" element={<SessionGeneratingPage />} />
51 <Route path="/sessions/:id" element={<SessionDetailPage />} />
52 <Route path="/edit-html/:id" element={<EditHtmlPage />} />
53 <Route path="*" element={<Navigate to="/" replace />} />
54 </Routes>
55 </div>
56 <UpdateAvailableDialog update={availableUpdate} onClose={() => setAvailableUpdate(null)} />
57 <AppToaster />
58 </>
59 )
60 }
61
62 return (
63 <>
64 <div className="h-full min-h-0 overflow-hidden bg-background text-foreground">
65 <div className="flex h-full min-h-0 flex-col">
66 <div className="app-drag-region app-titlebar flex bg-background/85 backdrop-blur-xl">
67 <WindowControls />
68 </div>
69
70 <div className="flex min-h-0 flex-1">
71 <aside className="hidden min-h-0 w-[240px] shrink-0 flex-col border-r border-border/70 bg-[#f7f0e2]/40 md:flex">
72 <Sidebar />
73 </aside>
74 {isThinkingRoute ? (
75 <div className="min-h-0 flex-1 overflow-hidden">
76 <Routes>
77 <Route path="/thinking" element={<ThinkingDetailPage />} />
78 <Route path="*" element={<Navigate to="/" replace />} />
79 </Routes>
80 </div>
81 ) : (
82 <ScrollArea className="min-h-0 flex-1">
83 <Routes>
84 <Route path="/" element={<HomePage />} />
85 <Route path="/create/session" element={<SessionCreatePage />} />
86 <Route path="/sessions" element={<SessionsPage />} />
87 <Route path="/templates" element={<TemplatesPage />} />
88 <Route path="/styles" element={<StylesPage />} />
89 <Route path="/fonts" element={<FontsPage />} />
90 <Route path="/token-usage" element={<TokenUsagePage />} />
91 <Route path="/styles/new" element={<StyleEditorPage />} />
92 <Route path="/styles/:styleId" element={<StyleEditorPage />} />
93 <Route path="/edit-html" element={<EditHtmlListPage />} />
94 <Route path="/settings" element={<SettingsPage />} />
95 <Route path="*" element={<Navigate to="/" replace />} />
96 </Routes>
97 </ScrollArea>
98 )}
99 </div>
100 </div>
101 </div>
102 <UpdateAvailableDialog update={availableUpdate} onClose={() => setAvailableUpdate(null)} />
103 <AppToaster />
104 </>
105 )
106 }
107
108 export default App
109
109 lines Plain Text