返回 DeepSeek-Reasonix
dockRegionBuilders.ts
根目录 / desktop / frontend / src / app-shell / dockRegionBuilders.ts
1 import { workspacePanelAriaMinWidth } from "../lib/workspaceLayout";
2 import type { Translator } from "../lib/i18n";
3 import type { Meta, RemoteHostView, RemoteConnectionStatus, WireCompletionSummary } from "../lib/types";
4 import type { projectConversation } from "../app-runtime/conversationProjection";
5 import type { useShellGeometry } from "../app-runtime/useShellGeometry";
6 import type { useWorkspacePanelCommands } from "../app-runtime/useWorkspacePanelCommands";
7 import type { useComposerInsertCommands } from "../app-runtime/useComposerInsertCommands";
8 import type { WorkspaceVerificationRevealRequest } from "../components/WorkspacePanel";
9 import type { WorkspaceDockRegionProps } from "./WorkspaceDockRegion";
10 import type { AppBottomRegionsProps } from "./AppBottomRegions";
11 import type { RightDockMode } from "../store/layout";
12 import { defaultRightDockTreeWidth, TERMINAL_DEFAULT_HEIGHT, TERMINAL_MIN_HEIGHT } from "../store/layout";
13
14 type ShellGeometry = ReturnType<typeof useShellGeometry>;
15 type WorkspacePanelApi = ReturnType<typeof useWorkspacePanelCommands>;
16 type InsertCommands = ReturnType<typeof useComposerInsertCommands>;
17 type ConversationView = ReturnType<typeof projectConversation>;
18 type StatusBarProps = NonNullable<AppBottomRegionsProps["status"]>;
19
20 /** Pure prop assembly for the dock and bottom regions; all ownership and
21 * geometry stays in the caller's hooks, only the object literals moved. */
22
23 export function buildWorkspaceDockProps(input: {
24 surface: { renderable: boolean; overlay: boolean; gridOpen: boolean };
25 showContext: boolean;
26 remote: boolean;
27 t: Translator;
28 context: ConversationView["context"];
29 sessionTurns: number;
30 contextRefreshKey: number;
31 workspaceKey: string;
32 workspaceScopeKey: string;
33 mode: RightDockMode;
34 meta: Meta | null | undefined;
35 tabId: string | undefined;
36 completionSummary: WireCompletionSummary | undefined;
37 turnStartAt: number;
38 layout: { treeWidth: number; previewWidth: number; maximized: boolean };
39 geometry: ShellGeometry;
40 panels: WorkspacePanelApi;
41 inserts: InsertCommands;
42 verification: { verificationRevealRequest: WorkspaceVerificationRevealRequest | null; closeTurnResult?: () => void };
43 onFileTreeRefresh: () => void;
44 onSessionRevertCommitted: WorkspaceDockRegionProps["workspace"]["onSessionRevertCommitted"];
45 onOpenInTerminal: WorkspaceDockRegionProps["workspace"]["onOpenInTerminal"];
46 }): WorkspaceDockRegionProps {
47 const { surface, geometry, panels } = input;
48 const workspacePanelResetWidth = defaultRightDockTreeWidth();
49 const workspacePanelResizeMinWidth = workspacePanelAriaMinWidth(geometry.workspacePanelMinWidth, geometry.workspacePanelRenderWidth);
50 return {
51 visible: surface.renderable,
52 overlay: surface.overlay,
53 mode: input.mode,
54 showContext: input.showContext,
55 t: input.t,
56 onPickEntry: panels.openDockEntry,
57 remote: { onClose: panels.closeWorkspacePanel },
58 context: {
59 ...input.context, sessionTurns: input.sessionTurns,
60 refreshKey: input.contextRefreshKey,
61 },
62 workspaceKey: input.workspaceKey,
63 workspace: {
64 open: surface.renderable, tabId: input.tabId, cwd: input.meta?.cwd,
65 workspaceScopeKey: input.workspaceScopeKey, workspaceMemoryKey: input.workspaceKey,
66 dockTreeWidth: input.layout.treeWidth, dockPreviewWidth: input.layout.previewWidth,
67 onRestoreDockWidths: panels.restoreWorkspaceDockWidths, maximized: input.layout.maximized,
68 panelWidth: geometry.workspacePanelRenderWidth, onClose: panels.closeWorkspacePanel,
69 onToggleMaximized: panels.toggleWorkspaceMaximized,
70 onPreviewModeChange: panels.handleWorkspacePreviewModeChange, onAddToChat: input.inserts.addWorkspaceTextToComposer,
71 onAddCodeToChat: input.inserts.addWorkspaceCodeToComposer, onRequestPanelWidth: geometry.ensureWorkspacePanelWidth,
72 onFileTreeRefresh: input.onFileTreeRefresh, onSessionRevertCommitted: input.onSessionRevertCommitted,
73 onOpenInTerminal: input.onOpenInTerminal,
74 initialViewMode: input.mode === "changed" ? "changed" : "files",
75 completionSummary: input.completionSummary, turnStartAt: input.turnStartAt,
76 sessionPath: input.meta?.sessionPath, onDismissTurnResult: input.verification.closeTurnResult,
77 verificationRevealRequest: input.verification.verificationRevealRequest,
78 showViewTabs: false,
79 },
80 resizer: surface.gridOpen ? {
81 min: workspacePanelResizeMinWidth,
82 max: Math.max(geometry.workspacePanelAvailableWidth, geometry.workspacePanelRenderWidth),
83 value: geometry.workspacePanelRenderWidth,
84 onPointerDown: geometry.startWorkspacePanelResize,
85 onKeyDown: geometry.resizeWorkspacePanelWithKeyboard,
86 onReset: () => geometry.setSavedWorkspacePanelWidth(workspacePanelResetWidth),
87 } : undefined,
88 };
89 }
90
91 export function buildBottomRegionsProps(input: {
92 t: Translator;
93 chatSurfaceVisible: boolean;
94 surfaceOpen: boolean;
95 contentVisible: boolean;
96 remote: boolean;
97 readOnly: boolean;
98 tabId: string | undefined;
99 meta: Meta | null | undefined;
100 fitEnabled: boolean;
101 liveTerminalHeight: number | null;
102 geometry: ShellGeometry;
103 terminal: {
104 onClose: () => void;
105 onAddOutput: (sessionId: string) => void;
106 onAddToChat: (text: string) => void;
107 };
108 status?: {
109 base: ConversationView["status"];
110 rewindCommitting: boolean;
111 sessionTurns: number;
112 labelStyle: StatusBarProps["labelStyle"];
113 items: StatusBarProps["items"];
114 extensionStatuses: StatusBarProps["extensionStatuses"];
115 remoteHosts: RemoteHostView[];
116 remoteStatuses: Record<string, RemoteConnectionStatus>;
117 onCancelJob: StatusBarProps["onCancelJob"];
118 onCancelRuntimeJob: StatusBarProps["onCancelRuntimeJob"];
119 onRevealRuntime: StatusBarProps["onRevealRuntime"];
120 onConnectRemote: StatusBarProps["onConnectRemote"];
121 onDisconnectRemote: StatusBarProps["onDisconnectRemote"];
122 onManageRemote: StatusBarProps["onManageRemote"];
123 onOpenRemote: StatusBarProps["onOpenRemote"];
124 onOpenRemoteWorkspace: StatusBarProps["onOpenRemoteWorkspace"];
125 };
126 }): AppBottomRegionsProps {
127 const { geometry, status } = input;
128 return {
129 terminal: {
130 surfaceVisible: input.chatSurfaceVisible,
131 open: input.surfaceOpen, contentVisible: input.contentVisible,
132 remoteSurface: input.remote, t: input.t,
133 panel: {
134 tabId: input.tabId ?? "", cwd: input.meta?.cwd, readOnly: input.readOnly,
135 open: input.surfaceOpen, fitEnabled: input.fitEnabled,
136 onClose: input.terminal.onClose,
137 onAddOutput: input.terminal.onAddOutput,
138 onAddToChat: input.terminal.onAddToChat,
139 },
140 resizer: {
141 min: TERMINAL_MIN_HEIGHT, max: geometry.terminalResizeMaxHeight,
142 value: input.liveTerminalHeight ?? geometry.terminalRenderHeight,
143 onPointerDown: geometry.startTerminalResize, onKeyDown: geometry.resizeTerminalWithKeyboard,
144 onReset: () => geometry.setSavedTerminalHeight(TERMINAL_DEFAULT_HEIGHT),
145 },
146 },
147 status: status ? {
148 ...status.base,
149 running: status.base.running || (!input.remote && status.rewindCommitting),
150 onCancelJob: status.onCancelJob,
151 onCancelRuntimeJob: status.onCancelRuntimeJob,
152 onRevealRuntime: status.onRevealRuntime,
153 sessionTurns: status.sessionTurns,
154 labelStyle: status.labelStyle,
155 items: status.items,
156 extensionStatuses: status.extensionStatuses,
157 onConnectRemote: status.onConnectRemote,
158 onDisconnectRemote: status.onDisconnectRemote,
159 onManageRemote: status.onManageRemote,
160 onOpenRemote: status.onOpenRemote,
161 onOpenRemoteWorkspace: status.onOpenRemoteWorkspace,
162 remoteHosts: status.remoteHosts,
163 remoteStatuses: status.remoteStatuses,
164 } : undefined,
165 };
166 }
167
167 lines TYPESCRIPT