@cerbur/clutch-dsh-worktree 0.1.1 → 0.1.3
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 +20 -5
- package/lib/client/WorktreeContext.d.ts +15 -0
- package/lib/client/WorktreeContext.d.ts.map +1 -0
- package/lib/client/WorktreeContext.js +19 -0
- package/lib/client/WorktreeContext.js.map +1 -0
- package/lib/client/WorktreeHeroContext.d.ts +10 -0
- package/lib/client/WorktreeHeroContext.d.ts.map +1 -0
- package/lib/client/WorktreeHeroContext.js +128 -0
- package/lib/client/WorktreeHeroContext.js.map +1 -0
- package/lib/client/WorktreeOverlay.d.ts +6 -0
- package/lib/client/WorktreeOverlay.d.ts.map +1 -0
- package/lib/client/WorktreeOverlay.js +8 -0
- package/lib/client/WorktreeOverlay.js.map +1 -0
- package/lib/client/WorktreeSurface.d.ts +3 -1
- package/lib/client/WorktreeSurface.d.ts.map +1 -1
- package/lib/client/WorktreeSurface.js +204 -58
- package/lib/client/WorktreeSurface.js.map +1 -1
- package/lib/client/entry.d.ts +1 -1
- package/lib/client/entry.d.ts.map +1 -1
- package/lib/client/entry.js +41 -14
- package/lib/client/entry.js.map +1 -1
- package/lib/client/locales.d.ts +30 -0
- package/lib/client/locales.d.ts.map +1 -1
- package/lib/client/locales.js +32 -2
- package/lib/client/locales.js.map +1 -1
- package/lib/client/session-view.d.ts +21 -0
- package/lib/client/session-view.d.ts.map +1 -0
- package/lib/client/session-view.js +26 -0
- package/lib/client/session-view.js.map +1 -0
- package/lib/client/sidebar-overlay-geometry.d.ts +1 -0
- package/lib/client/sidebar-overlay-geometry.d.ts.map +1 -1
- package/lib/client/sidebar-overlay-geometry.js +28 -17
- package/lib/client/sidebar-overlay-geometry.js.map +1 -1
- package/lib/client/virtual-workspace-membership.d.ts.map +1 -1
- package/lib/client/virtual-workspace-membership.js +17 -6
- package/lib/client/virtual-workspace-membership.js.map +1 -1
- package/lib/client/worktree-connection.d.ts +1 -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 +45 -0
- package/lib/client/worktree-context-store.d.ts.map +1 -0
- package/lib/client/worktree-context-store.js +199 -0
- package/lib/client/worktree-context-store.js.map +1 -0
- package/lib/client/worktree-context.d.ts +32 -0
- package/lib/client/worktree-context.d.ts.map +1 -0
- package/lib/client/worktree-context.js +51 -0
- package/lib/client/worktree-context.js.map +1 -0
- package/lib/client/worktree-error-copy.d.ts.map +1 -1
- package/lib/client/worktree-error-copy.js +14 -0
- package/lib/client/worktree-error-copy.js.map +1 -1
- package/lib/client/worktree-session.d.ts +83 -0
- package/lib/client/worktree-session.d.ts.map +1 -0
- package/lib/client/worktree-session.js +185 -0
- package/lib/client/worktree-session.js.map +1 -0
- package/lib/client/worktree-view.d.ts +37 -3
- package/lib/client/worktree-view.d.ts.map +1 -1
- package/lib/client/worktree-view.js +145 -7
- package/lib/client/worktree-view.js.map +1 -1
- package/lib/client.js +1015 -134
- package/lib/client.js.map +1 -1
- package/lib/contract/index.contract.js +2 -0
- package/lib/contract/index.contract.js.map +1 -1
- package/lib/contract/index.d.ts +17 -2
- package/lib/contract/index.d.ts.map +1 -1
- package/lib/contract/index.js +2 -0
- package/lib/contract/index.js.map +1 -1
- package/lib/host/remote.d.ts.map +1 -1
- package/lib/host/remote.js +1 -0
- package/lib/host/remote.js.map +1 -1
- package/lib/host/service.d.ts +6 -1
- package/lib/host/service.d.ts.map +1 -1
- package/lib/host/service.js +6 -0
- package/lib/host/service.js.map +1 -1
- package/lib/manage/manager.d.ts +6 -1
- package/lib/manage/manager.d.ts.map +1 -1
- package/lib/manage/manager.js +12 -1
- package/lib/manage/manager.js.map +1 -1
- package/lib/provider/sidecar.d.ts +2 -1
- package/lib/provider/sidecar.d.ts.map +1 -1
- package/lib/provider/sidecar.js +40 -0
- package/lib/provider/sidecar.js.map +1 -1
- package/lib/provider/types.d.ts +2 -1
- package/lib/provider/types.d.ts.map +1 -1
- package/lib/provider/types.js.map +1 -1
- package/lib/typert.host.js +60 -18
- package/lib/typert.remote-client.d.ts +3 -1
- package/lib/typert.remote-client.d.ts.map +1 -1
- package/lib/typert.remote-client.js +60 -18
- package/package.json +6 -2
|
@@ -1,12 +1,24 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
2
|
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
|
3
|
-
import { Button, IconArchiveOutline20, IconBranchOutline16, IconChevronDownOutline14, IconChevronRightOutline14, IconCloseOutline16, IconEditOutline16, IconEllipsisOutline16, IconFolderClose16, IconFolderOpen16, IconPlusOutline16, IconSearchOutline16, IconTrashOutline16, Input, Menu, Modal, StateDot, } from '@deepseek-ai/dsh-client-ui-primitives';
|
|
3
|
+
import { Button, HoverCard, IconArchiveOutline20, IconBranchOutline16, IconChevronDownOutline14, IconChevronRightOutline14, IconCloseOutline16, IconEditOutline16, IconEllipsisOutline16, IconFolderClose16, IconFolderOpen16, IconPlusOutline16, IconSearchOutline16, IconTrashOutline16, Input, Menu, Modal, StateDot, } from '@deepseek-ai/dsh-client-ui-primitives';
|
|
4
4
|
import { openWorktreeSession } from './navigation.js';
|
|
5
5
|
import { useSidebarOverlayGeometry } from './sidebar-overlay-geometry.js';
|
|
6
6
|
import { effectiveViewMode, unboundSessionIds, workspaceSessionIds } from './view-mode.js';
|
|
7
7
|
import { formatWorktreeViewError } from './worktree-error-copy.js';
|
|
8
|
-
import {
|
|
8
|
+
import { filterVisibleSessionIds, isBlankSession, sessionDisplayLabel, sessionMatchesQuery, } from './session-view.js';
|
|
9
|
+
import { retryWorktreeSessionBinding } from './worktree-session.js';
|
|
10
|
+
import { executeWorktreeAction, createDefaultWorktreeName, createWorktreeRefreshGuard, filterArchivedSessionIds, loadWorktreeViews, reconcileBaseBranchSelection, resolveWorktreeMove, selectDefaultBaseBranch, stableWorkspaceIds, toRetryableWorktreeOrderError, toWorktreeViewError, WorktreeSessionBindingError, worktreeSetupCommands, } from './worktree-view.js';
|
|
9
11
|
import styles from './worktree.css';
|
|
12
|
+
function worktreeSetupMessage(status, t) {
|
|
13
|
+
switch (status) {
|
|
14
|
+
case 'noRepository':
|
|
15
|
+
return t('worktree.setup.noRepository');
|
|
16
|
+
case 'noInitialCommit':
|
|
17
|
+
return t('worktree.setup.noInitialCommit');
|
|
18
|
+
case 'noLocalBranch':
|
|
19
|
+
return t('worktree.setup.noLocalBranch');
|
|
20
|
+
}
|
|
21
|
+
}
|
|
10
22
|
function toNativeWorktreeViewError(error) {
|
|
11
23
|
const viewError = toWorktreeViewError(error);
|
|
12
24
|
if (typeof error === 'object' && error !== null)
|
|
@@ -22,8 +34,8 @@ function useStableWorkspaceIds(workspaces) {
|
|
|
22
34
|
previousRef.current = stable;
|
|
23
35
|
return previousRef.current;
|
|
24
36
|
}
|
|
25
|
-
function sessionLabel(sessionId, sessions) {
|
|
26
|
-
return
|
|
37
|
+
function sessionLabel(sessionId, sessions, t) {
|
|
38
|
+
return sessionDisplayLabel(sessionId, sessions, t('session.new'));
|
|
27
39
|
}
|
|
28
40
|
function rowHalf(event) {
|
|
29
41
|
const rect = event.currentTarget.getBoundingClientRect();
|
|
@@ -42,7 +54,7 @@ function workspaceMatches(workspace, view, sessions, query) {
|
|
|
42
54
|
return true;
|
|
43
55
|
if (includesText(workspace.title, query))
|
|
44
56
|
return true;
|
|
45
|
-
if (workspace.sessionIds.some((sessionId) =>
|
|
57
|
+
if (workspace.sessionIds.some((sessionId) => sessionMatchesQuery(sessionId, sessions, query))) {
|
|
46
58
|
return true;
|
|
47
59
|
}
|
|
48
60
|
if (view === undefined)
|
|
@@ -50,7 +62,7 @@ function workspaceMatches(workspace, view, sessions, query) {
|
|
|
50
62
|
if (view.worktrees.some((record) => includesText(record.branch, query) || includesText(record.absolutePath, query))) {
|
|
51
63
|
return true;
|
|
52
64
|
}
|
|
53
|
-
return view.bindings.some((binding) =>
|
|
65
|
+
return view.bindings.some((binding) => sessionMatchesQuery(binding.sessionId, sessions, query));
|
|
54
66
|
}
|
|
55
67
|
/** Workspace row using the native DSH menu, fixed action column, and drag contract. */
|
|
56
68
|
function WorktreeWorkspaceRow({ t, workspace, expanded, actionPending, menuOpen, drag, onToggle, onCreateWorktree, onRename, onDelete, onMenuOpenChange, }) {
|
|
@@ -113,9 +125,38 @@ function WorktreeWorkspaceRow({ t, workspace, expanded, actionPending, menuOpen,
|
|
|
113
125
|
}, children: _jsx(IconPlusOutline16, {}) })] })] }));
|
|
114
126
|
}
|
|
115
127
|
/** Shared Main/Worktree group row with parameterized icon, state, and actions. */
|
|
116
|
-
function WorktreeGroupRow({ t, kind, label, expanded, icon, workspaceTitle, state, stateLabel, onToggle, onCreateSession, menu, }) {
|
|
128
|
+
function WorktreeGroupRow({ t, kind, label, worktreeId, expanded, icon, workspaceTitle, state, stateLabel, onToggle, onCreateSession, menu, drag, }) {
|
|
117
129
|
const main = kind === 'main';
|
|
118
|
-
|
|
130
|
+
const markerClass = drag?.marker === 'before'
|
|
131
|
+
? styles.dropBefore
|
|
132
|
+
: drag?.marker === 'after'
|
|
133
|
+
? styles.dropAfter
|
|
134
|
+
: '';
|
|
135
|
+
const dragProps = drag === undefined
|
|
136
|
+
? {}
|
|
137
|
+
: {
|
|
138
|
+
draggable: true,
|
|
139
|
+
onDragStart: (event) => {
|
|
140
|
+
event.dataTransfer.effectAllowed = 'move';
|
|
141
|
+
event.dataTransfer.setData('text/plain', worktreeId ?? label);
|
|
142
|
+
drag.start();
|
|
143
|
+
},
|
|
144
|
+
onDragEnd: drag.end,
|
|
145
|
+
onDragOver: (event) => {
|
|
146
|
+
if (!drag.active)
|
|
147
|
+
return;
|
|
148
|
+
event.preventDefault();
|
|
149
|
+
event.dataTransfer.dropEffect = 'move';
|
|
150
|
+
drag.hover(rowHalf(event));
|
|
151
|
+
},
|
|
152
|
+
onDrop: (event) => {
|
|
153
|
+
if (!drag.active)
|
|
154
|
+
return;
|
|
155
|
+
event.preventDefault();
|
|
156
|
+
drag.drop(rowHalf(event));
|
|
157
|
+
},
|
|
158
|
+
};
|
|
159
|
+
const row = (_jsxs("div", { className: `${styles.worktreeRow} ${markerClass}`, "data-main-group": main ? 'true' : undefined, "data-main-expanded": main ? String(expanded) : undefined, "data-menu-open": menu?.open ? 'true' : undefined, "data-worktree-drag": drag?.active ? 'active' : undefined, ...dragProps, onClick: onToggle, children: [_jsx("button", { type: "button", className: `${styles.disclosureButton} ${styles.worktreeDisclosure}`, "aria-label": t(expanded ? 'worktree.collapse' : 'worktree.expand', { name: label }), "aria-expanded": expanded, onClick: (event) => {
|
|
119
160
|
event.stopPropagation();
|
|
120
161
|
onToggle();
|
|
121
162
|
}, children: expanded ? (_jsx(IconChevronDownOutline14, { size: 18 })) : (_jsx(IconChevronRightOutline14, { size: 18 })) }), _jsx("span", { className: styles.worktreeIcon, "aria-hidden": "true", children: icon }), state !== undefined && stateLabel !== undefined && (_jsx("span", { className: styles.worktreeState, role: "img", "aria-label": stateLabel, title: stateLabel, children: _jsx(StateDot, { state: state }) })), _jsx("span", { className: styles.worktreeLabel, children: label }), _jsxs("span", { className: styles.treeActionSlot, children: [menu !== undefined && (_jsx("span", { className: styles.menuAction, children: _jsx(Menu, { open: menu.open, onClose: () => {
|
|
@@ -139,9 +180,12 @@ function WorktreeGroupRow({ t, kind, label, expanded, icon, workspaceTitle, stat
|
|
|
139
180
|
event.stopPropagation();
|
|
140
181
|
onCreateSession();
|
|
141
182
|
}, children: _jsx(IconPlusOutline16, {}) }))] })] }));
|
|
183
|
+
if (main)
|
|
184
|
+
return row;
|
|
185
|
+
return (_jsx(HoverCard, { anchor: row, content: _jsx("div", { className: styles.worktreeHoverTitle, children: label }), openDelayMs: 500, disabled: menu?.open === true }));
|
|
142
186
|
}
|
|
143
187
|
/** Worktree-mode Session row with the same trailing options menu as native DSH rows. */
|
|
144
|
-
function WorktreeSessionRow({ t, sessionId, label, drag, actionPending, onOpen, onRename, onFork, onArchive, }) {
|
|
188
|
+
function WorktreeSessionRow({ t, sessionId, blank, label, drag, actionPending, onOpen, onRename, onFork, onArchive, }) {
|
|
145
189
|
const [menuOpen, setMenuOpen] = useState(false);
|
|
146
190
|
const markerClass = drag.marker === 'before'
|
|
147
191
|
? styles.dropBefore
|
|
@@ -168,7 +212,7 @@ function WorktreeSessionRow({ t, sessionId, label, drag, actionPending, onOpen,
|
|
|
168
212
|
disabled: onArchive === undefined || actionPending,
|
|
169
213
|
},
|
|
170
214
|
];
|
|
171
|
-
return (_jsxs("div", { className: `${styles.treeSessionRow} ${markerClass}`, "data-session-id": sessionId, "data-session-drag": drag.active ? 'active' : undefined, "data-menu-open": menuOpen || undefined, role: "treeitem", draggable: true, onDragStart: (event) => {
|
|
215
|
+
return (_jsxs("div", { className: `${styles.treeSessionRow} ${markerClass}`, "data-session-id": sessionId, "data-session-blank": blank ? 'true' : undefined, "data-session-drag": drag.active ? 'active' : undefined, "data-menu-open": menuOpen || undefined, role: "treeitem", draggable: true, onDragStart: (event) => {
|
|
172
216
|
event.dataTransfer.effectAllowed = 'move';
|
|
173
217
|
event.dataTransfer.setData('text/plain', sessionId);
|
|
174
218
|
drag.start();
|
|
@@ -183,7 +227,7 @@ function WorktreeSessionRow({ t, sessionId, label, drag, actionPending, onOpen,
|
|
|
183
227
|
return;
|
|
184
228
|
event.preventDefault();
|
|
185
229
|
drag.drop(rowHalf(event));
|
|
186
|
-
}, children: [_jsxs("button", { type: "button", className: styles.treeSessionContent, onClick: onOpen, children: [_jsx("span", { className: styles.treeGuide, "aria-hidden": "true", children: "\u2514" }), _jsx("span", { className: styles.sessionLabel, children: label })] }), _jsx("span", { className: styles.rowActions, children: _jsx(Menu, { open: menuOpen, onClose: () => {
|
|
230
|
+
}, children: [_jsxs("button", { type: "button", className: styles.treeSessionContent, onClick: onOpen, children: [_jsx("span", { className: styles.treeGuide, "aria-hidden": "true", children: "\u2514" }), _jsx("span", { className: styles.sessionLabel, children: label })] }), !blank && (_jsx("span", { className: styles.rowActions, children: _jsx(Menu, { open: menuOpen, onClose: () => {
|
|
187
231
|
setMenuOpen(false);
|
|
188
232
|
}, items: sessionMenuItems, onSelect: (id) => {
|
|
189
233
|
setMenuOpen(false);
|
|
@@ -196,12 +240,12 @@ function WorktreeSessionRow({ t, sessionId, label, drag, actionPending, onOpen,
|
|
|
196
240
|
}, portal: true, closeOnPointerLeave: true, anchor: (_jsx("button", { type: "button", className: styles.iconButton, "data-session-menu": true, "aria-label": t('session.options', { name: label }), onClick: (event) => {
|
|
197
241
|
event.stopPropagation();
|
|
198
242
|
setMenuOpen((current) => !current);
|
|
199
|
-
}, children: _jsx(IconEllipsisOutline16, {}) })) }) })] }));
|
|
243
|
+
}, children: _jsx(IconEllipsisOutline16, {}) })) }) }))] }));
|
|
200
244
|
}
|
|
201
245
|
function WorktreeSessionGroup({ t, groupKey, sessionIds, workspaceId, expanded, actionPending, sessions, dragState, onToggleExpanded, onStartDrag, onHoverDrag, onClearDrag, onFinishDrag, onCommitDrag, onOpen, onRename, onFork, onArchive, }) {
|
|
202
246
|
const visibleSessionIds = expanded ? sessionIds : sessionIds.slice(0, 5);
|
|
203
247
|
const sameGroupDrag = dragState?.groupKey === groupKey;
|
|
204
|
-
return (_jsxs(_Fragment, { children: [visibleSessionIds.map((sessionId) => (_jsx(WorktreeSessionRow, { t: t, sessionId: sessionId, label: sessionLabel(sessionId, sessions), drag: {
|
|
248
|
+
return (_jsxs(_Fragment, { children: [visibleSessionIds.map((sessionId) => (_jsx(WorktreeSessionRow, { t: t, sessionId: sessionId, blank: isBlankSession(sessionId, sessions), label: sessionLabel(sessionId, sessions, t), drag: {
|
|
205
249
|
active: sameGroupDrag,
|
|
206
250
|
marker: sameGroupDrag && dragState.over?.sessionId === sessionId
|
|
207
251
|
? dragState.over.half
|
|
@@ -236,13 +280,15 @@ function WorktreeSessionGroup({ t, groupKey, sessionIds, workspaceId, expanded,
|
|
|
236
280
|
* Peer Worktree navigation surface. It keeps the original DSH Workspace mode
|
|
237
281
|
* intact and renders a browser-local Workspace → Worktree → Session projection.
|
|
238
282
|
*/
|
|
239
|
-
export function WorktreeSurface({ useStore, actions, useSessions, useWorkspaces, t, available, manager, createWorkspace, createSessionForWorktree: createSessionCallback, createMainSession, renameWorkspace, deleteWorkspace, insertWorkspaceBefore, insertSessionBefore, renameSession, forkSession, archiveSession, ensureSessionWorkspace, syncSessionWorkspaces, openSession, }) {
|
|
283
|
+
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, }) {
|
|
240
284
|
const preferredMode = useStore((state) => state.viewMode);
|
|
241
285
|
const mode = effectiveViewMode(preferredMode, available && manager !== undefined);
|
|
242
286
|
const sessions = useSessions((state) => state);
|
|
243
287
|
const workspaces = useWorkspaces((state) => state);
|
|
244
288
|
const workspaceIds = useStableWorkspaceIds(workspaces.items);
|
|
245
289
|
const [readState, setReadState] = useState(EMPTY_READ_STATE);
|
|
290
|
+
const readStateRef = useRef(readState);
|
|
291
|
+
readStateRef.current = readState;
|
|
246
292
|
const [searchQuery, setSearchQuery] = useState('');
|
|
247
293
|
const [expandedWorkspaces, setExpandedWorkspaces] = useState({});
|
|
248
294
|
const [expandedMains, setExpandedMains] = useState({});
|
|
@@ -272,33 +318,46 @@ export function WorktreeSurface({ useStore, actions, useSessions, useWorkspaces,
|
|
|
272
318
|
const [sessionDrag, setSessionDrag] = useState();
|
|
273
319
|
const [expandedSessionGroups, setExpandedSessionGroups] = useState({});
|
|
274
320
|
const sessionDropCommitted = useRef(false);
|
|
321
|
+
const [worktreeDrag, setWorktreeDrag] = useState();
|
|
322
|
+
const worktreeDropCommitted = useRef(false);
|
|
323
|
+
const refreshGuard = useRef(createWorktreeRefreshGuard());
|
|
275
324
|
const { ref, width, bounds } = useSidebarOverlayGeometry(mode === 'worktree');
|
|
276
325
|
const collapsed = width <= 64;
|
|
277
326
|
const query = searchQuery.trim().toLocaleLowerCase();
|
|
278
327
|
const archivedSessionIds = workspaces.archivedSessionIds ?? [];
|
|
279
|
-
const
|
|
328
|
+
const pendingSessionArchived = pendingSessionBinding !== undefined &&
|
|
329
|
+
archivedSessionIds.includes(pendingSessionBinding.sessionId);
|
|
330
|
+
const refresh = useCallback(async (options = {}) => {
|
|
280
331
|
if (manager === undefined) {
|
|
332
|
+
refreshGuard.current.invalidate();
|
|
281
333
|
setReadState(EMPTY_READ_STATE);
|
|
282
334
|
return;
|
|
283
335
|
}
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
setReadState({ status: 'ready', views });
|
|
336
|
+
const preserveCurrent = options.preserveCurrent === true;
|
|
337
|
+
if (!preserveCurrent) {
|
|
338
|
+
setReadState({ status: 'loading', views: [] });
|
|
288
339
|
}
|
|
289
|
-
|
|
340
|
+
await refreshGuard.current.run(() => loadWorktreeViews(manager, workspaceIds, {
|
|
341
|
+
invalidateContext: options.invalidateContext !== false,
|
|
342
|
+
invalidateWorktreeContext,
|
|
343
|
+
}), (views) => {
|
|
344
|
+
setReadState({ status: 'ready', views });
|
|
345
|
+
}, (error) => {
|
|
346
|
+
if (preserveCurrent)
|
|
347
|
+
throw error;
|
|
290
348
|
setReadState({
|
|
291
349
|
status: 'error',
|
|
292
350
|
views: [],
|
|
293
351
|
error: toWorktreeViewError(error),
|
|
294
352
|
});
|
|
295
|
-
}
|
|
296
|
-
}, [manager, workspaceIds]);
|
|
353
|
+
});
|
|
354
|
+
}, [invalidateWorktreeContext, manager, workspaceIds]);
|
|
297
355
|
useEffect(() => {
|
|
298
356
|
if (mode === 'worktree') {
|
|
299
|
-
void refresh();
|
|
357
|
+
void refresh({ preserveCurrent: readStateRef.current.status === 'ready' });
|
|
300
358
|
}
|
|
301
359
|
else {
|
|
360
|
+
refreshGuard.current.invalidate();
|
|
302
361
|
setReadState(EMPTY_READ_STATE);
|
|
303
362
|
}
|
|
304
363
|
}, [mode, refresh]);
|
|
@@ -315,12 +374,28 @@ export function WorktreeSurface({ useStore, actions, useSessions, useWorkspaces,
|
|
|
315
374
|
const modalView = worktreeModalWorkspaceId === undefined
|
|
316
375
|
? undefined
|
|
317
376
|
: viewByWorkspace.get(worktreeModalWorkspaceId);
|
|
377
|
+
const modalReadiness = modalView?.readiness;
|
|
378
|
+
const modalSetupStatus = modalView === undefined
|
|
379
|
+
? undefined
|
|
380
|
+
: modalReadiness?.status === 'ready'
|
|
381
|
+
? modalView.branches.length === 0 ? 'noLocalBranch' : undefined
|
|
382
|
+
: modalReadiness?.status;
|
|
383
|
+
const modalCanCreate = modalSetupStatus === undefined && modalReadiness?.status === 'ready';
|
|
384
|
+
useEffect(() => {
|
|
385
|
+
if (worktreeModalWorkspaceId === undefined || modalView === undefined)
|
|
386
|
+
return;
|
|
387
|
+
if (modalView.readiness.status !== 'ready') {
|
|
388
|
+
setSelectedBranch('');
|
|
389
|
+
return;
|
|
390
|
+
}
|
|
391
|
+
setSelectedBranch((current) => reconcileBaseBranchSelection(current, modalView.branches));
|
|
392
|
+
}, [modalView, worktreeModalWorkspaceId]);
|
|
318
393
|
const runMutation = async (operation) => {
|
|
319
394
|
setActionPending(true);
|
|
320
395
|
setActionError(undefined);
|
|
321
396
|
try {
|
|
322
397
|
await operation();
|
|
323
|
-
await refresh();
|
|
398
|
+
await refresh({ preserveCurrent: true });
|
|
324
399
|
}
|
|
325
400
|
catch (error) {
|
|
326
401
|
setActionError(toWorktreeViewError(error));
|
|
@@ -480,6 +555,31 @@ export function WorktreeSurface({ useStore, actions, useSessions, useWorkspaces,
|
|
|
480
555
|
setActionError(toWorktreeViewError(error));
|
|
481
556
|
});
|
|
482
557
|
};
|
|
558
|
+
const commitWorktreeDrag = (activeDrag, over, worktreeIds, workspaceId) => {
|
|
559
|
+
if (worktreeDropCommitted.current)
|
|
560
|
+
return;
|
|
561
|
+
worktreeDropCommitted.current = true;
|
|
562
|
+
setWorktreeDrag(undefined);
|
|
563
|
+
if (activeDrag.workspaceId !== workspaceId)
|
|
564
|
+
return;
|
|
565
|
+
const move = resolveWorktreeMove(worktreeIds, activeDrag.worktreeId, over.worktreeId, over.half);
|
|
566
|
+
if (move === undefined)
|
|
567
|
+
return;
|
|
568
|
+
if (insertWorktreeBefore === undefined) {
|
|
569
|
+
setActionError({
|
|
570
|
+
code: 'WORKTREE_ORDER_UNAVAILABLE',
|
|
571
|
+
message: '',
|
|
572
|
+
retryable: true,
|
|
573
|
+
});
|
|
574
|
+
return;
|
|
575
|
+
}
|
|
576
|
+
setActionError(undefined);
|
|
577
|
+
void insertWorktreeBefore(workspaceId, activeDrag.worktreeId, move.beforeWorktreeId)
|
|
578
|
+
.then(() => refresh({ preserveCurrent: true, invalidateContext: false }))
|
|
579
|
+
.catch((error) => {
|
|
580
|
+
setActionError(toRetryableWorktreeOrderError(error));
|
|
581
|
+
});
|
|
582
|
+
};
|
|
483
583
|
const openSessionRename = (sessionId, currentTitle) => {
|
|
484
584
|
setSessionRenameTarget({ sessionId, currentTitle });
|
|
485
585
|
setSessionRenameDraft(currentTitle);
|
|
@@ -556,6 +656,7 @@ export function WorktreeSurface({ useStore, actions, useSessions, useWorkspaces,
|
|
|
556
656
|
const worktreeName = newBranch.trim();
|
|
557
657
|
if (manager === undefined ||
|
|
558
658
|
modalWorkspace === undefined ||
|
|
659
|
+
!modalCanCreate ||
|
|
559
660
|
selectedBranch.length === 0 ||
|
|
560
661
|
worktreeName.length === 0) {
|
|
561
662
|
return;
|
|
@@ -582,7 +683,7 @@ export function WorktreeSurface({ useStore, actions, useSessions, useWorkspaces,
|
|
|
582
683
|
}
|
|
583
684
|
setWorktreeModalWorkspaceId(undefined);
|
|
584
685
|
if (createSessionCallback === undefined) {
|
|
585
|
-
await refresh();
|
|
686
|
+
await refresh({ preserveCurrent: true });
|
|
586
687
|
setActionError({
|
|
587
688
|
code: 'WORKTREE_CREATED_SESSION_UNAVAILABLE',
|
|
588
689
|
message: '',
|
|
@@ -597,14 +698,15 @@ export function WorktreeSurface({ useStore, actions, useSessions, useWorkspaces,
|
|
|
597
698
|
};
|
|
598
699
|
try {
|
|
599
700
|
await createSessionCallback(sessionInput);
|
|
701
|
+
await invalidateWorktreeContext?.(createdWorktree.workspaceId);
|
|
600
702
|
}
|
|
601
703
|
catch (error) {
|
|
602
|
-
if (error instanceof WorktreeSessionBindingError) {
|
|
704
|
+
if (error instanceof WorktreeSessionBindingError && error.retryable) {
|
|
603
705
|
setPendingSessionBinding({ ...sessionInput, sessionId: error.sessionId });
|
|
604
706
|
}
|
|
605
707
|
throw error;
|
|
606
708
|
}
|
|
607
|
-
await refresh();
|
|
709
|
+
await refresh({ preserveCurrent: true });
|
|
608
710
|
}
|
|
609
711
|
catch (error) {
|
|
610
712
|
setActionError(toWorktreeViewError(error));
|
|
@@ -627,10 +729,11 @@ export function WorktreeSurface({ useStore, actions, useSessions, useWorkspaces,
|
|
|
627
729
|
setPendingSessionBinding(undefined);
|
|
628
730
|
try {
|
|
629
731
|
await createSessionCallback(input);
|
|
630
|
-
await
|
|
732
|
+
await invalidateWorktreeContext?.(input.workspaceId);
|
|
733
|
+
await refresh({ preserveCurrent: true });
|
|
631
734
|
}
|
|
632
735
|
catch (error) {
|
|
633
|
-
if (error instanceof WorktreeSessionBindingError) {
|
|
736
|
+
if (error instanceof WorktreeSessionBindingError && error.retryable) {
|
|
634
737
|
setPendingSessionBinding({ ...input, sessionId: error.sessionId });
|
|
635
738
|
}
|
|
636
739
|
setActionError(toWorktreeViewError(error));
|
|
@@ -640,23 +743,31 @@ export function WorktreeSurface({ useStore, actions, useSessions, useWorkspaces,
|
|
|
640
743
|
}
|
|
641
744
|
};
|
|
642
745
|
const retrySessionBinding = async () => {
|
|
643
|
-
if (manager === undefined ||
|
|
746
|
+
if (manager === undefined ||
|
|
747
|
+
pendingSessionBinding === undefined ||
|
|
748
|
+
pendingSessionArchived)
|
|
644
749
|
return;
|
|
750
|
+
const pending = pendingSessionBinding;
|
|
645
751
|
setActionPending(true);
|
|
646
752
|
setActionError(undefined);
|
|
647
753
|
try {
|
|
648
|
-
await
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
754
|
+
await retryWorktreeSessionBinding({
|
|
755
|
+
manager,
|
|
756
|
+
pending,
|
|
757
|
+
archived: false,
|
|
758
|
+
ensureSessionWorkspace: (workspaceId, sessionId) => {
|
|
759
|
+
ensureSessionWorkspace?.(workspaceId, sessionId);
|
|
760
|
+
},
|
|
761
|
+
openSession,
|
|
652
762
|
});
|
|
653
|
-
const sessionId = pendingSessionBinding.sessionId;
|
|
654
763
|
setPendingSessionBinding(undefined);
|
|
655
|
-
|
|
656
|
-
await
|
|
657
|
-
openSession(sessionId);
|
|
764
|
+
await refresh({ preserveCurrent: true });
|
|
765
|
+
await invalidateWorktreeContext?.(pending.workspaceId);
|
|
658
766
|
}
|
|
659
767
|
catch (error) {
|
|
768
|
+
if (error instanceof WorktreeSessionBindingError && !error.retryable) {
|
|
769
|
+
setPendingSessionBinding(undefined);
|
|
770
|
+
}
|
|
660
771
|
setActionError(toWorktreeViewError(error));
|
|
661
772
|
}
|
|
662
773
|
finally {
|
|
@@ -682,7 +793,7 @@ export function WorktreeSurface({ useStore, actions, useSessions, useWorkspaces,
|
|
|
682
793
|
} }), _jsx("button", { type: "button", className: styles.iconButton, "aria-label": t('workspace.add'), onClick: () => {
|
|
683
794
|
if (createWorkspace !== undefined)
|
|
684
795
|
void runMutation(createWorkspace);
|
|
685
|
-
}, children: _jsx(IconPlusOutline16, {}) })] }), _jsxs("div", { className: styles.content, tabIndex: 0, children: [actionError !== undefined && (_jsxs("div", { className: styles.error, role: "alert", "data-worktree-error": true, children: [_jsx("p", { className: styles.message, "data-error": "true", children: formatWorktreeViewError(actionError, t) }), pendingSessionBinding !== undefined && (_jsxs("div", { className: styles.recoveryActions, children: [_jsx("button", { type: "button", className: styles.actionButton, disabled: actionPending, onClick: () => {
|
|
796
|
+
}, children: _jsx(IconPlusOutline16, {}) })] }), _jsxs("div", { className: styles.content, tabIndex: 0, children: [actionError !== undefined && (_jsxs("div", { className: styles.error, role: "alert", "data-worktree-error": true, children: [_jsx("p", { className: styles.message, "data-error": "true", children: formatWorktreeViewError(actionError, t) }), pendingSessionBinding !== undefined && (_jsxs("div", { className: styles.recoveryActions, children: [_jsx("button", { type: "button", className: styles.actionButton, disabled: actionPending || pendingSessionArchived, onClick: () => {
|
|
686
797
|
void retrySessionBinding();
|
|
687
798
|
}, children: t('action.retryBinding') }), _jsx("button", { type: "button", className: styles.actionButton, disabled: actionPending, onClick: () => {
|
|
688
799
|
const sessionId = pendingSessionBinding.sessionId;
|
|
@@ -696,19 +807,21 @@ export function WorktreeSurface({ useStore, actions, useSessions, useWorkspaces,
|
|
|
696
807
|
void refresh();
|
|
697
808
|
}, children: t('action.retry') })] })) : readState.status === 'ready' ? (_jsx("div", { className: styles.workspaceList, children: visibleWorkspaces.length === 0 ? (_jsx("p", { className: styles.empty, children: t('workspace.noMatches') })) : (visibleWorkspaces.map((workspace) => {
|
|
698
809
|
const view = viewByWorkspace.get(workspace.workspaceId);
|
|
810
|
+
const currentBranch = view?.branches.find((branch) => branch.isCurrent)?.name;
|
|
811
|
+
const mainLabel = currentBranch === undefined
|
|
812
|
+
? t('worktree.main')
|
|
813
|
+
: t('worktree.mainWithBranch', { branch: currentBranch });
|
|
699
814
|
const expanded = expandedWorkspaces[workspace.workspaceId] !== false;
|
|
700
815
|
const workspaceMatchesQuery = includesText(workspace.title, query);
|
|
701
816
|
const allWorkspaceSessionIds = filterArchivedSessionIds(workspaceSessionIds(workspaces, workspace.workspaceId, sessions.ids), archivedSessionIds);
|
|
702
817
|
const bindings = view?.bindings ?? [];
|
|
703
818
|
const boundSessionIds = new Set(bindings.map((binding) => binding.sessionId));
|
|
704
|
-
const mainSessionIds = unboundSessionIds(allWorkspaceSessionIds, [
|
|
705
|
-
|
|
706
|
-
]);
|
|
707
|
-
const visibleMainSessionIds = mainSessionIds.filter((sessionId) => workspaceMatchesQuery ||
|
|
708
|
-
includesText(sessionLabel(sessionId, sessions), query));
|
|
819
|
+
const mainSessionIds = filterVisibleSessionIds(unboundSessionIds(allWorkspaceSessionIds, [...boundSessionIds]), sessions);
|
|
820
|
+
const visibleMainSessionIds = mainSessionIds.filter((sessionId) => workspaceMatchesQuery || sessionMatchesQuery(sessionId, sessions, query));
|
|
709
821
|
const mainExpanded = expandedMains[workspace.workspaceId] !== false;
|
|
710
822
|
const mainGroupKey = `main:${workspace.workspaceId}`;
|
|
711
823
|
const worktrees = view?.worktrees ?? [];
|
|
824
|
+
const sameWorkspaceWorktreeDrag = worktreeDrag?.workspaceId === workspace.workspaceId;
|
|
712
825
|
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: {
|
|
713
826
|
active: workspaceDrag !== undefined,
|
|
714
827
|
marker: workspaceDrag?.over?.workspaceId === workspace.workspaceId
|
|
@@ -753,7 +866,7 @@ export function WorktreeSurface({ useStore, actions, useSessions, useWorkspaces,
|
|
|
753
866
|
openWorkspaceDelete(workspace);
|
|
754
867
|
}, onMenuOpenChange: (open) => {
|
|
755
868
|
setOpenWorkspaceMenuId(open ? workspace.workspaceId : undefined);
|
|
756
|
-
} }), expanded && (_jsxs("div", { className: styles.treeChildren, children: [_jsx(WorktreeGroupRow, { t: t, kind: "main", label:
|
|
869
|
+
} }), expanded && (_jsxs("div", { className: styles.treeChildren, children: [_jsx(WorktreeGroupRow, { t: t, kind: "main", label: mainLabel, expanded: mainExpanded, icon: _jsx(IconBranchOutline16, {}), workspaceTitle: workspace.title, onToggle: () => {
|
|
757
870
|
toggleMain(workspace.workspaceId);
|
|
758
871
|
}, onCreateSession: createMainSession === undefined
|
|
759
872
|
? undefined
|
|
@@ -778,17 +891,16 @@ export function WorktreeSurface({ useStore, actions, useSessions, useWorkspaces,
|
|
|
778
891
|
}, onCommitDrag: commitSessionDrag, onOpen: (sessionId) => {
|
|
779
892
|
openWorktreeSession({ open: openSession }, sessionId);
|
|
780
893
|
}, onRename: renameSession === undefined ? undefined : openSessionRename, onFork: forkSession, onArchive: archiveSession === undefined ? undefined : archiveWorktreeSession })), worktrees.length === 0 && (_jsx("p", { className: styles.emptyNested, children: t('worktree.noWorktrees') })), worktrees.map((record) => {
|
|
781
|
-
const worktreeSessionIds = filterArchivedSessionIds(bindingIdsFor(bindings, record.worktreeId).filter((sessionId) => sessions.ids.includes(sessionId)), archivedSessionIds);
|
|
894
|
+
const worktreeSessionIds = filterVisibleSessionIds(filterArchivedSessionIds(bindingIdsFor(bindings, record.worktreeId).filter((sessionId) => sessions.ids.includes(sessionId)), archivedSessionIds), sessions);
|
|
782
895
|
const worktreeMatchesQuery = workspaceMatchesQuery ||
|
|
783
896
|
includesText(record.branch, query) ||
|
|
784
897
|
includesText(record.absolutePath, query);
|
|
785
898
|
if (query.length > 0 &&
|
|
786
899
|
!worktreeMatchesQuery &&
|
|
787
|
-
!worktreeSessionIds.some((sessionId) =>
|
|
900
|
+
!worktreeSessionIds.some((sessionId) => sessionMatchesQuery(sessionId, sessions, query))) {
|
|
788
901
|
return null;
|
|
789
902
|
}
|
|
790
|
-
const visibleWorktreeSessionIds = worktreeSessionIds.filter((sessionId) => worktreeMatchesQuery ||
|
|
791
|
-
includesText(sessionLabel(sessionId, sessions), query));
|
|
903
|
+
const visibleWorktreeSessionIds = worktreeSessionIds.filter((sessionId) => worktreeMatchesQuery || sessionMatchesQuery(sessionId, sessions, query));
|
|
792
904
|
const worktreeGroupKey = `worktree:${record.worktreeId}`;
|
|
793
905
|
const state = record.status === 'removed'
|
|
794
906
|
? 'warning'
|
|
@@ -801,9 +913,9 @@ export function WorktreeSurface({ useStore, actions, useSessions, useWorkspaces,
|
|
|
801
913
|
? t('worktree.repair')
|
|
802
914
|
: t('worktree.ready');
|
|
803
915
|
const worktreeExpanded = expandedWorktrees[record.worktreeId] !== false;
|
|
804
|
-
return (_jsxs("div", { className: styles.worktreeGroup, "data-worktree-id": record.worktreeId, children: [_jsx(WorktreeGroupRow, { t: t, kind: "worktree", label: record.branch, expanded: worktreeExpanded, icon: _jsx(IconBranchOutline16, {}), workspaceTitle: workspace.title, state: state, stateLabel: stateLabel, onToggle: () => {
|
|
916
|
+
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: () => {
|
|
805
917
|
toggleWorktree(record.worktreeId);
|
|
806
|
-
}, onCreateSession: record.status === 'active'
|
|
918
|
+
}, onCreateSession: record.status === 'active' && record.health !== 'repair'
|
|
807
919
|
? () => {
|
|
808
920
|
void createSession({
|
|
809
921
|
workspaceId: record.workspaceId,
|
|
@@ -824,7 +936,38 @@ export function WorktreeSurface({ useStore, actions, useSessions, useWorkspaces,
|
|
|
824
936
|
setActionError(undefined);
|
|
825
937
|
},
|
|
826
938
|
}
|
|
827
|
-
: undefined
|
|
939
|
+
: undefined, drag: {
|
|
940
|
+
active: sameWorkspaceWorktreeDrag,
|
|
941
|
+
marker: worktreeDrag?.over?.worktreeId === record.worktreeId
|
|
942
|
+
? worktreeDrag.over.half
|
|
943
|
+
: null,
|
|
944
|
+
start: () => {
|
|
945
|
+
worktreeDropCommitted.current = false;
|
|
946
|
+
setWorktreeDrag({
|
|
947
|
+
workspaceId: workspace.workspaceId,
|
|
948
|
+
worktreeId: record.worktreeId,
|
|
949
|
+
over: null,
|
|
950
|
+
});
|
|
951
|
+
},
|
|
952
|
+
hover: (half) => {
|
|
953
|
+
setWorktreeDrag((current) => current === undefined ||
|
|
954
|
+
current.workspaceId !== workspace.workspaceId
|
|
955
|
+
? current
|
|
956
|
+
: {
|
|
957
|
+
...current,
|
|
958
|
+
over: { worktreeId: record.worktreeId, half },
|
|
959
|
+
});
|
|
960
|
+
},
|
|
961
|
+
drop: (half) => {
|
|
962
|
+
if (worktreeDrag === undefined)
|
|
963
|
+
return;
|
|
964
|
+
commitWorktreeDrag(worktreeDrag, { worktreeId: record.worktreeId, half }, worktrees.map((candidate) => candidate.worktreeId), workspace.workspaceId);
|
|
965
|
+
},
|
|
966
|
+
end: () => {
|
|
967
|
+
setWorktreeDrag(undefined);
|
|
968
|
+
worktreeDropCommitted.current = false;
|
|
969
|
+
},
|
|
970
|
+
} }), worktreeExpanded && (_jsx(WorktreeSessionGroup, { t: t, groupKey: worktreeGroupKey, sessionIds: visibleWorktreeSessionIds, workspaceId: workspace.workspaceId, expanded: expandedSessionGroups[worktreeGroupKey] === true, actionPending: actionPending, sessions: sessions, dragState: sessionDrag, onToggleExpanded: () => {
|
|
828
971
|
setExpandedSessionGroups((current) => ({
|
|
829
972
|
...current,
|
|
830
973
|
[worktreeGroupKey]: current[worktreeGroupKey] !== true,
|
|
@@ -874,7 +1017,7 @@ export function WorktreeSurface({ useStore, actions, useSessions, useWorkspaces,
|
|
|
874
1017
|
}
|
|
875
1018
|
} }), workspaceRenameDuplicate && (_jsx("p", { className: styles.renameError, role: "alert", children: t('workspace.duplicate') })), workspaceRenameError !== undefined && (_jsx("p", { className: styles.renameError, role: "alert", children: formatWorktreeViewError(workspaceRenameError, t) }))] })), workspaceDeleteTarget !== undefined && (_jsx(Modal, { open: workspaceDeleteTarget !== undefined, onClose: closeWorkspaceDelete, closeLabel: t('dialog.closeWorkspaceDelete'), title: t('workspace.deleteTitle'), description: t('workspace.deleteDescription', { name: workspaceDeleteTarget.title }), footer: (_jsxs(_Fragment, { children: [_jsx(Button, { variant: "outline", disabled: workspaceDeletePending, onClick: closeWorkspaceDelete, children: t('dialog.cancel') }), _jsx(Button, { variant: "outline", disabled: workspaceDeletePending, onClick: () => {
|
|
876
1019
|
void confirmWorkspaceDelete();
|
|
877
|
-
}, children: t('dialog.delete') })] })), children: workspaceDeleteError !== undefined && (_jsx("p", { className: styles.renameError, role: "alert", children: formatWorktreeViewError(workspaceDeleteError, t) })) })), worktreeModalWorkspaceId !== undefined && modalWorkspace !== undefined && (
|
|
1020
|
+
}, children: t('dialog.delete') })] })), children: workspaceDeleteError !== undefined && (_jsx("p", { className: styles.renameError, role: "alert", children: formatWorktreeViewError(workspaceDeleteError, t) })) })), worktreeModalWorkspaceId !== undefined && modalWorkspace !== undefined && (_jsx(Modal, { open: worktreeModalWorkspaceId !== undefined, onClose: () => {
|
|
878
1021
|
if (actionPending)
|
|
879
1022
|
return;
|
|
880
1023
|
setWorktreeModalWorkspaceId(undefined);
|
|
@@ -884,11 +1027,13 @@ export function WorktreeSurface({ useStore, actions, useSessions, useWorkspaces,
|
|
|
884
1027
|
selectedBranch.length === 0 ||
|
|
885
1028
|
newBranch.trim().length === 0, onClick: () => {
|
|
886
1029
|
void submitWorktree();
|
|
887
|
-
}, children: t('worktree.create') })] })), children: [_jsxs("label", { className: styles.modalField, children: [t('worktree.baseBranch'),
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
1030
|
+
}, children: t('worktree.create') })] })), children: modalCanCreate ? (_jsxs(_Fragment, { children: [_jsxs("label", { className: styles.modalField, children: [t('worktree.baseBranch'), _jsx("select", { className: styles.actionSelect, "aria-label": t('worktree.baseBranch'), value: selectedBranch, disabled: actionPending, onChange: (event) => {
|
|
1031
|
+
setSelectedBranch(event.currentTarget.value);
|
|
1032
|
+
}, children: modalView?.branches.map((branch) => (_jsxs("option", { value: branch.name, children: [branch.name, branch.isCurrent ? t('branch.current') : '', branch.checkedOut ? t('branch.checkedOut') : ''] }, branch.name))) })] }), _jsxs("label", { className: styles.modalField, children: [t('worktree.name'), _jsx(Input, { className: styles.renameInput, "aria-label": t('worktree.name'), value: newBranch, placeholder: "dsh/12345678", disabled: actionPending, onChange: (event) => {
|
|
1033
|
+
setNewBranch(event.currentTarget.value);
|
|
1034
|
+
} })] })] })) : (_jsxs("div", { className: styles.gitReadiness, "data-worktree-readiness": modalSetupStatus ?? 'loading', role: "alert", children: [_jsx("p", { className: styles.message, children: modalSetupStatus === undefined
|
|
1035
|
+
? t('status.loading')
|
|
1036
|
+
: worktreeSetupMessage(modalSetupStatus, t) }), modalSetupStatus !== undefined && (_jsx("pre", { className: styles.commandBlock, "aria-label": t('worktree.setup.commands'), children: worktreeSetupCommands(modalSetupStatus).join('\n') }))] })) })), worktreeRemoval !== undefined && (_jsx(Modal, { open: worktreeRemoval !== undefined, onClose: () => {
|
|
892
1037
|
if (actionPending)
|
|
893
1038
|
return;
|
|
894
1039
|
setWorktreeRemoval(undefined);
|
|
@@ -906,6 +1051,7 @@ export function WorktreeSurface({ useStore, actions, useSessions, useWorkspaces,
|
|
|
906
1051
|
worktreeId: target.worktreeId,
|
|
907
1052
|
},
|
|
908
1053
|
});
|
|
1054
|
+
await invalidateWorktreeContext?.(target.workspaceId);
|
|
909
1055
|
setWorktreeRemoval(undefined);
|
|
910
1056
|
});
|
|
911
1057
|
}, children: t('worktree.remove') })] })) }))] }));
|