@cerbur/clutch-dsh-worktree 0.1.4 → 0.1.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +89 -24
- package/README.zh.md +81 -23
- package/lib/client/WorktreeContext.d.ts.map +1 -1
- package/lib/client/WorktreeContext.js.map +1 -1
- package/lib/client/WorktreeHeroContext.d.ts +1 -1
- package/lib/client/WorktreeHeroContext.d.ts.map +1 -1
- package/lib/client/WorktreeHeroContext.js +10 -5
- package/lib/client/WorktreeHeroContext.js.map +1 -1
- package/lib/client/WorktreeSurface.d.ts +1 -1
- package/lib/client/WorktreeSurface.d.ts.map +1 -1
- package/lib/client/WorktreeSurface.js +349 -88
- package/lib/client/WorktreeSurface.js.map +1 -1
- package/lib/client/entry.d.ts.map +1 -1
- package/lib/client/entry.js +3 -0
- package/lib/client/entry.js.map +1 -1
- package/lib/client/locales.d.ts +28 -0
- package/lib/client/locales.d.ts.map +1 -1
- package/lib/client/locales.js +30 -2
- package/lib/client/locales.js.map +1 -1
- package/lib/client/virtual-workspace-membership.js +1 -1
- package/lib/client/virtual-workspace-membership.js.map +1 -1
- package/lib/client/worktree-connection.d.ts +2 -0
- package/lib/client/worktree-connection.d.ts.map +1 -1
- package/lib/client/worktree-connection.js +4 -0
- package/lib/client/worktree-connection.js.map +1 -1
- package/lib/client/worktree-context-store.d.ts.map +1 -1
- package/lib/client/worktree-context-store.js +51 -11
- package/lib/client/worktree-context-store.js.map +1 -1
- package/lib/client/worktree-error-copy.d.ts.map +1 -1
- package/lib/client/worktree-error-copy.js +8 -0
- package/lib/client/worktree-error-copy.js.map +1 -1
- package/lib/client/worktree-expand-state.d.ts +33 -0
- package/lib/client/worktree-expand-state.d.ts.map +1 -0
- package/lib/client/worktree-expand-state.js +83 -0
- package/lib/client/worktree-expand-state.js.map +1 -0
- package/lib/client/worktree-session-position.d.ts +2 -0
- package/lib/client/worktree-session-position.d.ts.map +1 -0
- package/lib/client/worktree-session-position.js +11 -0
- package/lib/client/worktree-session-position.js.map +1 -0
- package/lib/client/worktree-surface-dialogs.d.ts +1 -1
- package/lib/client/worktree-surface-dialogs.d.ts.map +1 -1
- package/lib/client/worktree-surface-dialogs.js +33 -13
- package/lib/client/worktree-surface-dialogs.js.map +1 -1
- package/lib/client/worktree-surface-rows.d.ts +2 -2
- package/lib/client/worktree-surface-rows.d.ts.map +1 -1
- package/lib/client/worktree-surface-rows.js +5 -5
- package/lib/client/worktree-surface-rows.js.map +1 -1
- package/lib/client/worktree-surface-selectors.d.ts +16 -0
- package/lib/client/worktree-surface-selectors.d.ts.map +1 -1
- package/lib/client/worktree-surface-selectors.js +54 -0
- package/lib/client/worktree-surface-selectors.js.map +1 -1
- package/lib/client/worktree-surface-types.d.ts +28 -1
- package/lib/client/worktree-surface-types.d.ts.map +1 -1
- package/lib/client/worktree-view-actions.d.ts +3 -0
- package/lib/client/worktree-view-actions.d.ts.map +1 -1
- package/lib/client/worktree-view-actions.js +3 -0
- package/lib/client/worktree-view-actions.js.map +1 -1
- package/lib/client/worktree-view-read.d.ts +11 -0
- package/lib/client/worktree-view-read.d.ts.map +1 -1
- package/lib/client/worktree-view-read.js +24 -0
- package/lib/client/worktree-view-read.js.map +1 -1
- package/lib/client.js +697 -137
- package/lib/client.js.map +1 -1
- package/lib/contract/index.contract.js +14 -0
- package/lib/contract/index.contract.js.map +1 -1
- package/lib/contract/index.d.ts +22 -2
- package/lib/contract/index.d.ts.map +1 -1
- package/lib/contract/index.js +5 -0
- package/lib/contract/index.js.map +1 -1
- package/lib/host/remote.d.ts.map +1 -1
- package/lib/host/remote.js +2 -0
- package/lib/host/remote.js.map +1 -1
- package/lib/host/service.d.ts +8 -1
- package/lib/host/service.d.ts.map +1 -1
- package/lib/host/service.js +12 -0
- package/lib/host/service.js.map +1 -1
- package/lib/index.d.ts +1 -1
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js.map +1 -1
- package/lib/manage/manager-support.d.ts +2 -0
- package/lib/manage/manager-support.d.ts.map +1 -1
- package/lib/manage/manager-support.js +9 -0
- package/lib/manage/manager-support.js.map +1 -1
- package/lib/manage/manager-worktrees.d.ts +10 -1
- package/lib/manage/manager-worktrees.d.ts.map +1 -1
- package/lib/manage/manager-worktrees.js +121 -5
- package/lib/manage/manager-worktrees.js.map +1 -1
- package/lib/manage/manager.d.ts +8 -1
- package/lib/manage/manager.d.ts.map +1 -1
- package/lib/manage/manager.js +7 -1
- package/lib/manage/manager.js.map +1 -1
- package/lib/provider/git.d.ts +8 -0
- package/lib/provider/git.d.ts.map +1 -1
- package/lib/provider/git.js +57 -11
- package/lib/provider/git.js.map +1 -1
- package/lib/provider/index.d.ts +1 -1
- package/lib/provider/index.d.ts.map +1 -1
- package/lib/provider/index.js +1 -1
- package/lib/provider/index.js.map +1 -1
- package/lib/provider/sidecar-schema.d.ts +1 -1
- package/lib/provider/sidecar-schema.d.ts.map +1 -1
- package/lib/provider/sidecar-schema.js +33 -37
- package/lib/provider/sidecar-schema.js.map +1 -1
- package/lib/provider/sidecar.d.ts.map +1 -1
- package/lib/provider/sidecar.js +3 -1
- package/lib/provider/sidecar.js.map +1 -1
- package/lib/provider/types.d.ts +9 -1
- package/lib/provider/types.d.ts.map +1 -1
- package/lib/provider/types.js +2 -1
- package/lib/provider/types.js.map +1 -1
- package/lib/typert.host.js +115 -21
- package/lib/typert.remote-client.d.ts +5 -1
- package/lib/typert.remote-client.d.ts.map +1 -1
- package/lib/typert.remote-client.js +115 -21
- package/package.json +30 -30
|
@@ -1,16 +1,18 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
|
2
|
+
import { useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState, useSyncExternalStore, } from 'react';
|
|
3
3
|
import { IconBranchOutline16, IconCloseOutline16, IconPlusOutline16, IconSearchOutline16, } from '@deepseek-ai/dsh-client-ui-primitives';
|
|
4
4
|
import { openWorktreeSession } from './navigation.js';
|
|
5
5
|
import { useSidebarOverlayGeometry } from './sidebar-overlay-geometry.js';
|
|
6
|
+
import { isMainExpanded, isWorkspaceExpanded, isWorktreeExpanded, } from './worktree-expand-state.js';
|
|
6
7
|
import { effectiveViewMode, unboundSessionIds, workspaceSessionIds } from './view-mode.js';
|
|
7
8
|
import { formatWorktreeViewError } from './worktree-error-copy.js';
|
|
8
9
|
import { filterVisibleSessionIds, sessionMatchesQuery, } from './session-view.js';
|
|
9
10
|
import { retryWorktreeSessionBinding } from './worktree-session.js';
|
|
10
11
|
import { WorktreeCreateDialog, WorktreeRemovalDialog, WorktreeSessionRenameDialog, WorktreeWorkspaceDeleteDialog, WorktreeWorkspaceRenameDialog, } from './worktree-surface-dialogs.js';
|
|
11
|
-
import { bindingIdsFor, includesText, workspaceMatches, } from './worktree-surface-selectors.js';
|
|
12
|
+
import { bindingIdsFor, clearSessionGroupExpansion, includesText, isCompleteWorktreeWorkspaceSnapshot, currentSessionRevealKeys, resolveCurrentSessionLocation, workspaceMatches, } from './worktree-surface-selectors.js';
|
|
13
|
+
import { scrollCurrentSessionIntoView } from './worktree-session-position.js';
|
|
12
14
|
import { WorktreeGroupRow, WorktreeSessionGroup, WorktreeWorkspaceRow, } from './worktree-surface-rows.js';
|
|
13
|
-
import { executeWorktreeAction, createDefaultWorktreeName, createWorktreeRefreshGuard, filterArchivedSessionIds, loadWorktreeViews, reconcileBaseBranchSelection, resolveWorktreeMove, selectDefaultBaseBranch, stableWorkspaceIds, toRetryableWorktreeOrderError, toWorktreeViewError, WorktreeSessionBindingError, } from './worktree-view.js';
|
|
15
|
+
import { executeWorktreeAction, createDefaultWorktreeName, createWorktreeModalViewLoader, createWorktreeRefreshGuard, filterArchivedSessionIds, loadWorktreeViews, mergeWorktreeView, reconcileBaseBranchSelection, resolveWorktreeMove, selectDefaultBaseBranch, stableWorkspaceIds, toRetryableWorktreeOrderError, toWorktreeViewError, WorktreeSessionBindingError, } from './worktree-view.js';
|
|
14
16
|
import styles from './worktree.css';
|
|
15
17
|
function toNativeWorktreeViewError(error) {
|
|
16
18
|
const viewError = toWorktreeViewError(error);
|
|
@@ -31,20 +33,29 @@ function useStableWorkspaceIds(workspaces) {
|
|
|
31
33
|
* Peer Worktree navigation surface. It keeps the original DSH Workspace mode
|
|
32
34
|
* intact and renders a browser-local Workspace → Worktree → Session projection.
|
|
33
35
|
*/
|
|
34
|
-
export function WorktreeSurface({ useStore, actions, useSessions, useWorkspaces, t, available, manager, invalidateWorktreeContext, createWorkspace, createSessionForWorktree: createSessionCallback, createMainSession, renameWorkspace, deleteWorkspace, insertWorkspaceBefore, insertSessionBefore, insertWorktreeBefore, renameSession, forkSession, archiveSession, ensureSessionWorkspace, syncSessionWorkspaces, openSession, }) {
|
|
36
|
+
export function WorktreeSurface({ useStore, actions, useSessions, useWorkspaces, t, available, expandState, manager, invalidateWorktreeContext, createWorkspace, createSessionForWorktree: createSessionCallback, createMainSession, renameWorkspace, deleteWorkspace, insertWorkspaceBefore, insertSessionBefore, insertWorktreeBefore, renameSession, forkSession, archiveSession, ensureSessionWorkspace, syncSessionWorkspaces, openSession, }) {
|
|
35
37
|
const preferredMode = useStore((state) => state.viewMode);
|
|
36
38
|
const mode = effectiveViewMode(preferredMode, available && manager !== undefined);
|
|
37
39
|
const sessions = useSessions((state) => state);
|
|
38
40
|
const workspaces = useWorkspaces((state) => state);
|
|
41
|
+
const currentSessionId = sessions.current;
|
|
39
42
|
const workspaceIds = useStableWorkspaceIds(workspaces.items);
|
|
40
43
|
const [readState, setReadState] = useState(EMPTY_READ_STATE);
|
|
44
|
+
const expandSnapshot = useSyncExternalStore(expandState.subscribe, expandState.getSnapshot, expandState.getSnapshot);
|
|
41
45
|
const readStateRef = useRef(readState);
|
|
42
46
|
readStateRef.current = readState;
|
|
43
47
|
const [searchQuery, setSearchQuery] = useState('');
|
|
44
|
-
const [
|
|
45
|
-
const
|
|
46
|
-
|
|
48
|
+
const [currentSessionReveal, setCurrentSessionReveal] = useState();
|
|
49
|
+
const searchQueryRef = useRef(searchQuery);
|
|
50
|
+
searchQueryRef.current = searchQuery;
|
|
51
|
+
const locateGenerationRef = useRef(0);
|
|
52
|
+
const positionedLocateGenerationRef = useRef();
|
|
47
53
|
const [worktreeModalWorkspaceId, setWorktreeModalWorkspaceId] = useState();
|
|
54
|
+
const [modalReadError, setModalReadError] = useState();
|
|
55
|
+
const [modalReadLoading, setModalReadLoading] = useState(false);
|
|
56
|
+
const [worktreeModalMode, setWorktreeModalMode] = useState('create');
|
|
57
|
+
const [importCandidates, setImportCandidates] = useState({ status: 'idle', candidates: [] });
|
|
58
|
+
const [selectedImportPath, setSelectedImportPath] = useState();
|
|
48
59
|
const [openWorkspaceMenuId, setOpenWorkspaceMenuId] = useState();
|
|
49
60
|
const [openWorktreeMenuId, setOpenWorktreeMenuId] = useState();
|
|
50
61
|
const [worktreeRemoval, setWorktreeRemoval] = useState();
|
|
@@ -72,6 +83,11 @@ export function WorktreeSurface({ useStore, actions, useSessions, useWorkspaces,
|
|
|
72
83
|
const [worktreeDrag, setWorktreeDrag] = useState();
|
|
73
84
|
const worktreeDropCommitted = useRef(false);
|
|
74
85
|
const refreshGuard = useRef(createWorktreeRefreshGuard());
|
|
86
|
+
const modalReadLoader = useRef(createWorktreeModalViewLoader());
|
|
87
|
+
const modalReadViewRef = useRef();
|
|
88
|
+
const importCandidatesGuard = useRef(createWorktreeRefreshGuard());
|
|
89
|
+
const modalWorkspaceIdRef = useRef(worktreeModalWorkspaceId);
|
|
90
|
+
modalWorkspaceIdRef.current = worktreeModalWorkspaceId;
|
|
75
91
|
const { ref, width, bounds } = useSidebarOverlayGeometry(mode === 'worktree');
|
|
76
92
|
const collapsed = width <= 64;
|
|
77
93
|
const query = searchQuery.trim().toLocaleLowerCase();
|
|
@@ -92,23 +108,59 @@ export function WorktreeSurface({ useStore, actions, useSessions, useWorkspaces,
|
|
|
92
108
|
invalidateContext: options.invalidateContext !== false,
|
|
93
109
|
invalidateWorktreeContext,
|
|
94
110
|
}), (views) => {
|
|
95
|
-
setReadState({
|
|
111
|
+
setReadState({
|
|
112
|
+
status: 'ready',
|
|
113
|
+
views: modalReadViewRef.current === undefined
|
|
114
|
+
? views
|
|
115
|
+
: mergeWorktreeView(views, modalReadViewRef.current),
|
|
116
|
+
});
|
|
96
117
|
}, (error) => {
|
|
97
118
|
if (preserveCurrent)
|
|
98
119
|
throw error;
|
|
99
120
|
setReadState({
|
|
100
121
|
status: 'error',
|
|
101
|
-
views:
|
|
122
|
+
views: modalReadViewRef.current === undefined
|
|
123
|
+
? []
|
|
124
|
+
: [modalReadViewRef.current],
|
|
102
125
|
error: toWorktreeViewError(error),
|
|
103
126
|
});
|
|
104
127
|
});
|
|
105
128
|
}, [invalidateWorktreeContext, manager, workspaceIds]);
|
|
129
|
+
const loadModalWorktreeView = useCallback((workspaceId) => {
|
|
130
|
+
setModalReadError(undefined);
|
|
131
|
+
setModalReadLoading(true);
|
|
132
|
+
if (manager === undefined) {
|
|
133
|
+
setModalReadLoading(false);
|
|
134
|
+
setModalReadError({
|
|
135
|
+
code: 'WORKTREE_VIEW_UNAVAILABLE',
|
|
136
|
+
message: '',
|
|
137
|
+
retryable: true,
|
|
138
|
+
});
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
void modalReadLoader.current.load(manager, workspaceId, (view) => {
|
|
142
|
+
modalReadViewRef.current = view;
|
|
143
|
+
setModalReadLoading(false);
|
|
144
|
+
setReadState((current) => ({
|
|
145
|
+
...current,
|
|
146
|
+
views: mergeWorktreeView(current.views, view),
|
|
147
|
+
}));
|
|
148
|
+
}, (error) => {
|
|
149
|
+
setModalReadLoading(false);
|
|
150
|
+
setModalReadError(toWorktreeViewError(error));
|
|
151
|
+
});
|
|
152
|
+
}, [manager]);
|
|
106
153
|
useEffect(() => {
|
|
107
154
|
if (mode === 'worktree') {
|
|
108
155
|
void refresh({ preserveCurrent: readStateRef.current.status === 'ready' });
|
|
109
156
|
}
|
|
110
157
|
else {
|
|
111
158
|
refreshGuard.current.invalidate();
|
|
159
|
+
modalReadLoader.current.invalidate();
|
|
160
|
+
modalReadViewRef.current = undefined;
|
|
161
|
+
setWorktreeModalWorkspaceId(undefined);
|
|
162
|
+
setModalReadError(undefined);
|
|
163
|
+
setModalReadLoading(false);
|
|
112
164
|
setReadState(EMPTY_READ_STATE);
|
|
113
165
|
}
|
|
114
166
|
}, [mode, refresh]);
|
|
@@ -121,6 +173,63 @@ export function WorktreeSurface({ useStore, actions, useSessions, useWorkspaces,
|
|
|
121
173
|
}))));
|
|
122
174
|
}, [readState.status, readState.views, syncSessionWorkspaces]);
|
|
123
175
|
const viewByWorkspace = useMemo(() => new Map(readState.views.map((view) => [view.workspaceId, view])), [readState.views]);
|
|
176
|
+
const currentSessionLocation = useMemo(() => readState.status === 'ready'
|
|
177
|
+
? resolveCurrentSessionLocation(currentSessionId, workspaces.items, readState.views)
|
|
178
|
+
: undefined, [currentSessionId, readState.status, readState.views, workspaces.items]);
|
|
179
|
+
const currentRevealKeys = useMemo(() => new Set(currentSessionRevealKeys(currentSessionLocation)), [currentSessionLocation]);
|
|
180
|
+
const isCurrentSessionReveal = (key) => currentSessionReveal !== undefined &&
|
|
181
|
+
currentSessionReveal.sessionId === currentSessionId &&
|
|
182
|
+
currentRevealKeys.has(key) &&
|
|
183
|
+
currentSessionReveal.suppressedKeys[key] !== true;
|
|
184
|
+
useLayoutEffect(() => {
|
|
185
|
+
locateGenerationRef.current += 1;
|
|
186
|
+
positionedLocateGenerationRef.current = undefined;
|
|
187
|
+
if (mode !== 'worktree') {
|
|
188
|
+
setCurrentSessionReveal(undefined);
|
|
189
|
+
return;
|
|
190
|
+
}
|
|
191
|
+
if (searchQueryRef.current.trim().length > 0)
|
|
192
|
+
setSearchQuery('');
|
|
193
|
+
setCurrentSessionReveal(currentSessionId === undefined
|
|
194
|
+
? undefined
|
|
195
|
+
: { sessionId: currentSessionId, suppressedKeys: {} });
|
|
196
|
+
}, [currentSessionId, mode]);
|
|
197
|
+
useLayoutEffect(() => {
|
|
198
|
+
if (mode !== 'worktree' ||
|
|
199
|
+
currentSessionId === undefined ||
|
|
200
|
+
currentSessionLocation === undefined) {
|
|
201
|
+
return;
|
|
202
|
+
}
|
|
203
|
+
const generation = locateGenerationRef.current;
|
|
204
|
+
if (positionedLocateGenerationRef.current === generation)
|
|
205
|
+
return;
|
|
206
|
+
let cancelled = false;
|
|
207
|
+
const frame = requestAnimationFrame(() => {
|
|
208
|
+
if (cancelled || generation !== locateGenerationRef.current)
|
|
209
|
+
return;
|
|
210
|
+
if (!scrollCurrentSessionIntoView(ref.current, currentSessionId))
|
|
211
|
+
return;
|
|
212
|
+
positionedLocateGenerationRef.current = generation;
|
|
213
|
+
});
|
|
214
|
+
return () => {
|
|
215
|
+
cancelled = true;
|
|
216
|
+
cancelAnimationFrame(frame);
|
|
217
|
+
};
|
|
218
|
+
}, [
|
|
219
|
+
currentSessionId,
|
|
220
|
+
currentSessionLocation,
|
|
221
|
+
currentSessionReveal,
|
|
222
|
+
expandSnapshot,
|
|
223
|
+
mode,
|
|
224
|
+
query,
|
|
225
|
+
readState.status,
|
|
226
|
+
]);
|
|
227
|
+
useEffect(() => {
|
|
228
|
+
if (readState.status !== 'ready' ||
|
|
229
|
+
!isCompleteWorktreeWorkspaceSnapshot(workspaceIds, readState.views))
|
|
230
|
+
return;
|
|
231
|
+
expandState.actions.retain(workspaceIds, readState.views.flatMap((view) => view.worktrees.map((record) => record.worktreeId)));
|
|
232
|
+
}, [expandState, readState.status, readState.views, workspaceIds]);
|
|
124
233
|
const modalWorkspace = workspaces.items.find((workspace) => workspace.workspaceId === worktreeModalWorkspaceId);
|
|
125
234
|
const modalView = worktreeModalWorkspaceId === undefined
|
|
126
235
|
? undefined
|
|
@@ -131,15 +240,27 @@ export function WorktreeSurface({ useStore, actions, useSessions, useWorkspaces,
|
|
|
131
240
|
: modalReadiness?.status === 'ready'
|
|
132
241
|
? modalView.branches.length === 0 ? 'noLocalBranch' : undefined
|
|
133
242
|
: modalReadiness?.status;
|
|
134
|
-
const modalCanCreate =
|
|
243
|
+
const modalCanCreate = !modalReadLoading &&
|
|
244
|
+
modalSetupStatus === undefined &&
|
|
245
|
+
modalReadiness?.status === 'ready';
|
|
135
246
|
useEffect(() => {
|
|
136
247
|
if (worktreeModalWorkspaceId === undefined || modalView === undefined)
|
|
137
248
|
return;
|
|
138
249
|
if (modalView.readiness.status !== 'ready') {
|
|
139
250
|
setSelectedBranch('');
|
|
251
|
+
setNewBranch('');
|
|
140
252
|
return;
|
|
141
253
|
}
|
|
142
254
|
setSelectedBranch((current) => reconcileBaseBranchSelection(current, modalView.branches));
|
|
255
|
+
setNewBranch((current) => {
|
|
256
|
+
if (current.length > 0)
|
|
257
|
+
return current;
|
|
258
|
+
const existingNames = [
|
|
259
|
+
...modalView.branches.map((branch) => branch.name),
|
|
260
|
+
...modalView.worktrees.map((worktree) => worktree.branch),
|
|
261
|
+
];
|
|
262
|
+
return createDefaultWorktreeName(existingNames);
|
|
263
|
+
});
|
|
143
264
|
}, [modalView, worktreeModalWorkspaceId]);
|
|
144
265
|
const runMutation = async (operation) => {
|
|
145
266
|
setActionPending(true);
|
|
@@ -155,6 +276,24 @@ export function WorktreeSurface({ useStore, actions, useSessions, useWorkspaces,
|
|
|
155
276
|
setActionPending(false);
|
|
156
277
|
}
|
|
157
278
|
};
|
|
279
|
+
const loadImportCandidates = useCallback(async (workspaceId) => {
|
|
280
|
+
if (manager === undefined)
|
|
281
|
+
return;
|
|
282
|
+
setImportCandidates((current) => ({ status: 'loading', candidates: current.candidates }));
|
|
283
|
+
await importCandidatesGuard.current.run(() => manager.listImportCandidates({ workspaceId }), (candidates) => {
|
|
284
|
+
if (modalWorkspaceIdRef.current !== workspaceId)
|
|
285
|
+
return;
|
|
286
|
+
setImportCandidates({ status: 'ready', candidates });
|
|
287
|
+
}, (error) => {
|
|
288
|
+
if (modalWorkspaceIdRef.current !== workspaceId)
|
|
289
|
+
return;
|
|
290
|
+
setImportCandidates((current) => ({
|
|
291
|
+
status: 'error',
|
|
292
|
+
candidates: current.candidates,
|
|
293
|
+
error: toWorktreeViewError(error),
|
|
294
|
+
}));
|
|
295
|
+
});
|
|
296
|
+
}, [manager]);
|
|
158
297
|
const workspaceRenameTrimmed = workspaceRenameDraft.trim();
|
|
159
298
|
const workspaceRenameDuplicate = workspaceRenameTarget !== undefined &&
|
|
160
299
|
workspaceRenameTrimmed.length > 0 &&
|
|
@@ -373,91 +512,201 @@ export function WorktreeSurface({ useStore, actions, useSessions, useWorkspaces,
|
|
|
373
512
|
return;
|
|
374
513
|
await runMutation(() => archiveSession(sessionId));
|
|
375
514
|
};
|
|
515
|
+
const clearSessionGroups = (groupKeys) => {
|
|
516
|
+
if (groupKeys.length === 0)
|
|
517
|
+
return;
|
|
518
|
+
setExpandedSessionGroups((current) => clearSessionGroupExpansion(current, groupKeys));
|
|
519
|
+
};
|
|
520
|
+
const suppressCurrentSessionReveal = (key) => {
|
|
521
|
+
if (!isCurrentSessionReveal(key))
|
|
522
|
+
return false;
|
|
523
|
+
setCurrentSessionReveal((current) => {
|
|
524
|
+
if (current === undefined || current.sessionId !== currentSessionId)
|
|
525
|
+
return current;
|
|
526
|
+
return {
|
|
527
|
+
...current,
|
|
528
|
+
suppressedKeys: { ...current.suppressedKeys, [key]: true },
|
|
529
|
+
};
|
|
530
|
+
});
|
|
531
|
+
return true;
|
|
532
|
+
};
|
|
376
533
|
const toggleWorkspace = (workspaceId) => {
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
534
|
+
const persistedExpanded = isWorkspaceExpanded(expandSnapshot, workspaceId);
|
|
535
|
+
const autoExpanded = isCurrentSessionReveal('workspace:' + workspaceId);
|
|
536
|
+
const visuallyExpanded = persistedExpanded || autoExpanded;
|
|
537
|
+
if (visuallyExpanded && autoExpanded) {
|
|
538
|
+
suppressCurrentSessionReveal('workspace:' + workspaceId);
|
|
539
|
+
}
|
|
540
|
+
if (visuallyExpanded && !persistedExpanded) {
|
|
541
|
+
clearSessionGroups([
|
|
542
|
+
'main:' + workspaceId,
|
|
543
|
+
...(viewByWorkspace.get(workspaceId)?.worktrees.map((record) => record.worktreeId) ?? []).map((worktreeId) => 'worktree:' + worktreeId),
|
|
544
|
+
]);
|
|
545
|
+
return;
|
|
546
|
+
}
|
|
547
|
+
expandState.actions.toggleWorkspace(workspaceId);
|
|
548
|
+
if (visuallyExpanded) {
|
|
549
|
+
clearSessionGroups([
|
|
550
|
+
'main:' + workspaceId,
|
|
551
|
+
...(viewByWorkspace.get(workspaceId)?.worktrees.map((record) => record.worktreeId) ?? []).map((worktreeId) => 'worktree:' + worktreeId),
|
|
552
|
+
]);
|
|
553
|
+
}
|
|
381
554
|
};
|
|
382
555
|
const toggleMain = (workspaceId) => {
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
556
|
+
const persistedExpanded = isMainExpanded(expandSnapshot, workspaceId);
|
|
557
|
+
const autoExpanded = isCurrentSessionReveal('main:' + workspaceId);
|
|
558
|
+
const visuallyExpanded = persistedExpanded || autoExpanded;
|
|
559
|
+
if (visuallyExpanded && autoExpanded) {
|
|
560
|
+
suppressCurrentSessionReveal('main:' + workspaceId);
|
|
561
|
+
}
|
|
562
|
+
if (visuallyExpanded && !persistedExpanded) {
|
|
563
|
+
clearSessionGroups(['main:' + workspaceId]);
|
|
564
|
+
return;
|
|
565
|
+
}
|
|
566
|
+
expandState.actions.toggleMain(workspaceId);
|
|
567
|
+
if (visuallyExpanded)
|
|
568
|
+
clearSessionGroups(['main:' + workspaceId]);
|
|
387
569
|
};
|
|
388
570
|
const toggleWorktree = (worktreeId) => {
|
|
389
|
-
|
|
571
|
+
const persistedExpanded = isWorktreeExpanded(expandSnapshot, worktreeId);
|
|
572
|
+
const autoExpanded = isCurrentSessionReveal('worktree:' + worktreeId);
|
|
573
|
+
const visuallyExpanded = persistedExpanded || autoExpanded;
|
|
574
|
+
if (visuallyExpanded && autoExpanded) {
|
|
575
|
+
suppressCurrentSessionReveal('worktree:' + worktreeId);
|
|
576
|
+
}
|
|
577
|
+
if (visuallyExpanded && !persistedExpanded) {
|
|
578
|
+
clearSessionGroups(['worktree:' + worktreeId]);
|
|
579
|
+
return;
|
|
580
|
+
}
|
|
581
|
+
expandState.actions.toggleWorktree(worktreeId);
|
|
582
|
+
if (visuallyExpanded)
|
|
583
|
+
clearSessionGroups(['worktree:' + worktreeId]);
|
|
584
|
+
};
|
|
585
|
+
const toggleSessionGroup = (groupKey) => {
|
|
586
|
+
const autoExpanded = isCurrentSessionReveal('session-group:' + groupKey);
|
|
587
|
+
const transientExpanded = expandedSessionGroups[groupKey] === true;
|
|
588
|
+
if (autoExpanded) {
|
|
589
|
+
suppressCurrentSessionReveal('session-group:' + groupKey);
|
|
590
|
+
setExpandedSessionGroups((current) => {
|
|
591
|
+
const next = { ...current };
|
|
592
|
+
delete next[groupKey];
|
|
593
|
+
return next;
|
|
594
|
+
});
|
|
595
|
+
return;
|
|
596
|
+
}
|
|
597
|
+
setExpandedSessionGroups((current) => ({
|
|
390
598
|
...current,
|
|
391
|
-
[
|
|
599
|
+
[groupKey]: !transientExpanded,
|
|
392
600
|
}));
|
|
393
601
|
};
|
|
602
|
+
const closeWorktreeCreator = (force = false) => {
|
|
603
|
+
if (actionPending && !force)
|
|
604
|
+
return;
|
|
605
|
+
modalReadLoader.current.invalidate();
|
|
606
|
+
modalReadViewRef.current = undefined;
|
|
607
|
+
importCandidatesGuard.current.invalidate();
|
|
608
|
+
setWorktreeModalWorkspaceId(undefined);
|
|
609
|
+
setModalReadError(undefined);
|
|
610
|
+
setModalReadLoading(false);
|
|
611
|
+
};
|
|
394
612
|
const openWorktreeCreator = (workspace) => {
|
|
395
613
|
const view = viewByWorkspace.get(workspace.workspaceId);
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
...(view?.worktrees ?? []).map((worktree) => worktree.branch),
|
|
400
|
-
];
|
|
614
|
+
modalReadLoader.current.invalidate();
|
|
615
|
+
modalReadViewRef.current = undefined;
|
|
616
|
+
importCandidatesGuard.current.invalidate();
|
|
401
617
|
setWorktreeModalWorkspaceId(workspace.workspaceId);
|
|
402
|
-
|
|
403
|
-
|
|
618
|
+
setWorktreeModalMode('create');
|
|
619
|
+
setImportCandidates({ status: 'idle', candidates: [] });
|
|
620
|
+
setSelectedImportPath(undefined);
|
|
404
621
|
setActionError(undefined);
|
|
622
|
+
setModalReadError(undefined);
|
|
623
|
+
setModalReadLoading(false);
|
|
624
|
+
if (view === undefined) {
|
|
625
|
+
setSelectedBranch('');
|
|
626
|
+
setNewBranch('');
|
|
627
|
+
loadModalWorktreeView(workspace.workspaceId);
|
|
628
|
+
return;
|
|
629
|
+
}
|
|
630
|
+
setSelectedBranch(selectDefaultBaseBranch(view.branches));
|
|
631
|
+
setNewBranch(createDefaultWorktreeName([
|
|
632
|
+
...view.branches.map((branch) => branch.name),
|
|
633
|
+
...view.worktrees.map((worktree) => worktree.branch),
|
|
634
|
+
]));
|
|
405
635
|
};
|
|
406
|
-
const
|
|
407
|
-
|
|
408
|
-
if (
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
636
|
+
const changeWorktreeModalMode = (mode) => {
|
|
637
|
+
setWorktreeModalMode(mode);
|
|
638
|
+
if (mode === 'import' &&
|
|
639
|
+
worktreeModalWorkspaceId !== undefined &&
|
|
640
|
+
importCandidates.status === 'idle') {
|
|
641
|
+
void loadImportCandidates(worktreeModalWorkspaceId);
|
|
642
|
+
}
|
|
643
|
+
};
|
|
644
|
+
const continueWorktreeRegistration = async (registeredWorktree) => {
|
|
645
|
+
closeWorktreeCreator(true);
|
|
646
|
+
if (createSessionCallback === undefined) {
|
|
647
|
+
await refresh({ preserveCurrent: true });
|
|
648
|
+
setActionError({
|
|
649
|
+
code: 'WORKTREE_REGISTRATION_SESSION_UNAVAILABLE',
|
|
650
|
+
message: '',
|
|
651
|
+
retryable: true,
|
|
652
|
+
});
|
|
413
653
|
return;
|
|
414
654
|
}
|
|
415
|
-
const
|
|
416
|
-
workspaceId:
|
|
417
|
-
|
|
418
|
-
|
|
655
|
+
const sessionInput = {
|
|
656
|
+
workspaceId: registeredWorktree.workspaceId,
|
|
657
|
+
worktreeId: registeredWorktree.worktreeId,
|
|
658
|
+
cwd: registeredWorktree.absolutePath,
|
|
419
659
|
};
|
|
660
|
+
try {
|
|
661
|
+
await createSessionCallback(sessionInput);
|
|
662
|
+
await invalidateWorktreeContext?.(registeredWorktree.workspaceId);
|
|
663
|
+
}
|
|
664
|
+
catch (error) {
|
|
665
|
+
if (error instanceof WorktreeSessionBindingError && error.retryable) {
|
|
666
|
+
setPendingSessionBinding({ ...sessionInput, sessionId: error.sessionId });
|
|
667
|
+
}
|
|
668
|
+
throw error;
|
|
669
|
+
}
|
|
670
|
+
await refresh({ preserveCurrent: true });
|
|
671
|
+
};
|
|
672
|
+
const submitWorktree = async () => {
|
|
673
|
+
const worktreeName = newBranch.trim();
|
|
674
|
+
const selectedImportCandidate = importCandidates.candidates.find((candidate) => candidate.absolutePath === selectedImportPath);
|
|
675
|
+
if (manager === undefined || modalWorkspace === undefined)
|
|
676
|
+
return;
|
|
677
|
+
if (worktreeModalMode === 'create' &&
|
|
678
|
+
(!modalCanCreate || selectedBranch.length === 0 || worktreeName.length === 0))
|
|
679
|
+
return;
|
|
680
|
+
if (worktreeModalMode === 'import' && selectedImportCandidate === undefined)
|
|
681
|
+
return;
|
|
420
682
|
setActionPending(true);
|
|
421
683
|
setActionError(undefined);
|
|
422
684
|
setPendingSessionBinding(undefined);
|
|
423
685
|
try {
|
|
424
|
-
const
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
686
|
+
const registeredWorktree = worktreeModalMode === 'create'
|
|
687
|
+
? await executeWorktreeAction(manager, {
|
|
688
|
+
type: 'createWorktree',
|
|
689
|
+
input: {
|
|
690
|
+
workspaceId: modalWorkspace.workspaceId,
|
|
691
|
+
branch: selectedBranch,
|
|
692
|
+
newBranch: worktreeName,
|
|
693
|
+
},
|
|
694
|
+
})
|
|
695
|
+
: await executeWorktreeAction(manager, {
|
|
696
|
+
type: 'importWorktree',
|
|
697
|
+
input: {
|
|
698
|
+
workspaceId: modalWorkspace.workspaceId,
|
|
699
|
+
absolutePath: selectedImportCandidate.absolutePath,
|
|
700
|
+
},
|
|
701
|
+
});
|
|
702
|
+
if (registeredWorktree === undefined) {
|
|
429
703
|
throw {
|
|
430
704
|
code: 'WORKTREE_RECORD_MISSING',
|
|
431
705
|
message: '',
|
|
432
706
|
retryable: true,
|
|
433
707
|
};
|
|
434
708
|
}
|
|
435
|
-
|
|
436
|
-
if (createSessionCallback === undefined) {
|
|
437
|
-
await refresh({ preserveCurrent: true });
|
|
438
|
-
setActionError({
|
|
439
|
-
code: 'WORKTREE_CREATED_SESSION_UNAVAILABLE',
|
|
440
|
-
message: '',
|
|
441
|
-
retryable: true,
|
|
442
|
-
});
|
|
443
|
-
return;
|
|
444
|
-
}
|
|
445
|
-
const sessionInput = {
|
|
446
|
-
workspaceId: createdWorktree.workspaceId,
|
|
447
|
-
worktreeId: createdWorktree.worktreeId,
|
|
448
|
-
cwd: createdWorktree.absolutePath,
|
|
449
|
-
};
|
|
450
|
-
try {
|
|
451
|
-
await createSessionCallback(sessionInput);
|
|
452
|
-
await invalidateWorktreeContext?.(createdWorktree.workspaceId);
|
|
453
|
-
}
|
|
454
|
-
catch (error) {
|
|
455
|
-
if (error instanceof WorktreeSessionBindingError && error.retryable) {
|
|
456
|
-
setPendingSessionBinding({ ...sessionInput, sessionId: error.sessionId });
|
|
457
|
-
}
|
|
458
|
-
throw error;
|
|
459
|
-
}
|
|
460
|
-
await refresh({ preserveCurrent: true });
|
|
709
|
+
await continueWorktreeRegistration(registeredWorktree);
|
|
461
710
|
}
|
|
462
711
|
catch (error) {
|
|
463
712
|
setActionError(toWorktreeViewError(error));
|
|
@@ -562,15 +811,21 @@ export function WorktreeSurface({ useStore, actions, useSessions, useWorkspaces,
|
|
|
562
811
|
const mainLabel = currentBranch === undefined
|
|
563
812
|
? t('worktree.main')
|
|
564
813
|
: t('worktree.mainWithBranch', { branch: currentBranch });
|
|
565
|
-
const expanded =
|
|
814
|
+
const expanded = isWorkspaceExpanded(expandSnapshot, workspace.workspaceId) ||
|
|
815
|
+
isCurrentSessionReveal('workspace:' + workspace.workspaceId);
|
|
566
816
|
const workspaceMatchesQuery = includesText(workspace.title, query);
|
|
567
817
|
const allWorkspaceSessionIds = filterArchivedSessionIds(workspaceSessionIds(workspaces, workspace.workspaceId, sessions.ids), archivedSessionIds);
|
|
568
818
|
const bindings = view?.bindings ?? [];
|
|
569
819
|
const boundSessionIds = new Set(bindings.map((binding) => binding.sessionId));
|
|
570
820
|
const mainSessionIds = filterVisibleSessionIds(unboundSessionIds(allWorkspaceSessionIds, [...boundSessionIds]), sessions);
|
|
571
821
|
const visibleMainSessionIds = mainSessionIds.filter((sessionId) => workspaceMatchesQuery || sessionMatchesQuery(sessionId, sessions, query));
|
|
572
|
-
const mainExpanded =
|
|
822
|
+
const mainExpanded = isMainExpanded(expandSnapshot, workspace.workspaceId) ||
|
|
823
|
+
isCurrentSessionReveal('main:' + workspace.workspaceId);
|
|
573
824
|
const mainGroupKey = `main:${workspace.workspaceId}`;
|
|
825
|
+
const sessionIds = visibleMainSessionIds;
|
|
826
|
+
const mainSessionGroupExpanded = expandedSessionGroups[mainGroupKey] === true ||
|
|
827
|
+
(sessionIds.length > 5 &&
|
|
828
|
+
isCurrentSessionReveal('session-group:' + mainGroupKey));
|
|
574
829
|
const worktrees = view?.worktrees ?? [];
|
|
575
830
|
const sameWorkspaceWorktreeDrag = worktreeDrag?.workspaceId === workspace.workspaceId;
|
|
576
831
|
return (_jsxs("section", { className: styles.workspaceGroup, "data-workspace-id": workspace.workspaceId, children: [_jsx(WorktreeWorkspaceRow, { t: t, workspace: workspace, expanded: expanded, actionPending: actionPending, menuOpen: openWorkspaceMenuId === workspace.workspaceId, drag: {
|
|
@@ -623,11 +878,8 @@ export function WorktreeSurface({ useStore, actions, useSessions, useWorkspaces,
|
|
|
623
878
|
? undefined
|
|
624
879
|
: () => {
|
|
625
880
|
createMainSession(workspace.workspaceId);
|
|
626
|
-
} }), mainExpanded && (_jsx(WorktreeSessionGroup, { t: t, groupKey: mainGroupKey, sessionIds:
|
|
627
|
-
|
|
628
|
-
...current,
|
|
629
|
-
[mainGroupKey]: current[mainGroupKey] !== true,
|
|
630
|
-
}));
|
|
881
|
+
} }), mainExpanded && (_jsx(WorktreeSessionGroup, { t: t, groupKey: mainGroupKey, sessionIds: sessionIds, workspaceId: workspace.workspaceId, currentSessionId: currentSessionId, expanded: mainSessionGroupExpanded, actionPending: actionPending, sessions: sessions, dragState: sessionDrag, onToggleExpanded: () => {
|
|
882
|
+
toggleSessionGroup(mainGroupKey);
|
|
631
883
|
}, onStartDrag: (groupKey, sessionId) => {
|
|
632
884
|
sessionDropCommitted.current = false;
|
|
633
885
|
setSessionDrag({ groupKey, sessionId, over: null });
|
|
@@ -653,6 +905,10 @@ export function WorktreeSurface({ useStore, actions, useSessions, useWorkspaces,
|
|
|
653
905
|
}
|
|
654
906
|
const visibleWorktreeSessionIds = worktreeSessionIds.filter((sessionId) => worktreeMatchesQuery || sessionMatchesQuery(sessionId, sessions, query));
|
|
655
907
|
const worktreeGroupKey = `worktree:${record.worktreeId}`;
|
|
908
|
+
const sessionIds = visibleWorktreeSessionIds;
|
|
909
|
+
const sessionGroupExpanded = expandedSessionGroups[worktreeGroupKey] === true ||
|
|
910
|
+
(sessionIds.length > 5 &&
|
|
911
|
+
isCurrentSessionReveal('session-group:' + worktreeGroupKey));
|
|
656
912
|
const state = record.status === 'removed'
|
|
657
913
|
? 'warning'
|
|
658
914
|
: record.health === 'repair'
|
|
@@ -663,7 +919,8 @@ export function WorktreeSurface({ useStore, actions, useSessions, useWorkspaces,
|
|
|
663
919
|
: record.health === 'repair'
|
|
664
920
|
? t('worktree.repair')
|
|
665
921
|
: t('worktree.ready');
|
|
666
|
-
const worktreeExpanded =
|
|
922
|
+
const worktreeExpanded = isWorktreeExpanded(expandSnapshot, record.worktreeId) ||
|
|
923
|
+
isCurrentSessionReveal('worktree:' + record.worktreeId);
|
|
667
924
|
return (_jsxs("div", { className: styles.worktreeGroup, "data-worktree-id": record.worktreeId, children: [_jsx(WorktreeGroupRow, { t: t, kind: "worktree", label: record.branch, worktreeId: record.worktreeId, expanded: worktreeExpanded, icon: _jsx(IconBranchOutline16, {}), workspaceTitle: workspace.title, state: state, stateLabel: stateLabel, onToggle: () => {
|
|
668
925
|
toggleWorktree(record.worktreeId);
|
|
669
926
|
}, onCreateSession: record.status === 'active' && record.health !== 'repair'
|
|
@@ -718,11 +975,8 @@ export function WorktreeSurface({ useStore, actions, useSessions, useWorkspaces,
|
|
|
718
975
|
setWorktreeDrag(undefined);
|
|
719
976
|
worktreeDropCommitted.current = false;
|
|
720
977
|
},
|
|
721
|
-
} }), worktreeExpanded && (_jsx(WorktreeSessionGroup, { t: t, groupKey: worktreeGroupKey, sessionIds:
|
|
722
|
-
|
|
723
|
-
...current,
|
|
724
|
-
[worktreeGroupKey]: current[worktreeGroupKey] !== true,
|
|
725
|
-
}));
|
|
978
|
+
} }), worktreeExpanded && (_jsx(WorktreeSessionGroup, { t: t, groupKey: worktreeGroupKey, sessionIds: sessionIds, workspaceId: workspace.workspaceId, currentSessionId: currentSessionId, expanded: sessionGroupExpanded, actionPending: actionPending, sessions: sessions, dragState: sessionDrag, onToggleExpanded: () => {
|
|
979
|
+
toggleSessionGroup(worktreeGroupKey);
|
|
726
980
|
}, onStartDrag: (groupKey, sessionId) => {
|
|
727
981
|
sessionDropCommitted.current = false;
|
|
728
982
|
setSessionDrag({ groupKey, sessionId, over: null });
|
|
@@ -740,17 +994,24 @@ export function WorktreeSurface({ useStore, actions, useSessions, useWorkspaces,
|
|
|
740
994
|
? undefined
|
|
741
995
|
: archiveWorktreeSession }))] }, record.worktreeId));
|
|
742
996
|
})] }))] }, workspace.workspaceId));
|
|
743
|
-
})) })) : null] })] }), _jsx(
|
|
744
|
-
actions.setViewMode('workspace-session');
|
|
745
|
-
}, children: "WT" }) }), _jsx(WorktreeSessionRenameDialog, { t: t, target: sessionRenameTarget, draft: sessionRenameDraft, pending: sessionRenamePending, error: sessionRenameError, onClose: closeSessionRename, onDraftChange: (draft) => {
|
|
997
|
+
})) })) : null] })] }), _jsx(WorktreeSessionRenameDialog, { t: t, target: sessionRenameTarget, draft: sessionRenameDraft, pending: sessionRenamePending, error: sessionRenameError, onClose: closeSessionRename, onDraftChange: (draft) => {
|
|
746
998
|
setSessionRenameDraft(draft);
|
|
747
999
|
setSessionRenameError(undefined);
|
|
748
1000
|
}, onSubmit: confirmSessionRename }), _jsx(WorktreeWorkspaceRenameDialog, { t: t, target: workspaceRenameTarget, draft: workspaceRenameDraft, pending: workspaceRenamePending, duplicate: workspaceRenameDuplicate, error: workspaceRenameError, onClose: closeWorkspaceRename, onDraftChange: (draft) => {
|
|
749
1001
|
setWorkspaceRenameDraft(draft);
|
|
750
1002
|
setWorkspaceRenameError(undefined);
|
|
751
|
-
}, onSubmit: confirmWorkspaceRename }), _jsx(WorktreeWorkspaceDeleteDialog, { t: t, target: workspaceDeleteTarget, pending: workspaceDeletePending, error: workspaceDeleteError, onClose: closeWorkspaceDelete, onSubmit: confirmWorkspaceDelete }), _jsx(WorktreeCreateDialog, { t: t, workspace: modalWorkspace, view: modalView, setupStatus: modalSetupStatus, canCreate: modalCanCreate, selectedBranch: selectedBranch, newBranch: newBranch, actionPending: actionPending, onClose: () => {
|
|
752
|
-
|
|
753
|
-
|
|
1003
|
+
}, onSubmit: confirmWorkspaceRename }), _jsx(WorktreeWorkspaceDeleteDialog, { t: t, target: workspaceDeleteTarget, pending: workspaceDeletePending, error: workspaceDeleteError, onClose: closeWorkspaceDelete, onSubmit: confirmWorkspaceDelete }), _jsx(WorktreeCreateDialog, { t: t, workspace: modalWorkspace, view: modalView, readError: modalReadError, setupStatus: modalSetupStatus, canCreate: modalCanCreate, mode: worktreeModalMode, importCandidates: importCandidates, selectedImportPath: selectedImportPath, selectedBranch: selectedBranch, newBranch: newBranch, actionPending: actionPending, onClose: closeWorktreeCreator, onRetry: () => {
|
|
1004
|
+
if (worktreeModalWorkspaceId === undefined)
|
|
1005
|
+
return;
|
|
1006
|
+
modalReadViewRef.current = undefined;
|
|
1007
|
+
setSelectedBranch('');
|
|
1008
|
+
setNewBranch('');
|
|
1009
|
+
loadModalWorktreeView(worktreeModalWorkspaceId);
|
|
1010
|
+
}, onModeChange: changeWorktreeModalMode, onRetryImportCandidates: () => {
|
|
1011
|
+
if (worktreeModalWorkspaceId !== undefined) {
|
|
1012
|
+
void loadImportCandidates(worktreeModalWorkspaceId);
|
|
1013
|
+
}
|
|
1014
|
+
}, onSelectedImportPathChange: setSelectedImportPath, onSelectedBranchChange: setSelectedBranch, onNewBranchChange: setNewBranch, onSubmit: submitWorktree }), _jsx(WorktreeRemovalDialog, { t: t, worktree: worktreeRemoval, actionPending: actionPending, onClose: () => {
|
|
754
1015
|
setWorktreeRemoval(undefined);
|
|
755
1016
|
}, onSubmit: () => {
|
|
756
1017
|
if (manager === undefined || worktreeRemoval === undefined)
|