返回 DeepSeek-Reasonix
AppOverlayHost.tsx
根目录 / desktop / frontend / src / app-shell / AppOverlayHost.tsx
1 import { lazy, Suspense, type ComponentProps } from "react";
2 import { RemoteHostKeyDialog } from "../components/RemoteHostKeyDialog";
3 import { RemoteSecretDialog } from "../components/RemoteSecretDialog";
4 import { ShortcutsCheatsheet } from "../components/ShortcutsCheatsheet";
5 import { StartupSplash } from "../components/StartupSplash";
6 import { ManagementSurface } from "../components/ManagementSurface";
7
8 const HistoryPanel = lazy(() => import("../components/HistoryPanel").then((module) => ({ default: module.HistoryPanel })));
9 const SessionRecoveryVersionsHost = lazy(() => import("../components/SessionRecoveryVersionsHost").then((module) => ({ default: module.SessionRecoveryVersionsHost })));
10 const loadSettingsPage = () => import("../components/SettingsPanelEntry").then((module) => ({ default: module.SettingsPanel }));
11 const loadTrashPage = () => import("../components/TrashPage").then((module) => ({ default: module.TrashPage }));
12 const loadAutomationPage = () => import("../custom/features/heartbeat/HeartbeatPanel").then((module) => ({ default: module.HeartbeatView }));
13 type LoadedProps<T> = T extends () => Promise<{ default: React.ComponentType<infer Props> }> ? Props : never;
14 const CommandPalette = lazy(() => import("../components/CommandPalette").then((module) => ({ default: module.CommandPalette })));
15 const WorktreeMergeModal = lazy(() => import("../components/WorktreeMergeModal").then((module) => ({ default: module.WorktreeMergeModal })));
16
17 type Region<Props, ViewKey extends keyof Props> = {
18 view: Pick<Props, ViewKey>;
19 commands: Omit<Props, ViewKey>;
20 };
21
22 export type AppOverlayHostProps = {
23 history?: Region<ComponentProps<typeof HistoryPanel>, "kind" | "sessions" | "running">;
24 recovery: Region<ComponentProps<typeof SessionRecoveryVersionsHost>, "sessions">;
25 settings?: Region<LoadedProps<typeof loadSettingsPage>, "initialTab" | "initialFocus" | "agentRunning" | "desktopPlatform" | "activeWorkspaceKey">;
26 trash?: Region<LoadedProps<typeof loadTrashPage>, "active">;
27 automation?: Region<LoadedProps<typeof loadAutomationPage>, "active">;
28 palette?: Region<ComponentProps<typeof CommandPalette>, "open" | "items" | "placeholder" | "emptyText">;
29 shortcuts: Region<ComponentProps<typeof ShortcutsCheatsheet>, "open" | "platform" | "t">;
30 startup?: Region<ComponentProps<typeof StartupSplash>, "hold">;
31 worktree?: Region<ComponentProps<typeof WorktreeMergeModal>, "tabId" | "isOpen">;
32 };
33
34 /** Presentation-only overlay region. Async ownership stays in feature owners. */
35 export function AppOverlayHost({ history, recovery, settings, trash, automation, palette, shortcuts, startup, worktree }: AppOverlayHostProps) {
36 return (
37 <>
38 {history && <Suspense fallback={null}><HistoryPanel {...history.view} {...history.commands} /></Suspense>}
39 <Suspense fallback={null}><SessionRecoveryVersionsHost {...recovery.view} {...recovery.commands} /></Suspense>
40 {trash && <ManagementSurface loader={loadTrashPage} active={trash.view.active} onBack={trash.commands.onBack}
41 surfaceProps={{ ...trash.view, ...trash.commands }} />}
42 {automation && <ManagementSurface loader={loadAutomationPage} active={automation.view.active !== false} onBack={automation.commands.onBack!}
43 surfaceProps={{ ...automation.view, ...automation.commands }} />}
44 {settings && <ManagementSurface loader={loadSettingsPage} active onBack={settings.commands.onClose}
45 surfaceProps={{ ...settings.view, ...settings.commands }} />}
46 <RemoteHostKeyDialog />
47 <RemoteSecretDialog />
48 {palette && <Suspense fallback={null}><CommandPalette {...palette.view} {...palette.commands} /></Suspense>}
49 <ShortcutsCheatsheet {...shortcuts.view} {...shortcuts.commands} />
50 {startup && <StartupSplash {...startup.view} {...startup.commands} />}
51 {worktree && <Suspense fallback={null}><WorktreeMergeModal {...worktree.view} {...worktree.commands} /></Suspense>}
52 </>
53 );
54 }
55
55 lines Plain Text