@cerbur/clutch-dsh-worktree 0.1.5 → 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 +66 -15
- package/README.zh.md +59 -13
- package/lib/client/WorktreeHeroContext.d.ts +1 -1
- package/lib/client/WorktreeHeroContext.js +1 -1
- package/lib/client/WorktreeSurface.d.ts +1 -1
- package/lib/client/WorktreeSurface.d.ts.map +1 -1
- package/lib/client/WorktreeSurface.js +348 -85
- 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 +24 -0
- package/lib/client/locales.d.ts.map +1 -1
- package/lib/client/locales.js +26 -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-error-copy.d.ts.map +1 -1
- package/lib/client/worktree-error-copy.js +6 -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 +30 -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 +8 -0
- package/lib/client/worktree-view-read.d.ts.map +1 -1
- package/lib/client/worktree-view-read.js +19 -0
- package/lib/client/worktree-view-read.js.map +1 -1
- package/lib/client.js +612 -101
- 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 +4 -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 +2 -0
- package/lib/provider/git.d.ts.map +1 -1
- package/lib/provider/git.js +23 -1
- 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
package/lib/client.js
CHANGED
|
@@ -42,10 +42,18 @@ window.__ModuleLoader__.load({
|
|
|
42
42
|
"worktree.options": "Worktree 选项:{name}",
|
|
43
43
|
"worktree.remove": "移除 Worktree",
|
|
44
44
|
"worktree.removeDescription": "移除“{name}”?Session 会保留在 DSH 中,并作为已分离关系继续可用。",
|
|
45
|
+
"worktree.removeExternalDescription": "移除“{name}”?这会删除关联的外部 Worktree 目录。Session 会保留在 DSH 中,并作为已分离关系继续可用。",
|
|
45
46
|
"worktree.addSession": "向 {name} 添加会话",
|
|
46
47
|
"worktree.noWorktrees": "暂无 Worktree",
|
|
47
48
|
"worktree.createTitle": "新建 Worktree",
|
|
48
49
|
"worktree.createDescription": "“{name}” · Worktree 路径由 DSH 管理。",
|
|
50
|
+
"worktree.tabCreate": "创建",
|
|
51
|
+
"worktree.tabImport": "导入",
|
|
52
|
+
"worktree.importDescription": "向“{name}”注册已有的 Worktree。注册不会移动目录;之后移除会删除关联的 Worktree 目录。",
|
|
53
|
+
"worktree.importLoading": "正在查找可导入的 Worktree…",
|
|
54
|
+
"worktree.importEmpty": "没有可导入的 Worktree。",
|
|
55
|
+
"worktree.importPlaceholder": "请选择要导入的 Worktree",
|
|
56
|
+
"worktree.importSelected": "已选择",
|
|
49
57
|
"worktree.baseBranch": "Worktree 基线分支",
|
|
50
58
|
"worktree.noLocalBranch": "没有本地分支",
|
|
51
59
|
"worktree.noBranches": "此工作区中没有找到本地分支。",
|
|
@@ -56,6 +64,7 @@ window.__ModuleLoader__.load({
|
|
|
56
64
|
"worktree.setup.commands": "可复制的命令",
|
|
57
65
|
"worktree.name": "Worktree 名称",
|
|
58
66
|
"worktree.create": "创建 Worktree",
|
|
67
|
+
"worktree.import": "导入 Worktree",
|
|
59
68
|
"session.options": "会话选项:{name}",
|
|
60
69
|
"session.new": "新会话",
|
|
61
70
|
"session.rename": "重命名会话",
|
|
@@ -86,7 +95,10 @@ window.__ModuleLoader__.load({
|
|
|
86
95
|
"error.worktreeOrderingUnavailable": "Worktree 排序不可用,请重新连接后重试。",
|
|
87
96
|
"error.worktreeCreatedSessionUnavailable": "Worktree 已创建,但 Session 创建不可用,请重新连接后重试。",
|
|
88
97
|
"error.sessionCreationUnavailable": "Session 创建不可用,请重新连接后重试。",
|
|
89
|
-
"error.worktreeRecordMissing": "Worktree
|
|
98
|
+
"error.worktreeRecordMissing": "Worktree 注册未返回 Worktree 记录,请重试请求。",
|
|
99
|
+
"error.worktreeImportInvalid": "这个 Worktree 无法导入,请选择同一 Workspace 中有效的绝对路径。",
|
|
100
|
+
"error.worktreeAlreadyManaged": "这个 Worktree 已由插件管理。",
|
|
101
|
+
"error.worktreeRegistrationSessionUnavailable": "Worktree 已注册,但 Session 创建不可用,请重新连接后重试。",
|
|
90
102
|
"error.workspaceRenameUnavailable": "工作区重命名不可用,请重新连接后重试。",
|
|
91
103
|
"error.workspaceDeleteUnavailable": "工作区删除不可用,请重新连接后重试。",
|
|
92
104
|
"error.sessionRenameUnavailable": "会话重命名不可用,请重新连接后重试。",
|
|
@@ -132,10 +144,18 @@ window.__ModuleLoader__.load({
|
|
|
132
144
|
"worktree.options": "Worktree options for {name}",
|
|
133
145
|
"worktree.remove": "Remove Worktree",
|
|
134
146
|
"worktree.removeDescription": "Remove {name}? Sessions stay in DSH and remain available as detached bindings.",
|
|
147
|
+
"worktree.removeExternalDescription": "Remove {name}? This deletes the linked external Worktree directory. Sessions stay in DSH and remain available as detached bindings.",
|
|
135
148
|
"worktree.addSession": "Add Session to {name}",
|
|
136
149
|
"worktree.noWorktrees": "No Worktrees",
|
|
137
150
|
"worktree.createTitle": "New Worktree",
|
|
138
151
|
"worktree.createDescription": "{name} · the Worktree path is managed by DSH.",
|
|
152
|
+
"worktree.tabCreate": "Create",
|
|
153
|
+
"worktree.tabImport": "Import",
|
|
154
|
+
"worktree.importDescription": "Register an existing Worktree for {name}. Registration leaves the directory in place; removing it later deletes the linked Worktree directory.",
|
|
155
|
+
"worktree.importLoading": "Finding importable Worktrees…",
|
|
156
|
+
"worktree.importEmpty": "No importable Worktrees found.",
|
|
157
|
+
"worktree.importPlaceholder": "Select a Worktree to import",
|
|
158
|
+
"worktree.importSelected": "Selected",
|
|
139
159
|
"worktree.baseBranch": "Worktree base branch",
|
|
140
160
|
"worktree.noLocalBranch": "No local branch",
|
|
141
161
|
"worktree.noBranches": "No local branches found in this Workspace.",
|
|
@@ -146,6 +166,7 @@ window.__ModuleLoader__.load({
|
|
|
146
166
|
"worktree.setup.commands": "Copyable commands",
|
|
147
167
|
"worktree.name": "Worktree name",
|
|
148
168
|
"worktree.create": "Create Worktree",
|
|
169
|
+
"worktree.import": "Import Worktree",
|
|
149
170
|
"session.options": "Session options for {name}",
|
|
150
171
|
"session.new": "New Session",
|
|
151
172
|
"session.rename": "Rename session",
|
|
@@ -176,7 +197,10 @@ window.__ModuleLoader__.load({
|
|
|
176
197
|
"error.worktreeOrderingUnavailable": "Worktree ordering is unavailable; retry after reconnecting.",
|
|
177
198
|
"error.worktreeCreatedSessionUnavailable": "Worktree created, but Session creation is unavailable; retry after reconnecting.",
|
|
178
199
|
"error.sessionCreationUnavailable": "Session creation is unavailable; retry after reconnecting.",
|
|
179
|
-
"error.worktreeRecordMissing": "Worktree
|
|
200
|
+
"error.worktreeRecordMissing": "Worktree registration returned no Worktree record; retry the request.",
|
|
201
|
+
"error.worktreeImportInvalid": "This Worktree cannot be imported. Choose a valid absolute path in this Workspace.",
|
|
202
|
+
"error.worktreeAlreadyManaged": "This Worktree is already managed by the plugin.",
|
|
203
|
+
"error.worktreeRegistrationSessionUnavailable": "The Worktree was registered, but Session creation is unavailable; retry after reconnecting.",
|
|
180
204
|
"error.workspaceRenameUnavailable": "Workspace rename is unavailable; retry after reconnecting.",
|
|
181
205
|
"error.workspaceDeleteUnavailable": "Workspace delete is unavailable; retry after reconnecting.",
|
|
182
206
|
"error.sessionRenameUnavailable": "Session rename is unavailable; retry after reconnecting.",
|
|
@@ -200,8 +224,10 @@ window.__ModuleLoader__.load({
|
|
|
200
224
|
*/
|
|
201
225
|
const WORKTREE_CONNECTION_ENDPOINTS = Object.freeze({
|
|
202
226
|
listWorktrees: "worktreeManager/listWorktrees",
|
|
227
|
+
listImportCandidates: "worktreeManager/listImportCandidates",
|
|
203
228
|
listBranches: "worktreeManager/listBranches",
|
|
204
229
|
createWorktree: "worktreeManager/createWorktree",
|
|
230
|
+
importWorktree: "worktreeManager/importWorktree",
|
|
205
231
|
removeWorktree: "worktreeManager/removeWorktree",
|
|
206
232
|
insertWorktreeBefore: "worktreeManager/insertWorktreeBefore",
|
|
207
233
|
listBindings: "worktreeManager/listBindings",
|
|
@@ -220,14 +246,14 @@ window.__ModuleLoader__.load({
|
|
|
220
246
|
this.retryable = options.retryable;
|
|
221
247
|
}
|
|
222
248
|
};
|
|
223
|
-
function isRecord(value) {
|
|
249
|
+
function isRecord$1(value) {
|
|
224
250
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
225
251
|
}
|
|
226
252
|
function isWorktreeError(value) {
|
|
227
|
-
return isRecord(value) && typeof value.code === "string" && typeof value.message === "string" && isRecord(value.details);
|
|
253
|
+
return isRecord$1(value) && typeof value.code === "string" && typeof value.message === "string" && isRecord$1(value.details);
|
|
228
254
|
}
|
|
229
255
|
function isWorktreeRemoteResult(value) {
|
|
230
|
-
if (!isRecord(value) || typeof value.ok !== "boolean") return false;
|
|
256
|
+
if (!isRecord$1(value) || typeof value.ok !== "boolean") return false;
|
|
231
257
|
return value.ok || isWorktreeError(value.error) && value.error.details !== void 0;
|
|
232
258
|
}
|
|
233
259
|
function disposedError() {
|
|
@@ -248,7 +274,7 @@ window.__ModuleLoader__.load({
|
|
|
248
274
|
});
|
|
249
275
|
}
|
|
250
276
|
function gatewayFailure(endpoint, result) {
|
|
251
|
-
const rawDetails = isRecord(result.error.details) ? result.error.details : {};
|
|
277
|
+
const rawDetails = isRecord$1(result.error.details) ? result.error.details : {};
|
|
252
278
|
throw new WorktreeConnectionError({
|
|
253
279
|
code: result.error.code,
|
|
254
280
|
message: result.error.message,
|
|
@@ -305,8 +331,10 @@ window.__ModuleLoader__.load({
|
|
|
305
331
|
}
|
|
306
332
|
return {
|
|
307
333
|
listWorktrees: (input) => invoke("listWorktrees", input),
|
|
334
|
+
listImportCandidates: (input) => invoke("listImportCandidates", input),
|
|
308
335
|
listBranches: (input) => invoke("listBranches", input),
|
|
309
336
|
createWorktree: (input) => invoke("createWorktree", input),
|
|
337
|
+
importWorktree: (input) => invoke("importWorktree", input),
|
|
310
338
|
async removeWorktree(input) {
|
|
311
339
|
await invoke("removeWorktree", input);
|
|
312
340
|
},
|
|
@@ -324,7 +352,7 @@ window.__ModuleLoader__.load({
|
|
|
324
352
|
};
|
|
325
353
|
}
|
|
326
354
|
//#endregion
|
|
327
|
-
//#region \0clutch-dsh-worktree-css:/
|
|
355
|
+
//#region \0clutch-dsh-worktree-css:/Users/yuancheng/.dsh/clutch-dsh-worktree/worktree/wt_0c53e50f-f169-4c5e-9664-1c2d58ae1212/packages/clutch-dsh-worktree/src/client/worktree-context.css.mjs
|
|
328
356
|
const css$1 = ".-cerbur-clutch-dsh-worktree-headerContext {\n display: inline-flex;\n min-width: 0;\n height: 22px;\n align-items: center;\n gap: 4px;\n max-width: 180px;\n overflow: hidden;\n border-radius: 6px;\n padding: 0 2px 0 0;\n background: var(--dsw-alias-fill-tsp-secondary);\n color: var(--dsw-alias-label-secondary);\n font-size: 12px;\n line-height: 22px;\n white-space: nowrap;\n}\n\n.-cerbur-clutch-dsh-worktree-contextIcon {\n flex: none;\n opacity: 0.7;\n}\n\n.-cerbur-clutch-dsh-worktree-contextLabel {\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.-cerbur-clutch-dsh-worktree-contextHoverTitle {\n max-width: 360px;\n color: var(--dsw-static-neutral-bluish-00);\n font-size: 14px;\n line-height: 20px;\n overflow-wrap: anywhere;\n white-space: normal;\n}\n\n.-cerbur-clutch-dsh-worktree-heroContextHost {\n position: absolute;\n z-index: 1;\n display: block;\n width: max-content;\n max-width: 260px;\n min-height: 22px;\n}\n\n.-cerbur-clutch-dsh-worktree-heroContext {\n display: inline-flex;\n box-sizing: border-box;\n max-width: 260px;\n min-height: 22px;\n align-items: center;\n overflow: hidden;\n border: 1px solid var(--dsw-alias-border-l2);\n border-radius: 999px;\n padding: 0 8px;\n background: var(--dsw-alias-bg-layer-1);\n color: var(--dsw-alias-label-secondary);\n font-size: 12px;\n line-height: 20px;\n pointer-events: auto;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n";
|
|
329
357
|
const styleId$1 = "@cerbur/clutch-dsh-worktree/worktree-context.css";
|
|
330
358
|
if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=\"@cerbur/clutch-dsh-worktree/worktree-context.css\"]") === null) {
|
|
@@ -371,8 +399,8 @@ window.__ModuleLoader__.load({
|
|
|
371
399
|
});
|
|
372
400
|
}
|
|
373
401
|
//#endregion
|
|
374
|
-
//#region \0clutch-dsh-worktree-css:/
|
|
375
|
-
const css = ".-cerbur-clutch-dsh-worktree-action {\n display: flex;\n align-items: center;\n justify-content: flex-start;\n gap: 8px;\n width: calc(100% + 4px);\n height: 42px;\n margin: 4px -2px;\n box-sizing: border-box;\n border: 0;\n border-radius: 12px;\n padding: 0 10px 0 8px;\n background: transparent;\n color: var(--dsw-alias-label-primary);\n cursor: pointer;\n font: inherit;\n font-size: 14px;\n line-height: 22px;\n text-align: left;\n overflow: hidden;\n}\n\n.-cerbur-clutch-dsh-worktree-action:hover,\n.-cerbur-clutch-dsh-worktree-action[data-active='true'] {\n background: var(--dsw-alias-interactive-bg-hover);\n}\n\n.-cerbur-clutch-dsh-worktree-action[data-collapsed='true'] {\n width: 36px;\n height: 36px;\n margin: 8px 0 10px;\n justify-content: center;\n gap: 0;\n padding: 0;\n border-radius: 50%;\n}\n\n.-cerbur-clutch-dsh-worktree-actionLabel {\n display: inline-flex;\n min-width: 0;\n align-items: center;\n height: 22px;\n overflow: hidden;\n font-weight: 400;\n line-height: 22px;\n white-space: nowrap;\n}\n\n.-cerbur-clutch-dsh-worktree-surface {\n position: absolute;\n top: 0;\n left: 0;\n display: flex;\n flex-direction: column;\n box-sizing: border-box;\n min-width: 56px;\n overflow: hidden;\n border-right: 1px solid var(--dsw-alias-border-l1);\n background: var(--dsw-specific-sidebar-fill);\n color: var(--dsw-alias-label-primary);\n pointer-events: auto;\n transition: width var(--ds-transition-duration-slow) var(--ds-ease-in-out);\n}\n\n@media (prefers-reduced-motion: reduce) {\n .-cerbur-clutch-dsh-worktree-surface {\n transition: none;\n }\n}\n\n.-cerbur-clutch-dsh-worktree-wideContent {\n display: flex;\n min-width: 0;\n min-height: 0;\n flex: 1;\n flex-direction: column;\n}\n\n.-cerbur-clutch-dsh-worktree-surface[data-collapsed='true'] .-cerbur-clutch-dsh-worktree-wideContent {\n display: none;\n}\n\n.-cerbur-clutch-dsh-worktree-closeButton {\n border: 0;\n border-radius: 8px;\n background: transparent;\n color: inherit;\n cursor: pointer;\n font: inherit;\n}\n\n.-cerbur-clutch-dsh-worktree-closeButton:hover {\n background: var(--dsw-alias-interactive-bg-hover);\n}\n\n.-cerbur-clutch-dsh-worktree-header {\n display: flex;\n align-items: center;\n gap: 8px;\n flex: none;\n min-height: 44px;\n padding: 6px 10px;\n box-sizing: border-box;\n border-bottom: 1px solid var(--dsw-alias-border-l1);\n}\n\n.-cerbur-clutch-dsh-worktree-title {\n min-width: 0;\n flex: 1;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n font-size: 14px;\n font-weight: 600;\n}\n\n.-cerbur-clutch-dsh-worktree-closeButton {\n flex: none;\n width: 28px;\n height: 28px;\n font-size: 18px;\n line-height: 1;\n}\n\n.-cerbur-clutch-dsh-worktree-modeButton[data-active='true'] {\n color: var(--dsw-alias-label-primary);\n}\n\n.-cerbur-clutch-dsh-worktree-workspacePicker {\n display: block;\n width: calc(100% - 20px);\n margin: 6px 10px 8px;\n padding: 6px 8px;\n border: 1px solid var(--dsw-alias-border-l2);\n border-radius: 7px;\n background: var(--dsw-alias-button-elevated-fill);\n color: var(--dsw-alias-label-primary);\n font: inherit;\n font-size: 12px;\n}\n\n.-cerbur-clutch-dsh-worktree-workspaceLabel {\n display: block;\n color: var(--dsw-alias-label-tertiary);\n font-size: 11px;\n}\n\n.-cerbur-clutch-dsh-worktree-content {\n min-height: 0;\n flex: 1;\n overflow: auto;\n padding: 0 10px 12px;\n}\n\n.-cerbur-clutch-dsh-worktree-content:focus-visible {\n outline: 2px solid var(--dsw-alias-border-l3);\n outline-offset: -2px;\n}\n\n.-cerbur-clutch-dsh-worktree-error {\n margin: 12px 0 0;\n padding: 8px;\n border: 1px solid var(--dsw-alias-state-error-primary);\n border-radius: 7px;\n}\n\n.-cerbur-clutch-dsh-worktree-retryButton,\n.-cerbur-clutch-dsh-worktree-actionButton {\n border: 0;\n border-radius: 6px;\n background: var(--dsw-alias-button-elevated-fill);\n color: var(--dsw-alias-label-primary);\n cursor: pointer;\n font: inherit;\n font-size: 11px;\n}\n\n.-cerbur-clutch-dsh-worktree-retryButton,\n.-cerbur-clutch-dsh-worktree-actionButton {\n width: 100%;\n padding: 6px 8px;\n}\n\n.-cerbur-clutch-dsh-worktree-recoveryActions {\n display: grid;\n gap: 6px;\n margin-top: 6px;\n}\n\n.-cerbur-clutch-dsh-worktree-retryButton:disabled,\n.-cerbur-clutch-dsh-worktree-actionButton:disabled {\n cursor: not-allowed;\n opacity: 0.5;\n}\n\n.-cerbur-clutch-dsh-worktree-actions {\n display: grid;\n gap: 6px;\n margin-top: 10px;\n padding: 8px;\n border: 1px solid var(--dsw-alias-border-l1);\n border-radius: 7px;\n}\n\n.-cerbur-clutch-dsh-worktree-actionSelect {\n min-width: 0;\n padding: 5px 6px;\n border: 1px solid var(--dsw-alias-border-l2);\n border-radius: 6px;\n background: var(--dsw-alias-button-elevated-fill);\n color: var(--dsw-alias-label-primary);\n font: inherit;\n font-size: 11px;\n}\n\n.-cerbur-clutch-dsh-worktree-section {\n margin: 12px 0 0;\n}\n\n.-cerbur-clutch-dsh-worktree-sectionTitle {\n margin: 0 2px 4px;\n color: var(--dsw-alias-label-tertiary);\n font-size: 11px;\n font-weight: 600;\n letter-spacing: 0.02em;\n text-transform: uppercase;\n}\n\n.-cerbur-clutch-dsh-worktree-empty,\n.-cerbur-clutch-dsh-worktree-message {\n margin: 0;\n padding: 8px 4px;\n color: var(--dsw-alias-label-tertiary);\n font-size: 12px;\n line-height: 18px;\n}\n\n.-cerbur-clutch-dsh-worktree-gitReadiness {\n display: grid;\n gap: 4px;\n}\n\n.-cerbur-clutch-dsh-worktree-commandBlock {\n margin: 6px 0 0;\n padding: 8px;\n overflow-x: auto;\n border-radius: 6px;\n background: var(--dsw-alias-button-elevated-fill);\n color: var(--dsw-alias-label-secondary);\n font: 11px/16px ui-monospace, SFMono-Regular, Menlo, monospace;\n white-space: pre-wrap;\n}\n\n.-cerbur-clutch-dsh-worktree-message[data-error='true'] {\n color: var(--dsw-alias-state-error-primary);\n}\n\n.-cerbur-clutch-dsh-worktree-worktree,\n.-cerbur-clutch-dsh-worktree-session {\n display: flex;\n align-items: center;\n width: 100%;\n min-width: 0;\n box-sizing: border-box;\n border: 0;\n border-radius: 7px;\n padding: 6px 8px;\n background: transparent;\n color: var(--dsw-alias-label-primary);\n font: inherit;\n font-size: 12px;\n text-align: left;\n}\n\n.-cerbur-clutch-dsh-worktree-worktree {\n cursor: default;\n}\n\n.-cerbur-clutch-dsh-worktree-session {\n cursor: pointer;\n}\n\n.-cerbur-clutch-dsh-worktree-worktree:hover,\n.-cerbur-clutch-dsh-worktree-session:hover {\n background: var(--dsw-alias-interactive-bg-hover);\n}\n\n.-cerbur-clutch-dsh-worktree-worktreeLabel,\n.-cerbur-clutch-dsh-worktree-sessionLabel {\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.-cerbur-clutch-dsh-worktree-status {\n flex: none;\n margin-left: auto;\n padding-left: 8px;\n color: var(--dsw-alias-label-tertiary);\n font-size: 11px;\n}\n\n.-cerbur-clutch-dsh-worktree-searchRow {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 8px 10px 6px;\n}\n\n.-cerbur-clutch-dsh-worktree-searchIcon {\n display: inline-flex;\n flex: none;\n align-items: center;\n justify-content: center;\n color: var(--dsw-alias-label-secondary);\n}\n\n.-cerbur-clutch-dsh-worktree-searchInput {\n min-width: 0;\n box-sizing: border-box;\n border: 1px solid var(--dsw-alias-border-l2);\n border-radius: 7px;\n background: var(--dsw-alias-button-elevated-fill);\n color: var(--dsw-alias-label-primary);\n font: inherit;\n outline: none;\n}\n\n.-cerbur-clutch-dsh-worktree-searchInput {\n width: 100%;\n padding: 6px 8px;\n font-size: 13px;\n line-height: 18px;\n}\n\n.-cerbur-clutch-dsh-worktree-searchInput:focus,\n.-cerbur-clutch-dsh-worktree-actionSelect:focus {\n border-color: #3b82f6;\n}\n\n.-cerbur-clutch-dsh-worktree-iconButton {\n display: inline-flex;\n flex: none;\n align-items: center;\n justify-content: center;\n width: 28px;\n height: 28px;\n border: 0;\n border-radius: 7px;\n background: transparent;\n color: var(--dsw-alias-label-secondary);\n cursor: pointer;\n font: inherit;\n font-size: 20px;\n line-height: 1;\n}\n\n.-cerbur-clutch-dsh-worktree-iconButton:hover {\n background: var(--dsw-alias-interactive-bg-hover);\n color: var(--dsw-alias-label-primary);\n}\n\n.-cerbur-clutch-dsh-worktree-workspaceList {\n min-width: 0;\n min-height: 0;\n display: grid;\n gap: 4px;\n overflow-x: hidden;\n}\n\n.-cerbur-clutch-dsh-worktree-workspaceGroup {\n min-width: 0;\n}\n\n.-cerbur-clutch-dsh-worktree-workspaceRow,\n.-cerbur-clutch-dsh-worktree-worktreeRow {\n position: relative;\n display: flex;\n align-items: center;\n min-width: 0;\n min-height: 36px;\n box-sizing: border-box;\n border-radius: 8px;\n padding: 3px 4px;\n}\n\n.-cerbur-clutch-dsh-worktree-workspaceRow:hover,\n.-cerbur-clutch-dsh-worktree-worktreeRow:hover {\n background: var(--dsw-alias-interactive-bg-hover);\n}\n\n.-cerbur-clutch-dsh-worktree-workspaceRow .-cerbur-clutch-dsh-worktree-workspaceDisclosure {\n display: none;\n}\n\n.-cerbur-clutch-dsh-worktree-workspaceRow:hover .-cerbur-clutch-dsh-worktree-workspaceDisclosure,\n.-cerbur-clutch-dsh-worktree-workspaceRow[data-menu-open='true'] .-cerbur-clutch-dsh-worktree-workspaceDisclosure {\n display: inline-flex;\n}\n\n.-cerbur-clutch-dsh-worktree-workspaceRow:hover .-cerbur-clutch-dsh-worktree-workspaceIcon,\n.-cerbur-clutch-dsh-worktree-workspaceRow[data-menu-open='true'] .-cerbur-clutch-dsh-worktree-workspaceIcon {\n display: none;\n}\n\n.-cerbur-clutch-dsh-worktree-worktreeRow .-cerbur-clutch-dsh-worktree-worktreeDisclosure {\n display: none;\n}\n\n.-cerbur-clutch-dsh-worktree-worktreeRow:hover .-cerbur-clutch-dsh-worktree-worktreeDisclosure,\n.-cerbur-clutch-dsh-worktree-worktreeRow[data-menu-open='true'] .-cerbur-clutch-dsh-worktree-worktreeDisclosure {\n display: inline-flex;\n}\n\n.-cerbur-clutch-dsh-worktree-worktreeRow:hover .-cerbur-clutch-dsh-worktree-worktreeIcon,\n.-cerbur-clutch-dsh-worktree-worktreeRow[data-menu-open='true'] .-cerbur-clutch-dsh-worktree-worktreeIcon {\n display: none;\n}\n\n.-cerbur-clutch-dsh-worktree-disclosureButton {\n flex: none;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 24px;\n height: 28px;\n border: 0;\n border-radius: 6px;\n padding: 0;\n background: transparent;\n color: var(--dsw-alias-label-secondary);\n cursor: pointer;\n font: inherit;\n font-size: 17px;\n line-height: 1;\n}\n\n.-cerbur-clutch-dsh-worktree-disclosureButton > svg {\n display: block;\n}\n\n.-cerbur-clutch-dsh-worktree-disclosureButton:hover {\n background: var(--dsw-alias-interactive-bg-hover);\n}\n\n.-cerbur-clutch-dsh-worktree-workspaceIcon,\n.-cerbur-clutch-dsh-worktree-worktreeIcon {\n flex: none;\n width: 24px;\n color: var(--dsw-alias-label-secondary);\n font-size: 20px;\n line-height: 1;\n text-align: center;\n}\n\n.-cerbur-clutch-dsh-worktree-worktreeState {\n display: inline-flex;\n flex: none;\n align-items: center;\n justify-content: center;\n width: 12px;\n margin-right: 0;\n}\n\n.-cerbur-clutch-dsh-worktree-workspaceIcon {\n color: var(--dsw-alias-brand-primary);\n}\n\n.-cerbur-clutch-dsh-worktree-workspaceTitle,\n.-cerbur-clutch-dsh-worktree-worktreeLabel {\n min-width: 0;\n overflow: hidden;\n flex: 1;\n padding: 0 6px;\n text-overflow: ellipsis;\n white-space: nowrap;\n font-size: 14px;\n font-weight: 400;\n line-height: 20px;\n}\n\n.-cerbur-clutch-dsh-worktree-worktreeRow[data-main-group='true'] .-cerbur-clutch-dsh-worktree-worktreeLabel {\n font-weight: 600;\n}\n\n.-cerbur-clutch-dsh-worktree-worktreeHoverTitle {\n color: var(--dsw-static-neutral-bluish-00);\n font-size: 14px;\n line-height: 20px;\n overflow-wrap: anywhere;\n}\n\n.-cerbur-clutch-dsh-worktree-treeActionSlot,\n.-cerbur-clutch-dsh-worktree-workspaceActions {\n position: relative;\n display: inline-flex;\n flex: 0 0 64px;\n align-items: center;\n justify-content: flex-end;\n width: 64px;\n height: 28px;\n margin-left: auto;\n}\n\n.-cerbur-clutch-dsh-worktree-treeActionSlot > .-cerbur-clutch-dsh-worktree-menuAction {\n position: absolute;\n top: 0;\n right: 32px;\n}\n\n.-cerbur-clutch-dsh-worktree-treeActionSlot > .-cerbur-clutch-dsh-worktree-iconButton:last-child {\n position: absolute;\n top: 0;\n right: 0;\n}\n\n.-cerbur-clutch-dsh-worktree-menuAction {\n display: inline-flex;\n width: 28px;\n height: 28px;\n visibility: hidden;\n}\n\n.-cerbur-clutch-dsh-worktree-workspaceRow:hover .-cerbur-clutch-dsh-worktree-menuAction,\n.-cerbur-clutch-dsh-worktree-workspaceRow[data-menu-open='true'] .-cerbur-clutch-dsh-worktree-menuAction,\n.-cerbur-clutch-dsh-worktree-worktreeRow:hover .-cerbur-clutch-dsh-worktree-menuAction,\n.-cerbur-clutch-dsh-worktree-worktreeRow[data-menu-open='true'] .-cerbur-clutch-dsh-worktree-menuAction {\n visibility: visible;\n}\n\n.-cerbur-clutch-dsh-worktree-workspaceRow.-cerbur-clutch-dsh-worktree-dropBefore::before,\n.-cerbur-clutch-dsh-worktree-workspaceRow.-cerbur-clutch-dsh-worktree-dropAfter::after {\n position: absolute;\n right: 4px;\n left: 4px;\n height: 2px;\n border-radius: 2px;\n background: var(--dsw-alias-brand-primary);\n content: '';\n}\n\n.-cerbur-clutch-dsh-worktree-workspaceRow.-cerbur-clutch-dsh-worktree-dropBefore::before {\n top: -1px;\n}\n\n.-cerbur-clutch-dsh-worktree-workspaceRow.-cerbur-clutch-dsh-worktree-dropAfter::after {\n bottom: -1px;\n}\n\n.-cerbur-clutch-dsh-worktree-worktreeRow.-cerbur-clutch-dsh-worktree-dropBefore::before,\n.-cerbur-clutch-dsh-worktree-worktreeRow.-cerbur-clutch-dsh-worktree-dropAfter::after {\n position: absolute;\n right: 4px;\n left: 4px;\n height: 2px;\n border-radius: 2px;\n background: var(--dsw-alias-brand-primary);\n content: '';\n}\n\n.-cerbur-clutch-dsh-worktree-worktreeRow.-cerbur-clutch-dsh-worktree-dropBefore::before {\n top: -1px;\n}\n\n.-cerbur-clutch-dsh-worktree-worktreeRow.-cerbur-clutch-dsh-worktree-dropAfter::after {\n bottom: -1px;\n}\n\n.-cerbur-clutch-dsh-worktree-treeChildren {\n margin-left: 24px;\n padding: 2px 0 5px 12px;\n border-left: 1px solid var(--dsw-alias-border-l1);\n}\n\n.-cerbur-clutch-dsh-worktree-groupLabel {\n padding: 6px 8px 3px;\n color: var(--dsw-alias-label-tertiary);\n font-size: 10px;\n font-weight: 600;\n letter-spacing: 0.05em;\n text-transform: uppercase;\n}\n\n.-cerbur-clutch-dsh-worktree-groupHeader {\n display: flex;\n align-items: center;\n min-height: 34px;\n padding-right: 4px;\n}\n\n.-cerbur-clutch-dsh-worktree-groupHeader .-cerbur-clutch-dsh-worktree-groupLabel {\n flex: 1;\n}\n\n.-cerbur-clutch-dsh-worktree-worktreeGroup {\n margin-top: 2px;\n}\n\n.-cerbur-clutch-dsh-worktree-worktreeRow {\n min-height: 34px;\n}\n\n.-cerbur-clutch-dsh-worktree-worktreeRow .-cerbur-clutch-dsh-worktree-worktreeIcon,\n.-cerbur-clutch-dsh-worktree-worktreeRow .-cerbur-clutch-dsh-worktree-disclosureButton {\n width: 22px;\n}\n\n.-cerbur-clutch-dsh-worktree-treeSessionRow {\n position: relative;\n display: flex;\n align-items: center;\n width: 100%;\n min-width: 0;\n min-height: 31px;\n box-sizing: border-box;\n border-radius: 7px;\n}\n\n.-cerbur-clutch-dsh-worktree-treeSessionRow:hover,\n.-cerbur-clutch-dsh-worktree-treeSessionRow[data-menu-open='true'] {\n background: var(--dsw-alias-interactive-bg-hover);\n}\n\n.-cerbur-clutch-dsh-worktree-treeSessionRow.-cerbur-clutch-dsh-worktree-dropBefore::before,\n.-cerbur-clutch-dsh-worktree-treeSessionRow.-cerbur-clutch-dsh-worktree-dropAfter::after {\n position: absolute;\n right: 4px;\n left: 4px;\n height: 2px;\n border-radius: 2px;\n background: var(--dsw-alias-brand-primary);\n content: '';\n}\n\n.-cerbur-clutch-dsh-worktree-treeSessionRow.-cerbur-clutch-dsh-worktree-dropBefore::before {\n top: -1px;\n}\n\n.-cerbur-clutch-dsh-worktree-treeSessionRow.-cerbur-clutch-dsh-worktree-dropAfter::after {\n bottom: -1px;\n}\n\n.-cerbur-clutch-dsh-worktree-treeSessionContent {\n display: flex;\n align-items: center;\n flex: 1;\n width: 0;\n min-width: 0;\n min-height: 31px;\n box-sizing: border-box;\n border: 0;\n border-radius: 7px;\n padding: 4px 4px;\n background: transparent;\n color: var(--dsw-alias-label-primary);\n cursor: pointer;\n font: inherit;\n font-size: 14px;\n font-weight: 400;\n line-height: 20px;\n text-align: left;\n}\n\n.-cerbur-clutch-dsh-worktree-treeSessionContent:hover {\n background: transparent;\n}\n\n.-cerbur-clutch-dsh-worktree-rowActions {\n display: none;\n flex: none;\n align-items: center;\n gap: 4px;\n}\n\n.-cerbur-clutch-dsh-worktree-sessionOverflowButton {\n display: block;\n width: calc(100% - 24px);\n margin: 2px 0 4px 24px;\n padding: 4px 8px;\n border: 0;\n border-radius: 6px;\n background: transparent;\n color: var(--dsw-alias-label-secondary);\n cursor: pointer;\n font: inherit;\n font-size: 12px;\n font-weight: 400;\n line-height: 20px;\n text-align: left;\n}\n\n.-cerbur-clutch-dsh-worktree-sessionOverflowButton:hover {\n background: var(--dsw-alias-interactive-bg-hover);\n color: var(--dsw-alias-label-primary);\n}\n\n.-cerbur-clutch-dsh-worktree-treeSessionRow:hover .-cerbur-clutch-dsh-worktree-rowActions,\n.-cerbur-clutch-dsh-worktree-treeSessionRow[data-menu-open='true'] .-cerbur-clutch-dsh-worktree-rowActions {\n display: inline-flex;\n}\n\n.-cerbur-clutch-dsh-worktree-renameInput {\n width: 100%;\n}\n\n.-cerbur-clutch-dsh-worktree-renameError {\n margin: 8px 0 0;\n color: var(--dsw-alias-state-error-primary);\n font-size: 13px;\n line-height: 20px;\n}\n\n.-cerbur-clutch-dsh-worktree-treeGuide {\n flex: none;\n width: 20px;\n color: var(--dsw-alias-label-tertiary);\n text-align: center;\n}\n\n.-cerbur-clutch-dsh-worktree-emptyNested {\n margin: 0;\n padding: 4px 8px 5px 28px;\n color: var(--dsw-alias-label-tertiary);\n font-size: 11px;\n}\n\n.-cerbur-clutch-dsh-worktree-modalField {\n display: grid;\n gap: 5px;\n color: var(--dsw-alias-label-secondary);\n font-size: 12px;\n}\n";
|
|
402
|
+
//#region \0clutch-dsh-worktree-css:/Users/yuancheng/.dsh/clutch-dsh-worktree/worktree/wt_0c53e50f-f169-4c5e-9664-1c2d58ae1212/packages/clutch-dsh-worktree/src/client/worktree.css.mjs
|
|
403
|
+
const css = ".-cerbur-clutch-dsh-worktree-action {\n display: flex;\n align-items: center;\n justify-content: flex-start;\n gap: 8px;\n width: calc(100% + 4px);\n height: 42px;\n margin: 4px -2px;\n box-sizing: border-box;\n border: 0;\n border-radius: 12px;\n padding: 0 10px 0 8px;\n background: transparent;\n color: var(--dsw-alias-label-primary);\n cursor: pointer;\n font: inherit;\n font-size: 14px;\n line-height: 22px;\n text-align: left;\n overflow: hidden;\n}\n\n.-cerbur-clutch-dsh-worktree-action:hover,\n.-cerbur-clutch-dsh-worktree-action[data-active='true'] {\n background: var(--dsw-alias-interactive-bg-hover);\n}\n\n.-cerbur-clutch-dsh-worktree-action[data-collapsed='true'] {\n width: 36px;\n height: 36px;\n margin: 8px 0 10px;\n justify-content: center;\n gap: 0;\n padding: 0;\n border-radius: 50%;\n}\n\n.-cerbur-clutch-dsh-worktree-actionLabel {\n display: inline-flex;\n min-width: 0;\n align-items: center;\n height: 22px;\n overflow: hidden;\n font-weight: 400;\n line-height: 22px;\n white-space: nowrap;\n}\n\n.-cerbur-clutch-dsh-worktree-surface {\n position: absolute;\n top: 0;\n left: 0;\n display: flex;\n flex-direction: column;\n box-sizing: border-box;\n min-width: 56px;\n overflow: hidden;\n border-right: 1px solid var(--dsw-alias-border-l1);\n background: var(--dsw-specific-sidebar-fill);\n color: var(--dsw-alias-label-primary);\n pointer-events: auto;\n transition: width var(--ds-transition-duration-slow) var(--ds-ease-in-out);\n}\n\n@media (prefers-reduced-motion: reduce) {\n .-cerbur-clutch-dsh-worktree-surface {\n transition: none;\n }\n}\n\n.-cerbur-clutch-dsh-worktree-wideContent {\n display: flex;\n min-width: 0;\n min-height: 0;\n flex: 1;\n flex-direction: column;\n}\n\n.-cerbur-clutch-dsh-worktree-surface[data-collapsed='true'] .-cerbur-clutch-dsh-worktree-wideContent {\n display: none;\n}\n\n.-cerbur-clutch-dsh-worktree-worktreeModalTabs {\n display: flex;\n gap: 8px;\n margin-bottom: 12px;\n}\n\n.-cerbur-clutch-dsh-worktree-worktreeModalTab {\n border: 0;\n border-bottom: 2px solid transparent;\n padding: 4px 0;\n background: transparent;\n color: var(--dsw-alias-label-secondary);\n cursor: pointer;\n font: inherit;\n}\n\n.-cerbur-clutch-dsh-worktree-worktreeModalTab[aria-selected='true'] {\n border-bottom-color: var(--dsw-alias-label-primary);\n color: var(--dsw-alias-label-primary);\n}\n\n.-cerbur-clutch-dsh-worktree-worktreeImportCandidates {\n display: grid;\n gap: 8px;\n}\n\n.-cerbur-clutch-dsh-worktree-worktreeImportSelect {\n width: 100%;\n min-width: 0;\n padding: 7px 8px;\n border: 1px solid var(--dsw-alias-border-l2);\n border-radius: 6px;\n background: var(--dsw-alias-button-elevated-fill);\n color: var(--dsw-alias-label-primary);\n font: inherit;\n font-size: 13px;\n}\n\n.-cerbur-clutch-dsh-worktree-worktreeImportError {\n display: grid;\n gap: 8px;\n}\n\n.-cerbur-clutch-dsh-worktree-closeButton {\n border: 0;\n border-radius: 8px;\n background: transparent;\n color: inherit;\n cursor: pointer;\n font: inherit;\n}\n\n.-cerbur-clutch-dsh-worktree-closeButton:hover {\n background: var(--dsw-alias-interactive-bg-hover);\n}\n\n.-cerbur-clutch-dsh-worktree-header {\n display: flex;\n align-items: center;\n gap: 8px;\n flex: none;\n min-height: 44px;\n padding: 6px 10px;\n box-sizing: border-box;\n border-bottom: 1px solid var(--dsw-alias-border-l1);\n}\n\n.-cerbur-clutch-dsh-worktree-title {\n min-width: 0;\n flex: 1;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n font-size: 14px;\n font-weight: 600;\n}\n\n.-cerbur-clutch-dsh-worktree-closeButton {\n flex: none;\n width: 28px;\n height: 28px;\n font-size: 18px;\n line-height: 1;\n}\n\n.-cerbur-clutch-dsh-worktree-modeButton[data-active='true'] {\n color: var(--dsw-alias-label-primary);\n}\n\n.-cerbur-clutch-dsh-worktree-workspacePicker {\n display: block;\n width: calc(100% - 20px);\n margin: 6px 10px 8px;\n padding: 6px 8px;\n border: 1px solid var(--dsw-alias-border-l2);\n border-radius: 7px;\n background: var(--dsw-alias-button-elevated-fill);\n color: var(--dsw-alias-label-primary);\n font: inherit;\n font-size: 12px;\n}\n\n.-cerbur-clutch-dsh-worktree-workspaceLabel {\n display: block;\n color: var(--dsw-alias-label-tertiary);\n font-size: 11px;\n}\n\n.-cerbur-clutch-dsh-worktree-content {\n min-height: 0;\n flex: 1;\n overflow: auto;\n padding: 0 10px 12px;\n}\n\n.-cerbur-clutch-dsh-worktree-content:focus-visible {\n outline: 2px solid var(--dsw-alias-border-l3);\n outline-offset: -2px;\n}\n\n.-cerbur-clutch-dsh-worktree-error {\n margin: 12px 0 0;\n padding: 8px;\n border: 1px solid var(--dsw-alias-state-error-primary);\n border-radius: 7px;\n}\n\n.-cerbur-clutch-dsh-worktree-retryButton,\n.-cerbur-clutch-dsh-worktree-actionButton {\n border: 0;\n border-radius: 6px;\n background: var(--dsw-alias-button-elevated-fill);\n color: var(--dsw-alias-label-primary);\n cursor: pointer;\n font: inherit;\n font-size: 11px;\n}\n\n.-cerbur-clutch-dsh-worktree-retryButton,\n.-cerbur-clutch-dsh-worktree-actionButton {\n width: 100%;\n padding: 6px 8px;\n}\n\n.-cerbur-clutch-dsh-worktree-recoveryActions {\n display: grid;\n gap: 6px;\n margin-top: 6px;\n}\n\n.-cerbur-clutch-dsh-worktree-retryButton:disabled,\n.-cerbur-clutch-dsh-worktree-actionButton:disabled {\n cursor: not-allowed;\n opacity: 0.5;\n}\n\n.-cerbur-clutch-dsh-worktree-actions {\n display: grid;\n gap: 6px;\n margin-top: 10px;\n padding: 8px;\n border: 1px solid var(--dsw-alias-border-l1);\n border-radius: 7px;\n}\n\n.-cerbur-clutch-dsh-worktree-actionSelect {\n min-width: 0;\n padding: 5px 6px;\n border: 1px solid var(--dsw-alias-border-l2);\n border-radius: 6px;\n background: var(--dsw-alias-button-elevated-fill);\n color: var(--dsw-alias-label-primary);\n font: inherit;\n font-size: 11px;\n}\n\n.-cerbur-clutch-dsh-worktree-section {\n margin: 12px 0 0;\n}\n\n.-cerbur-clutch-dsh-worktree-sectionTitle {\n margin: 0 2px 4px;\n color: var(--dsw-alias-label-tertiary);\n font-size: 11px;\n font-weight: 600;\n letter-spacing: 0.02em;\n text-transform: uppercase;\n}\n\n.-cerbur-clutch-dsh-worktree-empty,\n.-cerbur-clutch-dsh-worktree-message {\n margin: 0;\n padding: 8px 4px;\n color: var(--dsw-alias-label-tertiary);\n font-size: 12px;\n line-height: 18px;\n}\n\n.-cerbur-clutch-dsh-worktree-gitReadiness {\n display: grid;\n gap: 4px;\n}\n\n.-cerbur-clutch-dsh-worktree-commandBlock {\n margin: 6px 0 0;\n padding: 8px;\n overflow-x: auto;\n border-radius: 6px;\n background: var(--dsw-alias-button-elevated-fill);\n color: var(--dsw-alias-label-secondary);\n font: 11px/16px ui-monospace, SFMono-Regular, Menlo, monospace;\n white-space: pre-wrap;\n}\n\n.-cerbur-clutch-dsh-worktree-message[data-error='true'] {\n color: var(--dsw-alias-state-error-primary);\n}\n\n.-cerbur-clutch-dsh-worktree-worktree,\n.-cerbur-clutch-dsh-worktree-session {\n display: flex;\n align-items: center;\n width: 100%;\n min-width: 0;\n box-sizing: border-box;\n border: 0;\n border-radius: 7px;\n padding: 6px 8px;\n background: transparent;\n color: var(--dsw-alias-label-primary);\n font: inherit;\n font-size: 12px;\n text-align: left;\n}\n\n.-cerbur-clutch-dsh-worktree-worktree {\n cursor: default;\n}\n\n.-cerbur-clutch-dsh-worktree-session {\n cursor: pointer;\n}\n\n.-cerbur-clutch-dsh-worktree-worktree:hover,\n.-cerbur-clutch-dsh-worktree-session:hover {\n background: var(--dsw-alias-interactive-bg-hover);\n}\n\n.-cerbur-clutch-dsh-worktree-worktreeLabel,\n.-cerbur-clutch-dsh-worktree-sessionLabel {\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.-cerbur-clutch-dsh-worktree-status {\n flex: none;\n margin-left: auto;\n padding-left: 8px;\n color: var(--dsw-alias-label-tertiary);\n font-size: 11px;\n}\n\n.-cerbur-clutch-dsh-worktree-searchRow {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 8px 10px 6px;\n}\n\n.-cerbur-clutch-dsh-worktree-searchIcon {\n display: inline-flex;\n flex: none;\n align-items: center;\n justify-content: center;\n color: var(--dsw-alias-label-secondary);\n}\n\n.-cerbur-clutch-dsh-worktree-searchInput {\n min-width: 0;\n box-sizing: border-box;\n border: 1px solid var(--dsw-alias-border-l2);\n border-radius: 7px;\n background: var(--dsw-alias-button-elevated-fill);\n color: var(--dsw-alias-label-primary);\n font: inherit;\n outline: none;\n}\n\n.-cerbur-clutch-dsh-worktree-searchInput {\n width: 100%;\n padding: 6px 8px;\n font-size: 13px;\n line-height: 18px;\n}\n\n.-cerbur-clutch-dsh-worktree-searchInput:focus,\n.-cerbur-clutch-dsh-worktree-actionSelect:focus,\n.-cerbur-clutch-dsh-worktree-worktreeImportSelect:focus {\n border-color: #3b82f6;\n}\n\n.-cerbur-clutch-dsh-worktree-iconButton {\n display: inline-flex;\n flex: none;\n align-items: center;\n justify-content: center;\n width: 28px;\n height: 28px;\n border: 0;\n border-radius: 7px;\n background: transparent;\n color: var(--dsw-alias-label-secondary);\n cursor: pointer;\n font: inherit;\n font-size: 20px;\n line-height: 1;\n}\n\n.-cerbur-clutch-dsh-worktree-iconButton:hover {\n background: var(--dsw-alias-interactive-bg-hover);\n color: var(--dsw-alias-label-primary);\n}\n\n.-cerbur-clutch-dsh-worktree-workspaceList {\n min-width: 0;\n min-height: 0;\n display: grid;\n gap: 4px;\n overflow-x: hidden;\n}\n\n.-cerbur-clutch-dsh-worktree-workspaceGroup {\n min-width: 0;\n}\n\n.-cerbur-clutch-dsh-worktree-workspaceRow,\n.-cerbur-clutch-dsh-worktree-worktreeRow {\n position: relative;\n display: flex;\n align-items: center;\n min-width: 0;\n min-height: 36px;\n box-sizing: border-box;\n border-radius: 8px;\n padding: 3px 4px;\n}\n\n.-cerbur-clutch-dsh-worktree-workspaceRow:hover,\n.-cerbur-clutch-dsh-worktree-worktreeRow:hover {\n background: var(--dsw-alias-interactive-bg-hover);\n}\n\n.-cerbur-clutch-dsh-worktree-workspaceRow .-cerbur-clutch-dsh-worktree-workspaceDisclosure {\n display: none;\n}\n\n.-cerbur-clutch-dsh-worktree-workspaceRow:hover .-cerbur-clutch-dsh-worktree-workspaceDisclosure,\n.-cerbur-clutch-dsh-worktree-workspaceRow[data-menu-open='true'] .-cerbur-clutch-dsh-worktree-workspaceDisclosure {\n display: inline-flex;\n}\n\n.-cerbur-clutch-dsh-worktree-workspaceRow:hover .-cerbur-clutch-dsh-worktree-workspaceIcon,\n.-cerbur-clutch-dsh-worktree-workspaceRow[data-menu-open='true'] .-cerbur-clutch-dsh-worktree-workspaceIcon {\n display: none;\n}\n\n.-cerbur-clutch-dsh-worktree-worktreeRow .-cerbur-clutch-dsh-worktree-worktreeDisclosure {\n display: none;\n}\n\n.-cerbur-clutch-dsh-worktree-worktreeRow:hover .-cerbur-clutch-dsh-worktree-worktreeDisclosure,\n.-cerbur-clutch-dsh-worktree-worktreeRow[data-menu-open='true'] .-cerbur-clutch-dsh-worktree-worktreeDisclosure {\n display: inline-flex;\n}\n\n.-cerbur-clutch-dsh-worktree-worktreeRow:hover .-cerbur-clutch-dsh-worktree-worktreeIcon,\n.-cerbur-clutch-dsh-worktree-worktreeRow[data-menu-open='true'] .-cerbur-clutch-dsh-worktree-worktreeIcon {\n display: none;\n}\n\n.-cerbur-clutch-dsh-worktree-disclosureButton {\n flex: none;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 24px;\n height: 28px;\n border: 0;\n border-radius: 6px;\n padding: 0;\n background: transparent;\n color: var(--dsw-alias-label-secondary);\n cursor: pointer;\n font: inherit;\n font-size: 17px;\n line-height: 1;\n}\n\n.-cerbur-clutch-dsh-worktree-disclosureButton > svg {\n display: block;\n}\n\n.-cerbur-clutch-dsh-worktree-disclosureButton:hover {\n background: var(--dsw-alias-interactive-bg-hover);\n}\n\n.-cerbur-clutch-dsh-worktree-workspaceIcon,\n.-cerbur-clutch-dsh-worktree-worktreeIcon {\n flex: none;\n width: 24px;\n color: var(--dsw-alias-label-secondary);\n font-size: 20px;\n line-height: 1;\n text-align: center;\n}\n\n.-cerbur-clutch-dsh-worktree-worktreeState {\n display: inline-flex;\n flex: none;\n align-items: center;\n justify-content: center;\n width: 12px;\n margin-right: 0;\n}\n\n.-cerbur-clutch-dsh-worktree-workspaceIcon {\n color: var(--dsw-alias-brand-primary);\n}\n\n.-cerbur-clutch-dsh-worktree-workspaceTitle,\n.-cerbur-clutch-dsh-worktree-worktreeLabel {\n min-width: 0;\n overflow: hidden;\n flex: 1;\n padding: 0 6px;\n text-overflow: ellipsis;\n white-space: nowrap;\n font-size: 14px;\n font-weight: 400;\n line-height: 20px;\n}\n\n.-cerbur-clutch-dsh-worktree-worktreeRow[data-main-group='true'] .-cerbur-clutch-dsh-worktree-worktreeLabel {\n font-weight: 600;\n}\n\n.-cerbur-clutch-dsh-worktree-worktreeHoverTitle {\n color: var(--dsw-static-neutral-bluish-00);\n font-size: 14px;\n line-height: 20px;\n overflow-wrap: anywhere;\n}\n\n.-cerbur-clutch-dsh-worktree-treeActionSlot,\n.-cerbur-clutch-dsh-worktree-workspaceActions {\n position: relative;\n display: inline-flex;\n flex: 0 0 64px;\n align-items: center;\n justify-content: flex-end;\n width: 64px;\n height: 28px;\n margin-left: auto;\n}\n\n.-cerbur-clutch-dsh-worktree-treeActionSlot > .-cerbur-clutch-dsh-worktree-menuAction {\n position: absolute;\n top: 0;\n right: 32px;\n}\n\n.-cerbur-clutch-dsh-worktree-treeActionSlot > .-cerbur-clutch-dsh-worktree-iconButton:last-child {\n position: absolute;\n top: 0;\n right: 0;\n}\n\n.-cerbur-clutch-dsh-worktree-menuAction {\n display: inline-flex;\n width: 28px;\n height: 28px;\n visibility: hidden;\n}\n\n.-cerbur-clutch-dsh-worktree-workspaceRow:hover .-cerbur-clutch-dsh-worktree-menuAction,\n.-cerbur-clutch-dsh-worktree-workspaceRow[data-menu-open='true'] .-cerbur-clutch-dsh-worktree-menuAction,\n.-cerbur-clutch-dsh-worktree-worktreeRow:hover .-cerbur-clutch-dsh-worktree-menuAction,\n.-cerbur-clutch-dsh-worktree-worktreeRow[data-menu-open='true'] .-cerbur-clutch-dsh-worktree-menuAction {\n visibility: visible;\n}\n\n.-cerbur-clutch-dsh-worktree-workspaceRow.-cerbur-clutch-dsh-worktree-dropBefore::before,\n.-cerbur-clutch-dsh-worktree-workspaceRow.-cerbur-clutch-dsh-worktree-dropAfter::after {\n position: absolute;\n right: 4px;\n left: 4px;\n height: 2px;\n border-radius: 2px;\n background: var(--dsw-alias-brand-primary);\n content: '';\n}\n\n.-cerbur-clutch-dsh-worktree-workspaceRow.-cerbur-clutch-dsh-worktree-dropBefore::before {\n top: -1px;\n}\n\n.-cerbur-clutch-dsh-worktree-workspaceRow.-cerbur-clutch-dsh-worktree-dropAfter::after {\n bottom: -1px;\n}\n\n.-cerbur-clutch-dsh-worktree-worktreeRow.-cerbur-clutch-dsh-worktree-dropBefore::before,\n.-cerbur-clutch-dsh-worktree-worktreeRow.-cerbur-clutch-dsh-worktree-dropAfter::after {\n position: absolute;\n right: 4px;\n left: 4px;\n height: 2px;\n border-radius: 2px;\n background: var(--dsw-alias-brand-primary);\n content: '';\n}\n\n.-cerbur-clutch-dsh-worktree-worktreeRow.-cerbur-clutch-dsh-worktree-dropBefore::before {\n top: -1px;\n}\n\n.-cerbur-clutch-dsh-worktree-worktreeRow.-cerbur-clutch-dsh-worktree-dropAfter::after {\n bottom: -1px;\n}\n\n.-cerbur-clutch-dsh-worktree-treeChildren {\n margin-left: 16px;\n padding: 2px 0 5px 12px;\n border-left: 1px solid var(--dsw-alias-border-l1);\n}\n\n.-cerbur-clutch-dsh-worktree-groupLabel {\n padding: 6px 8px 3px;\n color: var(--dsw-alias-label-tertiary);\n font-size: 10px;\n font-weight: 600;\n letter-spacing: 0.05em;\n text-transform: uppercase;\n}\n\n.-cerbur-clutch-dsh-worktree-groupHeader {\n display: flex;\n align-items: center;\n min-height: 34px;\n padding-right: 4px;\n}\n\n.-cerbur-clutch-dsh-worktree-groupHeader .-cerbur-clutch-dsh-worktree-groupLabel {\n flex: 1;\n}\n\n.-cerbur-clutch-dsh-worktree-worktreeGroup {\n margin-top: 2px;\n}\n\n.-cerbur-clutch-dsh-worktree-worktreeRow {\n min-height: 34px;\n}\n\n.-cerbur-clutch-dsh-worktree-worktreeRow .-cerbur-clutch-dsh-worktree-worktreeIcon,\n.-cerbur-clutch-dsh-worktree-worktreeRow .-cerbur-clutch-dsh-worktree-disclosureButton {\n width: 22px;\n}\n\n.-cerbur-clutch-dsh-worktree-treeSessionRow {\n position: relative;\n display: flex;\n align-items: center;\n width: calc(100% - 22px);\n margin-left: 22px;\n min-width: 0;\n min-height: 31px;\n box-sizing: border-box;\n border-radius: 7px;\n}\n\n.-cerbur-clutch-dsh-worktree-treeSessionRow:hover,\n.-cerbur-clutch-dsh-worktree-treeSessionRow[data-menu-open='true'] {\n background: var(--dsw-alias-interactive-bg-hover);\n}\n\n.-cerbur-clutch-dsh-worktree-treeSessionRow[data-session-current='true'] {\n background: var(--dsw-alias-interactive-bg-hover);\n}\n\n.-cerbur-clutch-dsh-worktree-treeSessionRow[data-session-current='true'] .-cerbur-clutch-dsh-worktree-treeSessionContent {\n font-weight: 600;\n}\n\n.-cerbur-clutch-dsh-worktree-treeSessionRow.-cerbur-clutch-dsh-worktree-dropBefore::before,\n.-cerbur-clutch-dsh-worktree-treeSessionRow.-cerbur-clutch-dsh-worktree-dropAfter::after {\n position: absolute;\n right: 4px;\n left: 4px;\n height: 2px;\n border-radius: 2px;\n background: var(--dsw-alias-brand-primary);\n content: '';\n}\n\n.-cerbur-clutch-dsh-worktree-treeSessionRow.-cerbur-clutch-dsh-worktree-dropBefore::before {\n top: -1px;\n}\n\n.-cerbur-clutch-dsh-worktree-treeSessionRow.-cerbur-clutch-dsh-worktree-dropAfter::after {\n bottom: -1px;\n}\n\n.-cerbur-clutch-dsh-worktree-treeSessionContent {\n display: flex;\n align-items: center;\n flex: 1;\n width: 0;\n min-width: 0;\n min-height: 31px;\n box-sizing: border-box;\n border: 0;\n border-radius: 7px;\n padding: 4px 4px;\n background: transparent;\n color: var(--dsw-alias-label-primary);\n cursor: pointer;\n font: inherit;\n font-size: 14px;\n font-weight: 400;\n line-height: 20px;\n text-align: left;\n}\n\n.-cerbur-clutch-dsh-worktree-treeSessionContent:hover {\n background: transparent;\n}\n\n.-cerbur-clutch-dsh-worktree-rowActions {\n display: none;\n flex: none;\n align-items: center;\n gap: 4px;\n}\n\n.-cerbur-clutch-dsh-worktree-sessionOverflowButton {\n display: block;\n width: calc(100% - 24px);\n margin: 2px 0 4px 24px;\n padding: 4px 8px;\n border: 0;\n border-radius: 6px;\n background: transparent;\n color: var(--dsw-alias-label-secondary);\n cursor: pointer;\n font: inherit;\n font-size: 12px;\n font-weight: 400;\n line-height: 20px;\n text-align: left;\n}\n\n.-cerbur-clutch-dsh-worktree-sessionOverflowButton:hover {\n background: var(--dsw-alias-interactive-bg-hover);\n color: var(--dsw-alias-label-primary);\n}\n\n.-cerbur-clutch-dsh-worktree-treeSessionRow:hover .-cerbur-clutch-dsh-worktree-rowActions,\n.-cerbur-clutch-dsh-worktree-treeSessionRow[data-menu-open='true'] .-cerbur-clutch-dsh-worktree-rowActions {\n display: inline-flex;\n}\n\n.-cerbur-clutch-dsh-worktree-renameInput {\n width: 100%;\n}\n\n.-cerbur-clutch-dsh-worktree-renameError {\n margin: 8px 0 0;\n color: var(--dsw-alias-state-error-primary);\n font-size: 13px;\n line-height: 20px;\n}\n\n.-cerbur-clutch-dsh-worktree-emptyNested {\n margin: 0;\n padding: 4px 8px 5px 28px;\n color: var(--dsw-alias-label-tertiary);\n font-size: 11px;\n}\n\n.-cerbur-clutch-dsh-worktree-modalField {\n display: grid;\n gap: 5px;\n color: var(--dsw-alias-label-secondary);\n font-size: 12px;\n}\n";
|
|
376
404
|
const styleId = "@cerbur/clutch-dsh-worktree/worktree.css";
|
|
377
405
|
if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=\"@cerbur/clutch-dsh-worktree/worktree.css\"]") === null) {
|
|
378
406
|
const tag = document.createElement("style");
|
|
@@ -386,6 +414,11 @@ window.__ModuleLoader__.load({
|
|
|
386
414
|
"actionLabel": "-cerbur-clutch-dsh-worktree-actionLabel",
|
|
387
415
|
"surface": "-cerbur-clutch-dsh-worktree-surface",
|
|
388
416
|
"wideContent": "-cerbur-clutch-dsh-worktree-wideContent",
|
|
417
|
+
"worktreeModalTabs": "-cerbur-clutch-dsh-worktree-worktreeModalTabs",
|
|
418
|
+
"worktreeModalTab": "-cerbur-clutch-dsh-worktree-worktreeModalTab",
|
|
419
|
+
"worktreeImportCandidates": "-cerbur-clutch-dsh-worktree-worktreeImportCandidates",
|
|
420
|
+
"worktreeImportSelect": "-cerbur-clutch-dsh-worktree-worktreeImportSelect",
|
|
421
|
+
"worktreeImportError": "-cerbur-clutch-dsh-worktree-worktreeImportError",
|
|
389
422
|
"closeButton": "-cerbur-clutch-dsh-worktree-closeButton",
|
|
390
423
|
"header": "-cerbur-clutch-dsh-worktree-header",
|
|
391
424
|
"title": "-cerbur-clutch-dsh-worktree-title",
|
|
@@ -441,7 +474,6 @@ window.__ModuleLoader__.load({
|
|
|
441
474
|
"sessionOverflowButton": "-cerbur-clutch-dsh-worktree-sessionOverflowButton",
|
|
442
475
|
"renameInput": "-cerbur-clutch-dsh-worktree-renameInput",
|
|
443
476
|
"renameError": "-cerbur-clutch-dsh-worktree-renameError",
|
|
444
|
-
"treeGuide": "-cerbur-clutch-dsh-worktree-treeGuide",
|
|
445
477
|
"emptyNested": "-cerbur-clutch-dsh-worktree-emptyNested",
|
|
446
478
|
"modalField": "-cerbur-clutch-dsh-worktree-modalField"
|
|
447
479
|
};
|
|
@@ -512,7 +544,7 @@ window.__ModuleLoader__.load({
|
|
|
512
544
|
}
|
|
513
545
|
/**
|
|
514
546
|
* Browser-local Hero suffix. It intentionally uses the frame overlay because
|
|
515
|
-
*
|
|
547
|
+
* The current upstream DSH exposes no additive slot beside the native Hero headline.
|
|
516
548
|
*/
|
|
517
549
|
function WorktreeHeroContext({ useWorktreeContext, t }) {
|
|
518
550
|
const state = useWorktreeContext((snapshot) => snapshot);
|
|
@@ -711,6 +743,84 @@ window.__ModuleLoader__.load({
|
|
|
711
743
|
};
|
|
712
744
|
}
|
|
713
745
|
//#endregion
|
|
746
|
+
//#region lib/client/worktree-expand-state.js
|
|
747
|
+
/** Browser-local storage identity; never sent to DSH or the plugin sidecar. */
|
|
748
|
+
const WORKTREE_EXPAND_STATE_STORAGE_KEY = "clutch-dsh-worktree.expand-state";
|
|
749
|
+
function emptyState() {
|
|
750
|
+
return {
|
|
751
|
+
collapsedWorkspaceIds: {},
|
|
752
|
+
collapsedMainWorkspaceIds: {},
|
|
753
|
+
collapsedWorktreeIds: {}
|
|
754
|
+
};
|
|
755
|
+
}
|
|
756
|
+
function isRecord(value) {
|
|
757
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
758
|
+
}
|
|
759
|
+
function normalizeIds(value) {
|
|
760
|
+
if (!isRecord(value)) return {};
|
|
761
|
+
return Object.fromEntries(Object.entries(value).filter(([id, collapsed]) => id.length > 0 && collapsed === true));
|
|
762
|
+
}
|
|
763
|
+
/** Turn any persisted JSON value into the current state shape. */
|
|
764
|
+
function normalizeWorktreeExpandState(value) {
|
|
765
|
+
const source = isRecord(value) ? value : {};
|
|
766
|
+
return {
|
|
767
|
+
collapsedWorkspaceIds: normalizeIds(source.collapsedWorkspaceIds),
|
|
768
|
+
collapsedMainWorkspaceIds: normalizeIds(source.collapsedMainWorkspaceIds),
|
|
769
|
+
collapsedWorktreeIds: normalizeIds(source.collapsedWorktreeIds)
|
|
770
|
+
};
|
|
771
|
+
}
|
|
772
|
+
function isWorkspaceExpanded(state, workspaceId) {
|
|
773
|
+
return state.collapsedWorkspaceIds[workspaceId] !== true;
|
|
774
|
+
}
|
|
775
|
+
function isMainExpanded(state, workspaceId) {
|
|
776
|
+
return state.collapsedMainWorkspaceIds[workspaceId] !== true;
|
|
777
|
+
}
|
|
778
|
+
function isWorktreeExpanded(state, worktreeId) {
|
|
779
|
+
return state.collapsedWorktreeIds[worktreeId] !== true;
|
|
780
|
+
}
|
|
781
|
+
function toggle(record, id) {
|
|
782
|
+
if (record[id] === true) delete record[id];
|
|
783
|
+
else record[id] = true;
|
|
784
|
+
}
|
|
785
|
+
function retain(record, ids) {
|
|
786
|
+
const allowed = new Set(ids);
|
|
787
|
+
for (const id of Object.keys(record)) if (!allowed.has(id)) delete record[id];
|
|
788
|
+
}
|
|
789
|
+
/** Create one apply-scoped store; component remounts share this instance. */
|
|
790
|
+
function createWorktreeExpandStateStore(snapshotStoreFactory) {
|
|
791
|
+
let store;
|
|
792
|
+
try {
|
|
793
|
+
store = snapshotStoreFactory(emptyState(), { persist: { name: WORKTREE_EXPAND_STATE_STORAGE_KEY } });
|
|
794
|
+
} catch {
|
|
795
|
+
store = snapshotStoreFactory(emptyState());
|
|
796
|
+
}
|
|
797
|
+
store.set(normalizeWorktreeExpandState(store.getSnapshot()));
|
|
798
|
+
return Object.assign(store, { actions: {
|
|
799
|
+
toggleWorkspace: (workspaceId) => {
|
|
800
|
+
store.update((draft) => {
|
|
801
|
+
toggle(draft.collapsedWorkspaceIds, workspaceId);
|
|
802
|
+
});
|
|
803
|
+
},
|
|
804
|
+
toggleMain: (workspaceId) => {
|
|
805
|
+
store.update((draft) => {
|
|
806
|
+
toggle(draft.collapsedMainWorkspaceIds, workspaceId);
|
|
807
|
+
});
|
|
808
|
+
},
|
|
809
|
+
toggleWorktree: (worktreeId) => {
|
|
810
|
+
store.update((draft) => {
|
|
811
|
+
toggle(draft.collapsedWorktreeIds, worktreeId);
|
|
812
|
+
});
|
|
813
|
+
},
|
|
814
|
+
retain: (workspaceIds, worktreeIds) => {
|
|
815
|
+
store.update((draft) => {
|
|
816
|
+
retain(draft.collapsedWorkspaceIds, workspaceIds);
|
|
817
|
+
retain(draft.collapsedMainWorkspaceIds, workspaceIds);
|
|
818
|
+
retain(draft.collapsedWorktreeIds, worktreeIds);
|
|
819
|
+
});
|
|
820
|
+
}
|
|
821
|
+
} });
|
|
822
|
+
}
|
|
823
|
+
//#endregion
|
|
714
824
|
//#region lib/client/view-mode.js
|
|
715
825
|
/** Browser-local storage key; it is never sent to DSH or the sidecar. */
|
|
716
826
|
const WORKTREE_VIEW_MODE_STORAGE_KEY = "clutch-dsh-worktree.view-mode";
|
|
@@ -787,6 +897,9 @@ window.__ModuleLoader__.load({
|
|
|
787
897
|
case "SESSION_CREATE_UNAVAILABLE": return t("error.sessionCreationUnavailable");
|
|
788
898
|
case "WORKTREE_CREATED_SESSION_UNAVAILABLE": return t("error.worktreeCreatedSessionUnavailable");
|
|
789
899
|
case "WORKTREE_RECORD_MISSING": return t("error.worktreeRecordMissing");
|
|
900
|
+
case "WORKTREE_IMPORT_INVALID": return t("error.worktreeImportInvalid");
|
|
901
|
+
case "WORKTREE_ALREADY_MANAGED": return t("error.worktreeAlreadyManaged");
|
|
902
|
+
case "WORKTREE_REGISTRATION_SESSION_UNAVAILABLE": return t("error.worktreeRegistrationSessionUnavailable");
|
|
790
903
|
case "WORKSPACE_RENAME_UNAVAILABLE": return t("error.workspaceRenameUnavailable");
|
|
791
904
|
case "WORKSPACE_DELETE_UNAVAILABLE": return t("error.workspaceDeleteUnavailable");
|
|
792
905
|
case "SESSION_RENAME_UNAVAILABLE": return t("error.sessionRenameUnavailable");
|
|
@@ -917,6 +1030,7 @@ window.__ModuleLoader__.load({
|
|
|
917
1030
|
/** Keep mutation routing in the browser Consumer while leaving wire details to the adapter. */
|
|
918
1031
|
async function executeWorktreeAction(manager, action) {
|
|
919
1032
|
if (action.type === "createWorktree") return manager.createWorktree(action.input);
|
|
1033
|
+
if (action.type === "importWorktree") return manager.importWorktree(action.input);
|
|
920
1034
|
if (action.type === "removeWorktree") {
|
|
921
1035
|
await manager.removeWorktree(action.input);
|
|
922
1036
|
return;
|
|
@@ -943,6 +1057,14 @@ window.__ModuleLoader__.load({
|
|
|
943
1057
|
}
|
|
944
1058
|
//#endregion
|
|
945
1059
|
//#region lib/client/worktree-view-read.js
|
|
1060
|
+
/** Merge one freshly read Workspace projection without clearing other ready views. */
|
|
1061
|
+
function mergeWorktreeView(views, nextView) {
|
|
1062
|
+
const index = views.findIndex((view) => view.workspaceId === nextView.workspaceId);
|
|
1063
|
+
if (index === -1) return [...views, nextView];
|
|
1064
|
+
const merged = [...views];
|
|
1065
|
+
merged[index] = nextView;
|
|
1066
|
+
return merged;
|
|
1067
|
+
}
|
|
946
1068
|
/** Reuse the previous ID snapshot when DSH republishes equivalent Workspace items. */
|
|
947
1069
|
function stableWorkspaceIds(previous, next) {
|
|
948
1070
|
if (previous.length !== next.length) return next;
|
|
@@ -1048,6 +1170,19 @@ window.__ModuleLoader__.load({
|
|
|
1048
1170
|
readiness: branchesResult.value.length > 0 ? { status: "ready" } : { status: "noLocalBranch" }
|
|
1049
1171
|
};
|
|
1050
1172
|
}
|
|
1173
|
+
/** Isolate modal-target reads from full-surface refresh generations. */
|
|
1174
|
+
function createWorktreeModalViewLoader() {
|
|
1175
|
+
const guard = createWorktreeRefreshGuard();
|
|
1176
|
+
return {
|
|
1177
|
+
invalidate: guard.invalidate,
|
|
1178
|
+
load(manager, workspaceId, onSuccess, onError) {
|
|
1179
|
+
return guard.run(() => loadWorktreeView(manager, workspaceId), (data) => onSuccess({
|
|
1180
|
+
workspaceId,
|
|
1181
|
+
...data
|
|
1182
|
+
}), (error) => onError(toWorktreeViewError(error)));
|
|
1183
|
+
}
|
|
1184
|
+
};
|
|
1185
|
+
}
|
|
1051
1186
|
/** Load one independent projection per DSH Workspace for the flat sidebar hierarchy. */
|
|
1052
1187
|
async function loadWorktreeViews(manager, workspaceIds, options = {}) {
|
|
1053
1188
|
const views = await Promise.all(workspaceIds.map(async (workspaceId) => ({
|
|
@@ -1348,10 +1483,12 @@ window.__ModuleLoader__.load({
|
|
|
1348
1483
|
})
|
|
1349
1484
|
});
|
|
1350
1485
|
}
|
|
1351
|
-
function WorktreeCreateDialog({ t, workspace, view, setupStatus, canCreate, selectedBranch, newBranch, actionPending, onClose, onSelectedBranchChange, onNewBranchChange, onSubmit }) {
|
|
1486
|
+
function WorktreeCreateDialog({ t, workspace, view, readError, setupStatus, canCreate, mode, importCandidates, selectedImportPath, selectedBranch, newBranch, actionPending, onClose, onRetry, onModeChange, onRetryImportCandidates, onSelectedImportPathChange, onSelectedBranchChange, onNewBranchChange, onSubmit }) {
|
|
1352
1487
|
if (workspace === void 0) return null;
|
|
1353
1488
|
const setupCommands = setupStatus === void 0 ? [] : worktreeSetupCommands(setupStatus);
|
|
1354
|
-
|
|
1489
|
+
const importing = mode === "import";
|
|
1490
|
+
const importBlocked = actionPending || importCandidates.status === "loading" || selectedImportPath === void 0;
|
|
1491
|
+
return (0, react_jsx_runtime.jsxs)(_deepseek_ai_dsh_client_ui_primitives.Modal, {
|
|
1355
1492
|
open: true,
|
|
1356
1493
|
onClose: () => {
|
|
1357
1494
|
if (actionPending) return;
|
|
@@ -1359,7 +1496,7 @@ window.__ModuleLoader__.load({
|
|
|
1359
1496
|
},
|
|
1360
1497
|
closeLabel: t("dialog.closeWorktreeCreate"),
|
|
1361
1498
|
title: t("worktree.createTitle"),
|
|
1362
|
-
description: t("worktree.createDescription", { name: workspace.title }),
|
|
1499
|
+
description: importing ? t("worktree.importDescription", { name: workspace.title }) : t("worktree.createDescription", { name: workspace.title }),
|
|
1363
1500
|
footer: (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [(0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
1364
1501
|
variant: "outline",
|
|
1365
1502
|
disabled: actionPending,
|
|
@@ -1367,13 +1504,104 @@ window.__ModuleLoader__.load({
|
|
|
1367
1504
|
children: t("dialog.cancel")
|
|
1368
1505
|
}), (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
1369
1506
|
variant: "primary",
|
|
1370
|
-
disabled: actionPending || selectedBranch.length === 0 || newBranch.trim().length === 0,
|
|
1507
|
+
disabled: importing ? importBlocked : actionPending || !canCreate || selectedBranch.length === 0 || newBranch.trim().length === 0,
|
|
1371
1508
|
onClick: () => {
|
|
1372
1509
|
onSubmit();
|
|
1373
1510
|
},
|
|
1374
|
-
children: t("worktree.create")
|
|
1511
|
+
children: importing ? t("worktree.import") : t("worktree.create")
|
|
1375
1512
|
})] }),
|
|
1376
|
-
children:
|
|
1513
|
+
children: [(0, react_jsx_runtime.jsxs)("div", {
|
|
1514
|
+
className: worktree_css_default.worktreeModalTabs,
|
|
1515
|
+
role: "tablist",
|
|
1516
|
+
"aria-label": t("worktree.title"),
|
|
1517
|
+
children: [(0, react_jsx_runtime.jsx)("button", {
|
|
1518
|
+
className: worktree_css_default.worktreeModalTab,
|
|
1519
|
+
type: "button",
|
|
1520
|
+
role: "tab",
|
|
1521
|
+
"aria-selected": mode === "create",
|
|
1522
|
+
disabled: actionPending,
|
|
1523
|
+
onClick: () => {
|
|
1524
|
+
onModeChange("create");
|
|
1525
|
+
},
|
|
1526
|
+
children: t("worktree.tabCreate")
|
|
1527
|
+
}), (0, react_jsx_runtime.jsx)("button", {
|
|
1528
|
+
className: worktree_css_default.worktreeModalTab,
|
|
1529
|
+
type: "button",
|
|
1530
|
+
role: "tab",
|
|
1531
|
+
"aria-selected": mode === "import",
|
|
1532
|
+
disabled: actionPending,
|
|
1533
|
+
onClick: () => {
|
|
1534
|
+
onModeChange("import");
|
|
1535
|
+
},
|
|
1536
|
+
children: t("worktree.tabImport")
|
|
1537
|
+
})]
|
|
1538
|
+
}), importing ? (0, react_jsx_runtime.jsxs)("div", {
|
|
1539
|
+
className: worktree_css_default.worktreeImportCandidates,
|
|
1540
|
+
role: "tabpanel",
|
|
1541
|
+
children: [
|
|
1542
|
+
importCandidates.status === "loading" && importCandidates.candidates.length === 0 && (0, react_jsx_runtime.jsx)("p", {
|
|
1543
|
+
className: worktree_css_default.message,
|
|
1544
|
+
children: t("worktree.importLoading")
|
|
1545
|
+
}),
|
|
1546
|
+
importCandidates.status === "error" && (0, react_jsx_runtime.jsxs)("div", {
|
|
1547
|
+
className: worktree_css_default.worktreeImportError,
|
|
1548
|
+
role: "alert",
|
|
1549
|
+
children: [(0, react_jsx_runtime.jsx)("p", {
|
|
1550
|
+
className: worktree_css_default.message,
|
|
1551
|
+
children: formatWorktreeViewError(importCandidates.error, t)
|
|
1552
|
+
}), (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
1553
|
+
variant: "outline",
|
|
1554
|
+
disabled: actionPending,
|
|
1555
|
+
onClick: onRetryImportCandidates,
|
|
1556
|
+
children: t("action.retry")
|
|
1557
|
+
})]
|
|
1558
|
+
}),
|
|
1559
|
+
importCandidates.candidates.length === 0 && importCandidates.status === "ready" && (0, react_jsx_runtime.jsx)("p", {
|
|
1560
|
+
className: worktree_css_default.message,
|
|
1561
|
+
children: t("worktree.importEmpty")
|
|
1562
|
+
}),
|
|
1563
|
+
importCandidates.candidates.length > 0 && (0, react_jsx_runtime.jsxs)("label", {
|
|
1564
|
+
className: worktree_css_default.modalField,
|
|
1565
|
+
children: [t("worktree.tabImport"), (0, react_jsx_runtime.jsxs)("select", {
|
|
1566
|
+
className: worktree_css_default.worktreeImportSelect,
|
|
1567
|
+
"data-worktree-import-select": true,
|
|
1568
|
+
"aria-label": t("worktree.tabImport"),
|
|
1569
|
+
value: selectedImportPath ?? "",
|
|
1570
|
+
disabled: actionPending,
|
|
1571
|
+
onChange: (event) => {
|
|
1572
|
+
onSelectedImportPathChange(event.currentTarget.value);
|
|
1573
|
+
},
|
|
1574
|
+
children: [(0, react_jsx_runtime.jsx)("option", {
|
|
1575
|
+
value: "",
|
|
1576
|
+
disabled: true,
|
|
1577
|
+
children: t("worktree.importPlaceholder")
|
|
1578
|
+
}), importCandidates.candidates.map((candidate) => (0, react_jsx_runtime.jsxs)("option", {
|
|
1579
|
+
value: candidate.absolutePath,
|
|
1580
|
+
children: [
|
|
1581
|
+
candidate.branch,
|
|
1582
|
+
" — ",
|
|
1583
|
+
candidate.absolutePath
|
|
1584
|
+
]
|
|
1585
|
+
}, candidate.absolutePath))]
|
|
1586
|
+
})]
|
|
1587
|
+
})
|
|
1588
|
+
]
|
|
1589
|
+
}) : readError !== void 0 ? (0, react_jsx_runtime.jsxs)("div", {
|
|
1590
|
+
className: worktree_css_default.gitReadiness,
|
|
1591
|
+
"data-worktree-readiness": "error",
|
|
1592
|
+
role: "alert",
|
|
1593
|
+
children: [(0, react_jsx_runtime.jsx)("p", {
|
|
1594
|
+
className: worktree_css_default.message,
|
|
1595
|
+
"data-error": "true",
|
|
1596
|
+
children: formatWorktreeViewError(readError, t)
|
|
1597
|
+
}), readError.retryable && onRetry !== void 0 && (0, react_jsx_runtime.jsx)("button", {
|
|
1598
|
+
type: "button",
|
|
1599
|
+
className: worktree_css_default.retryButton,
|
|
1600
|
+
disabled: actionPending,
|
|
1601
|
+
onClick: onRetry,
|
|
1602
|
+
children: t("action.retry")
|
|
1603
|
+
})]
|
|
1604
|
+
}) : canCreate ? (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [(0, react_jsx_runtime.jsxs)("label", {
|
|
1377
1605
|
className: worktree_css_default.modalField,
|
|
1378
1606
|
children: [t("worktree.baseBranch"), (0, react_jsx_runtime.jsx)("select", {
|
|
1379
1607
|
className: worktree_css_default.actionSelect,
|
|
@@ -1416,7 +1644,7 @@ window.__ModuleLoader__.load({
|
|
|
1416
1644
|
"aria-label": t("worktree.setup.commands"),
|
|
1417
1645
|
children: setupCommands.join("\n")
|
|
1418
1646
|
})]
|
|
1419
|
-
})
|
|
1647
|
+
})]
|
|
1420
1648
|
});
|
|
1421
1649
|
}
|
|
1422
1650
|
function WorktreeRemovalDialog({ t, worktree, actionPending, onClose, onSubmit }) {
|
|
@@ -1429,7 +1657,7 @@ window.__ModuleLoader__.load({
|
|
|
1429
1657
|
},
|
|
1430
1658
|
closeLabel: t("dialog.closeWorktreeRemove"),
|
|
1431
1659
|
title: t("worktree.remove"),
|
|
1432
|
-
description: t("worktree.removeDescription", { name: worktree.branch }),
|
|
1660
|
+
description: worktree.source === "external" ? t("worktree.removeExternalDescription", { name: worktree.branch }) : t("worktree.removeDescription", { name: worktree.branch }),
|
|
1433
1661
|
footer: (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [(0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
1434
1662
|
variant: "outline",
|
|
1435
1663
|
disabled: actionPending,
|
|
@@ -1453,6 +1681,17 @@ window.__ModuleLoader__.load({
|
|
|
1453
1681
|
function bindingIdsFor(bindings, worktreeId) {
|
|
1454
1682
|
return bindings.filter((binding) => binding.worktreeId === worktreeId).map((binding) => binding.sessionId);
|
|
1455
1683
|
}
|
|
1684
|
+
function clearSessionGroupExpansion(current, groupKeys) {
|
|
1685
|
+
const next = { ...current };
|
|
1686
|
+
for (const key of groupKeys) delete next[key];
|
|
1687
|
+
return next;
|
|
1688
|
+
}
|
|
1689
|
+
function isCompleteWorktreeWorkspaceSnapshot(workspaceIds, views) {
|
|
1690
|
+
if (views.length !== workspaceIds.length) return false;
|
|
1691
|
+
const expected = new Set(workspaceIds);
|
|
1692
|
+
const actual = new Set(views.map((view) => view.workspaceId));
|
|
1693
|
+
return actual.size === expected.size && [...expected].every((id) => actual.has(id));
|
|
1694
|
+
}
|
|
1456
1695
|
function includesText(value, query) {
|
|
1457
1696
|
return value.toLocaleLowerCase().includes(query);
|
|
1458
1697
|
}
|
|
@@ -1464,6 +1703,46 @@ window.__ModuleLoader__.load({
|
|
|
1464
1703
|
if (view.worktrees.some((record) => includesText(record.branch, query) || includesText(record.absolutePath, query))) return true;
|
|
1465
1704
|
return view.bindings.some((binding) => sessionMatchesQuery(binding.sessionId, sessions, query));
|
|
1466
1705
|
}
|
|
1706
|
+
function resolveCurrentSessionLocation(currentSessionId, workspaces, views) {
|
|
1707
|
+
if (currentSessionId === void 0) return void 0;
|
|
1708
|
+
const workspace = workspaces.find((candidate) => candidate.sessionIds.includes(currentSessionId));
|
|
1709
|
+
if (workspace === void 0) return void 0;
|
|
1710
|
+
const view = views.find((candidate) => candidate.workspaceId === workspace.workspaceId);
|
|
1711
|
+
if (view === void 0) return void 0;
|
|
1712
|
+
const binding = view.bindings.find((candidate) => candidate.sessionId === currentSessionId);
|
|
1713
|
+
if (binding === void 0) return {
|
|
1714
|
+
sessionId: currentSessionId,
|
|
1715
|
+
workspaceId: workspace.workspaceId,
|
|
1716
|
+
groupKey: "main:" + workspace.workspaceId,
|
|
1717
|
+
kind: "main"
|
|
1718
|
+
};
|
|
1719
|
+
const worktree = view.worktrees.find((candidate) => candidate.worktreeId === binding.worktreeId && candidate.workspaceId === workspace.workspaceId);
|
|
1720
|
+
if (worktree === void 0) return void 0;
|
|
1721
|
+
return {
|
|
1722
|
+
sessionId: currentSessionId,
|
|
1723
|
+
workspaceId: workspace.workspaceId,
|
|
1724
|
+
groupKey: "worktree:" + worktree.worktreeId,
|
|
1725
|
+
kind: "worktree",
|
|
1726
|
+
worktreeId: worktree.worktreeId
|
|
1727
|
+
};
|
|
1728
|
+
}
|
|
1729
|
+
function currentSessionRevealKeys(location) {
|
|
1730
|
+
if (location === void 0) return [];
|
|
1731
|
+
return [
|
|
1732
|
+
"workspace:" + location.workspaceId,
|
|
1733
|
+
location.kind === "main" ? "main:" + location.workspaceId : "worktree:" + location.worktreeId,
|
|
1734
|
+
"session-group:" + location.groupKey
|
|
1735
|
+
];
|
|
1736
|
+
}
|
|
1737
|
+
//#endregion
|
|
1738
|
+
//#region lib/client/worktree-session-position.js
|
|
1739
|
+
function scrollCurrentSessionIntoView(root, sessionId) {
|
|
1740
|
+
if (root === null) return false;
|
|
1741
|
+
const row = Array.from(root.querySelectorAll("[data-session-id]")).find((candidate) => candidate.dataset.sessionId === sessionId);
|
|
1742
|
+
if (row === void 0) return false;
|
|
1743
|
+
row.scrollIntoView({ block: "nearest" });
|
|
1744
|
+
return true;
|
|
1745
|
+
}
|
|
1467
1746
|
//#endregion
|
|
1468
1747
|
//#region lib/client/worktree-surface-rows.js
|
|
1469
1748
|
function rowHalf(event) {
|
|
@@ -1696,7 +1975,7 @@ window.__ModuleLoader__.load({
|
|
|
1696
1975
|
});
|
|
1697
1976
|
}
|
|
1698
1977
|
/** Worktree-mode Session row with the same trailing options menu as native DSH rows. */
|
|
1699
|
-
function WorktreeSessionRow({ t, sessionId, blank, label, drag, actionPending, onOpen, onRename, onFork, onArchive }) {
|
|
1978
|
+
function WorktreeSessionRow({ t, sessionId, blank, current, label, drag, actionPending, onOpen, onRename, onFork, onArchive }) {
|
|
1700
1979
|
const [menuOpen, setMenuOpen] = (0, react.useState)(false);
|
|
1701
1980
|
const markerClass = drag.marker === "before" ? worktree_css_default.dropBefore : drag.marker === "after" ? worktree_css_default.dropAfter : "";
|
|
1702
1981
|
const sessionMenuItems = [
|
|
@@ -1723,9 +2002,11 @@ window.__ModuleLoader__.load({
|
|
|
1723
2002
|
className: `${worktree_css_default.treeSessionRow} ${markerClass}`,
|
|
1724
2003
|
"data-session-id": sessionId,
|
|
1725
2004
|
"data-session-blank": blank ? "true" : void 0,
|
|
2005
|
+
"data-session-current": current ? "true" : void 0,
|
|
1726
2006
|
"data-session-drag": drag.active ? "active" : void 0,
|
|
1727
2007
|
"data-menu-open": menuOpen || void 0,
|
|
1728
2008
|
role: "treeitem",
|
|
2009
|
+
"aria-current": current ? "true" : void 0,
|
|
1729
2010
|
draggable: true,
|
|
1730
2011
|
onDragStart: (event) => {
|
|
1731
2012
|
event.dataTransfer.effectAllowed = "move";
|
|
@@ -1744,18 +2025,14 @@ window.__ModuleLoader__.load({
|
|
|
1744
2025
|
event.preventDefault();
|
|
1745
2026
|
drag.drop(rowHalf(event));
|
|
1746
2027
|
},
|
|
1747
|
-
children: [(0, react_jsx_runtime.
|
|
2028
|
+
children: [(0, react_jsx_runtime.jsx)("button", {
|
|
1748
2029
|
type: "button",
|
|
1749
2030
|
className: worktree_css_default.treeSessionContent,
|
|
1750
2031
|
onClick: onOpen,
|
|
1751
|
-
children:
|
|
1752
|
-
className: worktree_css_default.treeGuide,
|
|
1753
|
-
"aria-hidden": "true",
|
|
1754
|
-
children: "└"
|
|
1755
|
-
}), (0, react_jsx_runtime.jsx)("span", {
|
|
2032
|
+
children: (0, react_jsx_runtime.jsx)("span", {
|
|
1756
2033
|
className: worktree_css_default.sessionLabel,
|
|
1757
2034
|
children: label
|
|
1758
|
-
})
|
|
2035
|
+
})
|
|
1759
2036
|
}), !blank && (0, react_jsx_runtime.jsx)("span", {
|
|
1760
2037
|
className: worktree_css_default.rowActions,
|
|
1761
2038
|
children: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Menu, {
|
|
@@ -1787,13 +2064,14 @@ window.__ModuleLoader__.load({
|
|
|
1787
2064
|
})]
|
|
1788
2065
|
});
|
|
1789
2066
|
}
|
|
1790
|
-
function WorktreeSessionGroup({ t, groupKey, sessionIds, workspaceId, expanded, actionPending, sessions, dragState, onToggleExpanded, onStartDrag, onHoverDrag, onClearDrag, onFinishDrag, onCommitDrag, onOpen, onRename, onFork, onArchive }) {
|
|
2067
|
+
function WorktreeSessionGroup({ t, groupKey, sessionIds, workspaceId, currentSessionId, expanded, actionPending, sessions, dragState, onToggleExpanded, onStartDrag, onHoverDrag, onClearDrag, onFinishDrag, onCommitDrag, onOpen, onRename, onFork, onArchive }) {
|
|
1791
2068
|
const visibleSessionIds = expanded ? sessionIds : sessionIds.slice(0, 5);
|
|
1792
2069
|
const sameGroupDrag = dragState?.groupKey === groupKey;
|
|
1793
2070
|
return (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [visibleSessionIds.map((sessionId) => (0, react_jsx_runtime.jsx)(WorktreeSessionRow, {
|
|
1794
2071
|
t,
|
|
1795
2072
|
sessionId,
|
|
1796
2073
|
blank: isBlankSession(sessionId, sessions),
|
|
2074
|
+
current: sessionId === currentSessionId,
|
|
1797
2075
|
label: sessionLabel(sessionId, sessions, t),
|
|
1798
2076
|
drag: {
|
|
1799
2077
|
active: sameGroupDrag,
|
|
@@ -1857,19 +2135,31 @@ window.__ModuleLoader__.load({
|
|
|
1857
2135
|
* Peer Worktree navigation surface. It keeps the original DSH Workspace mode
|
|
1858
2136
|
* intact and renders a browser-local Workspace → Worktree → Session projection.
|
|
1859
2137
|
*/
|
|
1860
|
-
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 }) {
|
|
2138
|
+
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 }) {
|
|
1861
2139
|
const mode = effectiveViewMode(useStore((state) => state.viewMode), available && manager !== void 0);
|
|
1862
2140
|
const sessions = useSessions((state) => state);
|
|
1863
2141
|
const workspaces = useWorkspaces((state) => state);
|
|
2142
|
+
const currentSessionId = sessions.current;
|
|
1864
2143
|
const workspaceIds = useStableWorkspaceIds(workspaces.items);
|
|
1865
2144
|
const [readState, setReadState] = (0, react.useState)(EMPTY_READ_STATE);
|
|
2145
|
+
const expandSnapshot = (0, react.useSyncExternalStore)(expandState.subscribe, expandState.getSnapshot, expandState.getSnapshot);
|
|
1866
2146
|
const readStateRef = (0, react.useRef)(readState);
|
|
1867
2147
|
readStateRef.current = readState;
|
|
1868
2148
|
const [searchQuery, setSearchQuery] = (0, react.useState)("");
|
|
1869
|
-
const [
|
|
1870
|
-
const
|
|
1871
|
-
|
|
2149
|
+
const [currentSessionReveal, setCurrentSessionReveal] = (0, react.useState)();
|
|
2150
|
+
const searchQueryRef = (0, react.useRef)(searchQuery);
|
|
2151
|
+
searchQueryRef.current = searchQuery;
|
|
2152
|
+
const locateGenerationRef = (0, react.useRef)(0);
|
|
2153
|
+
const positionedLocateGenerationRef = (0, react.useRef)();
|
|
1872
2154
|
const [worktreeModalWorkspaceId, setWorktreeModalWorkspaceId] = (0, react.useState)();
|
|
2155
|
+
const [modalReadError, setModalReadError] = (0, react.useState)();
|
|
2156
|
+
const [modalReadLoading, setModalReadLoading] = (0, react.useState)(false);
|
|
2157
|
+
const [worktreeModalMode, setWorktreeModalMode] = (0, react.useState)("create");
|
|
2158
|
+
const [importCandidates, setImportCandidates] = (0, react.useState)({
|
|
2159
|
+
status: "idle",
|
|
2160
|
+
candidates: []
|
|
2161
|
+
});
|
|
2162
|
+
const [selectedImportPath, setSelectedImportPath] = (0, react.useState)();
|
|
1873
2163
|
const [openWorkspaceMenuId, setOpenWorkspaceMenuId] = (0, react.useState)();
|
|
1874
2164
|
const [openWorktreeMenuId, setOpenWorktreeMenuId] = (0, react.useState)();
|
|
1875
2165
|
const [worktreeRemoval, setWorktreeRemoval] = (0, react.useState)();
|
|
@@ -1897,6 +2187,11 @@ window.__ModuleLoader__.load({
|
|
|
1897
2187
|
const [worktreeDrag, setWorktreeDrag] = (0, react.useState)();
|
|
1898
2188
|
const worktreeDropCommitted = (0, react.useRef)(false);
|
|
1899
2189
|
const refreshGuard = (0, react.useRef)(createWorktreeRefreshGuard());
|
|
2190
|
+
const modalReadLoader = (0, react.useRef)(createWorktreeModalViewLoader());
|
|
2191
|
+
const modalReadViewRef = (0, react.useRef)();
|
|
2192
|
+
const importCandidatesGuard = (0, react.useRef)(createWorktreeRefreshGuard());
|
|
2193
|
+
const modalWorkspaceIdRef = (0, react.useRef)(worktreeModalWorkspaceId);
|
|
2194
|
+
modalWorkspaceIdRef.current = worktreeModalWorkspaceId;
|
|
1900
2195
|
const { ref, width, bounds } = useSidebarOverlayGeometry(mode === "worktree");
|
|
1901
2196
|
const collapsed = width <= 64;
|
|
1902
2197
|
const query = searchQuery.trim().toLocaleLowerCase();
|
|
@@ -1919,13 +2214,13 @@ window.__ModuleLoader__.load({
|
|
|
1919
2214
|
}), (views) => {
|
|
1920
2215
|
setReadState({
|
|
1921
2216
|
status: "ready",
|
|
1922
|
-
views
|
|
2217
|
+
views: modalReadViewRef.current === void 0 ? views : mergeWorktreeView(views, modalReadViewRef.current)
|
|
1923
2218
|
});
|
|
1924
2219
|
}, (error) => {
|
|
1925
2220
|
if (preserveCurrent) throw error;
|
|
1926
2221
|
setReadState({
|
|
1927
2222
|
status: "error",
|
|
1928
|
-
views: [],
|
|
2223
|
+
views: modalReadViewRef.current === void 0 ? [] : [modalReadViewRef.current],
|
|
1929
2224
|
error: toWorktreeViewError(error)
|
|
1930
2225
|
});
|
|
1931
2226
|
});
|
|
@@ -1934,10 +2229,39 @@ window.__ModuleLoader__.load({
|
|
|
1934
2229
|
manager,
|
|
1935
2230
|
workspaceIds
|
|
1936
2231
|
]);
|
|
2232
|
+
const loadModalWorktreeView = (0, react.useCallback)((workspaceId) => {
|
|
2233
|
+
setModalReadError(void 0);
|
|
2234
|
+
setModalReadLoading(true);
|
|
2235
|
+
if (manager === void 0) {
|
|
2236
|
+
setModalReadLoading(false);
|
|
2237
|
+
setModalReadError({
|
|
2238
|
+
code: "WORKTREE_VIEW_UNAVAILABLE",
|
|
2239
|
+
message: "",
|
|
2240
|
+
retryable: true
|
|
2241
|
+
});
|
|
2242
|
+
return;
|
|
2243
|
+
}
|
|
2244
|
+
modalReadLoader.current.load(manager, workspaceId, (view) => {
|
|
2245
|
+
modalReadViewRef.current = view;
|
|
2246
|
+
setModalReadLoading(false);
|
|
2247
|
+
setReadState((current) => ({
|
|
2248
|
+
...current,
|
|
2249
|
+
views: mergeWorktreeView(current.views, view)
|
|
2250
|
+
}));
|
|
2251
|
+
}, (error) => {
|
|
2252
|
+
setModalReadLoading(false);
|
|
2253
|
+
setModalReadError(toWorktreeViewError(error));
|
|
2254
|
+
});
|
|
2255
|
+
}, [manager]);
|
|
1937
2256
|
(0, react.useEffect)(() => {
|
|
1938
2257
|
if (mode === "worktree") refresh({ preserveCurrent: readStateRef.current.status === "ready" });
|
|
1939
2258
|
else {
|
|
1940
2259
|
refreshGuard.current.invalidate();
|
|
2260
|
+
modalReadLoader.current.invalidate();
|
|
2261
|
+
modalReadViewRef.current = void 0;
|
|
2262
|
+
setWorktreeModalWorkspaceId(void 0);
|
|
2263
|
+
setModalReadError(void 0);
|
|
2264
|
+
setModalReadLoading(false);
|
|
1941
2265
|
setReadState(EMPTY_READ_STATE);
|
|
1942
2266
|
}
|
|
1943
2267
|
}, [mode, refresh]);
|
|
@@ -1953,18 +2277,76 @@ window.__ModuleLoader__.load({
|
|
|
1953
2277
|
syncSessionWorkspaces
|
|
1954
2278
|
]);
|
|
1955
2279
|
const viewByWorkspace = (0, react.useMemo)(() => new Map(readState.views.map((view) => [view.workspaceId, view])), [readState.views]);
|
|
2280
|
+
const currentSessionLocation = (0, react.useMemo)(() => readState.status === "ready" ? resolveCurrentSessionLocation(currentSessionId, workspaces.items, readState.views) : void 0, [
|
|
2281
|
+
currentSessionId,
|
|
2282
|
+
readState.status,
|
|
2283
|
+
readState.views,
|
|
2284
|
+
workspaces.items
|
|
2285
|
+
]);
|
|
2286
|
+
const currentRevealKeys = (0, react.useMemo)(() => new Set(currentSessionRevealKeys(currentSessionLocation)), [currentSessionLocation]);
|
|
2287
|
+
const isCurrentSessionReveal = (key) => currentSessionReveal !== void 0 && currentSessionReveal.sessionId === currentSessionId && currentRevealKeys.has(key) && currentSessionReveal.suppressedKeys[key] !== true;
|
|
2288
|
+
(0, react.useLayoutEffect)(() => {
|
|
2289
|
+
locateGenerationRef.current += 1;
|
|
2290
|
+
positionedLocateGenerationRef.current = void 0;
|
|
2291
|
+
if (mode !== "worktree") {
|
|
2292
|
+
setCurrentSessionReveal(void 0);
|
|
2293
|
+
return;
|
|
2294
|
+
}
|
|
2295
|
+
if (searchQueryRef.current.trim().length > 0) setSearchQuery("");
|
|
2296
|
+
setCurrentSessionReveal(currentSessionId === void 0 ? void 0 : {
|
|
2297
|
+
sessionId: currentSessionId,
|
|
2298
|
+
suppressedKeys: {}
|
|
2299
|
+
});
|
|
2300
|
+
}, [currentSessionId, mode]);
|
|
2301
|
+
(0, react.useLayoutEffect)(() => {
|
|
2302
|
+
if (mode !== "worktree" || currentSessionId === void 0 || currentSessionLocation === void 0) return;
|
|
2303
|
+
const generation = locateGenerationRef.current;
|
|
2304
|
+
if (positionedLocateGenerationRef.current === generation) return;
|
|
2305
|
+
let cancelled = false;
|
|
2306
|
+
const frame = requestAnimationFrame(() => {
|
|
2307
|
+
if (cancelled || generation !== locateGenerationRef.current) return;
|
|
2308
|
+
if (!scrollCurrentSessionIntoView(ref.current, currentSessionId)) return;
|
|
2309
|
+
positionedLocateGenerationRef.current = generation;
|
|
2310
|
+
});
|
|
2311
|
+
return () => {
|
|
2312
|
+
cancelled = true;
|
|
2313
|
+
cancelAnimationFrame(frame);
|
|
2314
|
+
};
|
|
2315
|
+
}, [
|
|
2316
|
+
currentSessionId,
|
|
2317
|
+
currentSessionLocation,
|
|
2318
|
+
currentSessionReveal,
|
|
2319
|
+
expandSnapshot,
|
|
2320
|
+
mode,
|
|
2321
|
+
query,
|
|
2322
|
+
readState.status
|
|
2323
|
+
]);
|
|
2324
|
+
(0, react.useEffect)(() => {
|
|
2325
|
+
if (readState.status !== "ready" || !isCompleteWorktreeWorkspaceSnapshot(workspaceIds, readState.views)) return;
|
|
2326
|
+
expandState.actions.retain(workspaceIds, readState.views.flatMap((view) => view.worktrees.map((record) => record.worktreeId)));
|
|
2327
|
+
}, [
|
|
2328
|
+
expandState,
|
|
2329
|
+
readState.status,
|
|
2330
|
+
readState.views,
|
|
2331
|
+
workspaceIds
|
|
2332
|
+
]);
|
|
1956
2333
|
const modalWorkspace = workspaces.items.find((workspace) => workspace.workspaceId === worktreeModalWorkspaceId);
|
|
1957
2334
|
const modalView = worktreeModalWorkspaceId === void 0 ? void 0 : viewByWorkspace.get(worktreeModalWorkspaceId);
|
|
1958
2335
|
const modalReadiness = modalView?.readiness;
|
|
1959
2336
|
const modalSetupStatus = modalView === void 0 ? void 0 : modalReadiness?.status === "ready" ? modalView.branches.length === 0 ? "noLocalBranch" : void 0 : modalReadiness?.status;
|
|
1960
|
-
const modalCanCreate = modalSetupStatus === void 0 && modalReadiness?.status === "ready";
|
|
2337
|
+
const modalCanCreate = !modalReadLoading && modalSetupStatus === void 0 && modalReadiness?.status === "ready";
|
|
1961
2338
|
(0, react.useEffect)(() => {
|
|
1962
2339
|
if (worktreeModalWorkspaceId === void 0 || modalView === void 0) return;
|
|
1963
2340
|
if (modalView.readiness.status !== "ready") {
|
|
1964
2341
|
setSelectedBranch("");
|
|
2342
|
+
setNewBranch("");
|
|
1965
2343
|
return;
|
|
1966
2344
|
}
|
|
1967
2345
|
setSelectedBranch((current) => reconcileBaseBranchSelection(current, modalView.branches));
|
|
2346
|
+
setNewBranch((current) => {
|
|
2347
|
+
if (current.length > 0) return current;
|
|
2348
|
+
return createDefaultWorktreeName([...modalView.branches.map((branch) => branch.name), ...modalView.worktrees.map((worktree) => worktree.branch)]);
|
|
2349
|
+
});
|
|
1968
2350
|
}, [modalView, worktreeModalWorkspaceId]);
|
|
1969
2351
|
const runMutation = async (operation) => {
|
|
1970
2352
|
setActionPending(true);
|
|
@@ -1978,6 +2360,27 @@ window.__ModuleLoader__.load({
|
|
|
1978
2360
|
setActionPending(false);
|
|
1979
2361
|
}
|
|
1980
2362
|
};
|
|
2363
|
+
const loadImportCandidates = (0, react.useCallback)(async (workspaceId) => {
|
|
2364
|
+
if (manager === void 0) return;
|
|
2365
|
+
setImportCandidates((current) => ({
|
|
2366
|
+
status: "loading",
|
|
2367
|
+
candidates: current.candidates
|
|
2368
|
+
}));
|
|
2369
|
+
await importCandidatesGuard.current.run(() => manager.listImportCandidates({ workspaceId }), (candidates) => {
|
|
2370
|
+
if (modalWorkspaceIdRef.current !== workspaceId) return;
|
|
2371
|
+
setImportCandidates({
|
|
2372
|
+
status: "ready",
|
|
2373
|
+
candidates
|
|
2374
|
+
});
|
|
2375
|
+
}, (error) => {
|
|
2376
|
+
if (modalWorkspaceIdRef.current !== workspaceId) return;
|
|
2377
|
+
setImportCandidates((current) => ({
|
|
2378
|
+
status: "error",
|
|
2379
|
+
candidates: current.candidates,
|
|
2380
|
+
error: toWorktreeViewError(error)
|
|
2381
|
+
}));
|
|
2382
|
+
});
|
|
2383
|
+
}, [manager]);
|
|
1981
2384
|
const workspaceRenameTrimmed = workspaceRenameDraft.trim();
|
|
1982
2385
|
const workspaceRenameDuplicate = workspaceRenameTarget !== void 0 && workspaceRenameTrimmed.length > 0 && workspaces.items.some((workspace) => workspace.workspaceId !== workspaceRenameTarget.workspaceId && workspace.title === workspaceRenameTrimmed);
|
|
1983
2386
|
const workspaceRenameBlocked = workspaceRenamePending || workspaceRenameTarget === void 0 || workspaceRenameTrimmed.length === 0 || workspaceRenameTrimmed === workspaceRenameTarget?.currentTitle || workspaceRenameDuplicate;
|
|
@@ -2160,80 +2563,172 @@ window.__ModuleLoader__.load({
|
|
|
2160
2563
|
if (archiveSession === void 0) return;
|
|
2161
2564
|
await runMutation(() => archiveSession(sessionId));
|
|
2162
2565
|
};
|
|
2566
|
+
const clearSessionGroups = (groupKeys) => {
|
|
2567
|
+
if (groupKeys.length === 0) return;
|
|
2568
|
+
setExpandedSessionGroups((current) => clearSessionGroupExpansion(current, groupKeys));
|
|
2569
|
+
};
|
|
2570
|
+
const suppressCurrentSessionReveal = (key) => {
|
|
2571
|
+
if (!isCurrentSessionReveal(key)) return false;
|
|
2572
|
+
setCurrentSessionReveal((current) => {
|
|
2573
|
+
if (current === void 0 || current.sessionId !== currentSessionId) return current;
|
|
2574
|
+
return {
|
|
2575
|
+
...current,
|
|
2576
|
+
suppressedKeys: {
|
|
2577
|
+
...current.suppressedKeys,
|
|
2578
|
+
[key]: true
|
|
2579
|
+
}
|
|
2580
|
+
};
|
|
2581
|
+
});
|
|
2582
|
+
return true;
|
|
2583
|
+
};
|
|
2163
2584
|
const toggleWorkspace = (workspaceId) => {
|
|
2164
|
-
|
|
2165
|
-
|
|
2166
|
-
|
|
2167
|
-
|
|
2585
|
+
const persistedExpanded = isWorkspaceExpanded(expandSnapshot, workspaceId);
|
|
2586
|
+
const autoExpanded = isCurrentSessionReveal("workspace:" + workspaceId);
|
|
2587
|
+
const visuallyExpanded = persistedExpanded || autoExpanded;
|
|
2588
|
+
if (visuallyExpanded && autoExpanded) suppressCurrentSessionReveal("workspace:" + workspaceId);
|
|
2589
|
+
if (visuallyExpanded && !persistedExpanded) {
|
|
2590
|
+
clearSessionGroups(["main:" + workspaceId, ...(viewByWorkspace.get(workspaceId)?.worktrees.map((record) => record.worktreeId) ?? []).map((worktreeId) => "worktree:" + worktreeId)]);
|
|
2591
|
+
return;
|
|
2592
|
+
}
|
|
2593
|
+
expandState.actions.toggleWorkspace(workspaceId);
|
|
2594
|
+
if (visuallyExpanded) clearSessionGroups(["main:" + workspaceId, ...(viewByWorkspace.get(workspaceId)?.worktrees.map((record) => record.worktreeId) ?? []).map((worktreeId) => "worktree:" + worktreeId)]);
|
|
2168
2595
|
};
|
|
2169
2596
|
const toggleMain = (workspaceId) => {
|
|
2170
|
-
|
|
2171
|
-
|
|
2172
|
-
|
|
2173
|
-
|
|
2597
|
+
const persistedExpanded = isMainExpanded(expandSnapshot, workspaceId);
|
|
2598
|
+
const autoExpanded = isCurrentSessionReveal("main:" + workspaceId);
|
|
2599
|
+
const visuallyExpanded = persistedExpanded || autoExpanded;
|
|
2600
|
+
if (visuallyExpanded && autoExpanded) suppressCurrentSessionReveal("main:" + workspaceId);
|
|
2601
|
+
if (visuallyExpanded && !persistedExpanded) {
|
|
2602
|
+
clearSessionGroups(["main:" + workspaceId]);
|
|
2603
|
+
return;
|
|
2604
|
+
}
|
|
2605
|
+
expandState.actions.toggleMain(workspaceId);
|
|
2606
|
+
if (visuallyExpanded) clearSessionGroups(["main:" + workspaceId]);
|
|
2174
2607
|
};
|
|
2175
2608
|
const toggleWorktree = (worktreeId) => {
|
|
2176
|
-
|
|
2609
|
+
const persistedExpanded = isWorktreeExpanded(expandSnapshot, worktreeId);
|
|
2610
|
+
const autoExpanded = isCurrentSessionReveal("worktree:" + worktreeId);
|
|
2611
|
+
const visuallyExpanded = persistedExpanded || autoExpanded;
|
|
2612
|
+
if (visuallyExpanded && autoExpanded) suppressCurrentSessionReveal("worktree:" + worktreeId);
|
|
2613
|
+
if (visuallyExpanded && !persistedExpanded) {
|
|
2614
|
+
clearSessionGroups(["worktree:" + worktreeId]);
|
|
2615
|
+
return;
|
|
2616
|
+
}
|
|
2617
|
+
expandState.actions.toggleWorktree(worktreeId);
|
|
2618
|
+
if (visuallyExpanded) clearSessionGroups(["worktree:" + worktreeId]);
|
|
2619
|
+
};
|
|
2620
|
+
const toggleSessionGroup = (groupKey) => {
|
|
2621
|
+
const autoExpanded = isCurrentSessionReveal("session-group:" + groupKey);
|
|
2622
|
+
const transientExpanded = expandedSessionGroups[groupKey] === true;
|
|
2623
|
+
if (autoExpanded) {
|
|
2624
|
+
suppressCurrentSessionReveal("session-group:" + groupKey);
|
|
2625
|
+
setExpandedSessionGroups((current) => {
|
|
2626
|
+
const next = { ...current };
|
|
2627
|
+
delete next[groupKey];
|
|
2628
|
+
return next;
|
|
2629
|
+
});
|
|
2630
|
+
return;
|
|
2631
|
+
}
|
|
2632
|
+
setExpandedSessionGroups((current) => ({
|
|
2177
2633
|
...current,
|
|
2178
|
-
[
|
|
2634
|
+
[groupKey]: !transientExpanded
|
|
2179
2635
|
}));
|
|
2180
2636
|
};
|
|
2637
|
+
const closeWorktreeCreator = (force = false) => {
|
|
2638
|
+
if (actionPending && !force) return;
|
|
2639
|
+
modalReadLoader.current.invalidate();
|
|
2640
|
+
modalReadViewRef.current = void 0;
|
|
2641
|
+
importCandidatesGuard.current.invalidate();
|
|
2642
|
+
setWorktreeModalWorkspaceId(void 0);
|
|
2643
|
+
setModalReadError(void 0);
|
|
2644
|
+
setModalReadLoading(false);
|
|
2645
|
+
};
|
|
2181
2646
|
const openWorktreeCreator = (workspace) => {
|
|
2182
2647
|
const view = viewByWorkspace.get(workspace.workspaceId);
|
|
2183
|
-
|
|
2184
|
-
|
|
2648
|
+
modalReadLoader.current.invalidate();
|
|
2649
|
+
modalReadViewRef.current = void 0;
|
|
2650
|
+
importCandidatesGuard.current.invalidate();
|
|
2185
2651
|
setWorktreeModalWorkspaceId(workspace.workspaceId);
|
|
2186
|
-
|
|
2187
|
-
|
|
2652
|
+
setWorktreeModalMode("create");
|
|
2653
|
+
setImportCandidates({
|
|
2654
|
+
status: "idle",
|
|
2655
|
+
candidates: []
|
|
2656
|
+
});
|
|
2657
|
+
setSelectedImportPath(void 0);
|
|
2188
2658
|
setActionError(void 0);
|
|
2659
|
+
setModalReadError(void 0);
|
|
2660
|
+
setModalReadLoading(false);
|
|
2661
|
+
if (view === void 0) {
|
|
2662
|
+
setSelectedBranch("");
|
|
2663
|
+
setNewBranch("");
|
|
2664
|
+
loadModalWorktreeView(workspace.workspaceId);
|
|
2665
|
+
return;
|
|
2666
|
+
}
|
|
2667
|
+
setSelectedBranch(selectDefaultBaseBranch(view.branches));
|
|
2668
|
+
setNewBranch(createDefaultWorktreeName([...view.branches.map((branch) => branch.name), ...view.worktrees.map((worktree) => worktree.branch)]));
|
|
2669
|
+
};
|
|
2670
|
+
const changeWorktreeModalMode = (mode) => {
|
|
2671
|
+
setWorktreeModalMode(mode);
|
|
2672
|
+
if (mode === "import" && worktreeModalWorkspaceId !== void 0 && importCandidates.status === "idle") loadImportCandidates(worktreeModalWorkspaceId);
|
|
2673
|
+
};
|
|
2674
|
+
const continueWorktreeRegistration = async (registeredWorktree) => {
|
|
2675
|
+
closeWorktreeCreator(true);
|
|
2676
|
+
if (createSessionCallback === void 0) {
|
|
2677
|
+
await refresh({ preserveCurrent: true });
|
|
2678
|
+
setActionError({
|
|
2679
|
+
code: "WORKTREE_REGISTRATION_SESSION_UNAVAILABLE",
|
|
2680
|
+
message: "",
|
|
2681
|
+
retryable: true
|
|
2682
|
+
});
|
|
2683
|
+
return;
|
|
2684
|
+
}
|
|
2685
|
+
const sessionInput = {
|
|
2686
|
+
workspaceId: registeredWorktree.workspaceId,
|
|
2687
|
+
worktreeId: registeredWorktree.worktreeId,
|
|
2688
|
+
cwd: registeredWorktree.absolutePath
|
|
2689
|
+
};
|
|
2690
|
+
try {
|
|
2691
|
+
await createSessionCallback(sessionInput);
|
|
2692
|
+
await invalidateWorktreeContext?.(registeredWorktree.workspaceId);
|
|
2693
|
+
} catch (error) {
|
|
2694
|
+
if (error instanceof WorktreeSessionBindingError && error.retryable) setPendingSessionBinding({
|
|
2695
|
+
...sessionInput,
|
|
2696
|
+
sessionId: error.sessionId
|
|
2697
|
+
});
|
|
2698
|
+
throw error;
|
|
2699
|
+
}
|
|
2700
|
+
await refresh({ preserveCurrent: true });
|
|
2189
2701
|
};
|
|
2190
2702
|
const submitWorktree = async () => {
|
|
2191
2703
|
const worktreeName = newBranch.trim();
|
|
2192
|
-
|
|
2193
|
-
|
|
2194
|
-
|
|
2195
|
-
|
|
2196
|
-
newBranch: worktreeName
|
|
2197
|
-
};
|
|
2704
|
+
const selectedImportCandidate = importCandidates.candidates.find((candidate) => candidate.absolutePath === selectedImportPath);
|
|
2705
|
+
if (manager === void 0 || modalWorkspace === void 0) return;
|
|
2706
|
+
if (worktreeModalMode === "create" && (!modalCanCreate || selectedBranch.length === 0 || worktreeName.length === 0)) return;
|
|
2707
|
+
if (worktreeModalMode === "import" && selectedImportCandidate === void 0) return;
|
|
2198
2708
|
setActionPending(true);
|
|
2199
2709
|
setActionError(void 0);
|
|
2200
2710
|
setPendingSessionBinding(void 0);
|
|
2201
2711
|
try {
|
|
2202
|
-
const
|
|
2712
|
+
const registeredWorktree = worktreeModalMode === "create" ? await executeWorktreeAction(manager, {
|
|
2203
2713
|
type: "createWorktree",
|
|
2204
|
-
input
|
|
2714
|
+
input: {
|
|
2715
|
+
workspaceId: modalWorkspace.workspaceId,
|
|
2716
|
+
branch: selectedBranch,
|
|
2717
|
+
newBranch: worktreeName
|
|
2718
|
+
}
|
|
2719
|
+
}) : await executeWorktreeAction(manager, {
|
|
2720
|
+
type: "importWorktree",
|
|
2721
|
+
input: {
|
|
2722
|
+
workspaceId: modalWorkspace.workspaceId,
|
|
2723
|
+
absolutePath: selectedImportCandidate.absolutePath
|
|
2724
|
+
}
|
|
2205
2725
|
});
|
|
2206
|
-
if (
|
|
2726
|
+
if (registeredWorktree === void 0) throw {
|
|
2207
2727
|
code: "WORKTREE_RECORD_MISSING",
|
|
2208
2728
|
message: "",
|
|
2209
2729
|
retryable: true
|
|
2210
2730
|
};
|
|
2211
|
-
|
|
2212
|
-
if (createSessionCallback === void 0) {
|
|
2213
|
-
await refresh({ preserveCurrent: true });
|
|
2214
|
-
setActionError({
|
|
2215
|
-
code: "WORKTREE_CREATED_SESSION_UNAVAILABLE",
|
|
2216
|
-
message: "",
|
|
2217
|
-
retryable: true
|
|
2218
|
-
});
|
|
2219
|
-
return;
|
|
2220
|
-
}
|
|
2221
|
-
const sessionInput = {
|
|
2222
|
-
workspaceId: createdWorktree.workspaceId,
|
|
2223
|
-
worktreeId: createdWorktree.worktreeId,
|
|
2224
|
-
cwd: createdWorktree.absolutePath
|
|
2225
|
-
};
|
|
2226
|
-
try {
|
|
2227
|
-
await createSessionCallback(sessionInput);
|
|
2228
|
-
await invalidateWorktreeContext?.(createdWorktree.workspaceId);
|
|
2229
|
-
} catch (error) {
|
|
2230
|
-
if (error instanceof WorktreeSessionBindingError && error.retryable) setPendingSessionBinding({
|
|
2231
|
-
...sessionInput,
|
|
2232
|
-
sessionId: error.sessionId
|
|
2233
|
-
});
|
|
2234
|
-
throw error;
|
|
2235
|
-
}
|
|
2236
|
-
await refresh({ preserveCurrent: true });
|
|
2731
|
+
await continueWorktreeRegistration(registeredWorktree);
|
|
2237
2732
|
} catch (error) {
|
|
2238
2733
|
setActionError(toWorktreeViewError(error));
|
|
2239
2734
|
} finally {
|
|
@@ -2437,13 +2932,15 @@ window.__ModuleLoader__.load({
|
|
|
2437
2932
|
const view = viewByWorkspace.get(workspace.workspaceId);
|
|
2438
2933
|
const currentBranch = view?.branches.find((branch) => branch.isCurrent)?.name;
|
|
2439
2934
|
const mainLabel = currentBranch === void 0 ? t("worktree.main") : t("worktree.mainWithBranch", { branch: currentBranch });
|
|
2440
|
-
const expanded =
|
|
2935
|
+
const expanded = isWorkspaceExpanded(expandSnapshot, workspace.workspaceId) || isCurrentSessionReveal("workspace:" + workspace.workspaceId);
|
|
2441
2936
|
const workspaceMatchesQuery = includesText(workspace.title, query);
|
|
2442
2937
|
const allWorkspaceSessionIds = filterArchivedSessionIds(workspaceSessionIds(workspaces, workspace.workspaceId, sessions.ids), archivedSessionIds);
|
|
2443
2938
|
const bindings = view?.bindings ?? [];
|
|
2444
2939
|
const visibleMainSessionIds = filterVisibleSessionIds(unboundSessionIds(allWorkspaceSessionIds, [...new Set(bindings.map((binding) => binding.sessionId))]), sessions).filter((sessionId) => workspaceMatchesQuery || sessionMatchesQuery(sessionId, sessions, query));
|
|
2445
|
-
const mainExpanded =
|
|
2940
|
+
const mainExpanded = isMainExpanded(expandSnapshot, workspace.workspaceId) || isCurrentSessionReveal("main:" + workspace.workspaceId);
|
|
2446
2941
|
const mainGroupKey = `main:${workspace.workspaceId}`;
|
|
2942
|
+
const sessionIds = visibleMainSessionIds;
|
|
2943
|
+
const mainSessionGroupExpanded = expandedSessionGroups[mainGroupKey] === true || sessionIds.length > 5 && isCurrentSessionReveal("session-group:" + mainGroupKey);
|
|
2447
2944
|
const worktrees = view?.worktrees ?? [];
|
|
2448
2945
|
const sameWorkspaceWorktreeDrag = worktreeDrag?.workspaceId === workspace.workspaceId;
|
|
2449
2946
|
return (0, react_jsx_runtime.jsxs)("section", {
|
|
@@ -2522,17 +3019,15 @@ window.__ModuleLoader__.load({
|
|
|
2522
3019
|
mainExpanded && (0, react_jsx_runtime.jsx)(WorktreeSessionGroup, {
|
|
2523
3020
|
t,
|
|
2524
3021
|
groupKey: mainGroupKey,
|
|
2525
|
-
sessionIds
|
|
3022
|
+
sessionIds,
|
|
2526
3023
|
workspaceId: workspace.workspaceId,
|
|
2527
|
-
|
|
3024
|
+
currentSessionId,
|
|
3025
|
+
expanded: mainSessionGroupExpanded,
|
|
2528
3026
|
actionPending,
|
|
2529
3027
|
sessions,
|
|
2530
3028
|
dragState: sessionDrag,
|
|
2531
3029
|
onToggleExpanded: () => {
|
|
2532
|
-
|
|
2533
|
-
...current,
|
|
2534
|
-
[mainGroupKey]: current[mainGroupKey] !== true
|
|
2535
|
-
}));
|
|
3030
|
+
toggleSessionGroup(mainGroupKey);
|
|
2536
3031
|
},
|
|
2537
3032
|
onStartDrag: (groupKey, sessionId) => {
|
|
2538
3033
|
sessionDropCommitted.current = false;
|
|
@@ -2575,9 +3070,11 @@ window.__ModuleLoader__.load({
|
|
|
2575
3070
|
if (query.length > 0 && !worktreeMatchesQuery && !worktreeSessionIds.some((sessionId) => sessionMatchesQuery(sessionId, sessions, query))) return null;
|
|
2576
3071
|
const visibleWorktreeSessionIds = worktreeSessionIds.filter((sessionId) => worktreeMatchesQuery || sessionMatchesQuery(sessionId, sessions, query));
|
|
2577
3072
|
const worktreeGroupKey = `worktree:${record.worktreeId}`;
|
|
3073
|
+
const sessionIds = visibleWorktreeSessionIds;
|
|
3074
|
+
const sessionGroupExpanded = expandedSessionGroups[worktreeGroupKey] === true || sessionIds.length > 5 && isCurrentSessionReveal("session-group:" + worktreeGroupKey);
|
|
2578
3075
|
const state = record.status === "removed" ? "warning" : record.health === "repair" ? "error" : "done";
|
|
2579
3076
|
const stateLabel = record.status === "removed" ? t("worktree.detached") : record.health === "repair" ? t("worktree.repair") : t("worktree.ready");
|
|
2580
|
-
const worktreeExpanded =
|
|
3077
|
+
const worktreeExpanded = isWorktreeExpanded(expandSnapshot, record.worktreeId) || isCurrentSessionReveal("worktree:" + record.worktreeId);
|
|
2581
3078
|
return (0, react_jsx_runtime.jsxs)("div", {
|
|
2582
3079
|
className: worktree_css_default.worktreeGroup,
|
|
2583
3080
|
"data-worktree-id": record.worktreeId,
|
|
@@ -2648,17 +3145,15 @@ window.__ModuleLoader__.load({
|
|
|
2648
3145
|
}), worktreeExpanded && (0, react_jsx_runtime.jsx)(WorktreeSessionGroup, {
|
|
2649
3146
|
t,
|
|
2650
3147
|
groupKey: worktreeGroupKey,
|
|
2651
|
-
sessionIds
|
|
3148
|
+
sessionIds,
|
|
2652
3149
|
workspaceId: workspace.workspaceId,
|
|
2653
|
-
|
|
3150
|
+
currentSessionId,
|
|
3151
|
+
expanded: sessionGroupExpanded,
|
|
2654
3152
|
actionPending,
|
|
2655
3153
|
sessions,
|
|
2656
3154
|
dragState: sessionDrag,
|
|
2657
3155
|
onToggleExpanded: () => {
|
|
2658
|
-
|
|
2659
|
-
...current,
|
|
2660
|
-
[worktreeGroupKey]: current[worktreeGroupKey] !== true
|
|
2661
|
-
}));
|
|
3156
|
+
toggleSessionGroup(worktreeGroupKey);
|
|
2662
3157
|
},
|
|
2663
3158
|
onStartDrag: (groupKey, sessionId) => {
|
|
2664
3159
|
sessionDropCommitted.current = false;
|
|
@@ -2741,14 +3236,28 @@ window.__ModuleLoader__.load({
|
|
|
2741
3236
|
t,
|
|
2742
3237
|
workspace: modalWorkspace,
|
|
2743
3238
|
view: modalView,
|
|
3239
|
+
readError: modalReadError,
|
|
2744
3240
|
setupStatus: modalSetupStatus,
|
|
2745
3241
|
canCreate: modalCanCreate,
|
|
3242
|
+
mode: worktreeModalMode,
|
|
3243
|
+
importCandidates,
|
|
3244
|
+
selectedImportPath,
|
|
2746
3245
|
selectedBranch,
|
|
2747
3246
|
newBranch,
|
|
2748
3247
|
actionPending,
|
|
2749
|
-
onClose:
|
|
2750
|
-
|
|
3248
|
+
onClose: closeWorktreeCreator,
|
|
3249
|
+
onRetry: () => {
|
|
3250
|
+
if (worktreeModalWorkspaceId === void 0) return;
|
|
3251
|
+
modalReadViewRef.current = void 0;
|
|
3252
|
+
setSelectedBranch("");
|
|
3253
|
+
setNewBranch("");
|
|
3254
|
+
loadModalWorktreeView(worktreeModalWorkspaceId);
|
|
3255
|
+
},
|
|
3256
|
+
onModeChange: changeWorktreeModalMode,
|
|
3257
|
+
onRetryImportCandidates: () => {
|
|
3258
|
+
if (worktreeModalWorkspaceId !== void 0) loadImportCandidates(worktreeModalWorkspaceId);
|
|
2751
3259
|
},
|
|
3260
|
+
onSelectedImportPathChange: setSelectedImportPath,
|
|
2752
3261
|
onSelectedBranchChange: setSelectedBranch,
|
|
2753
3262
|
onNewBranchChange: setNewBranch,
|
|
2754
3263
|
onSubmit: submitWorktree
|
|
@@ -3172,6 +3681,7 @@ window.__ModuleLoader__.load({
|
|
|
3172
3681
|
ctx.effect(() => () => contextProjection.dispose(), "clutch-dsh-worktree: Session context cleanup");
|
|
3173
3682
|
contextProjection.refresh();
|
|
3174
3683
|
const viewStore = createWorktreeViewStore();
|
|
3684
|
+
const expandState = createWorktreeExpandStateStore(_deepseek_ai_dsh_client_runtime_client.createSnapshotStore);
|
|
3175
3685
|
const ensureSessionWorkspace = (workspaceId, sessionId) => {
|
|
3176
3686
|
virtualWorkspaceMembership.ensure({
|
|
3177
3687
|
workspaceId,
|
|
@@ -3213,6 +3723,7 @@ window.__ModuleLoader__.load({
|
|
|
3213
3723
|
locale: WORKTREE_NS,
|
|
3214
3724
|
inject: () => ({
|
|
3215
3725
|
available: true,
|
|
3726
|
+
expandState,
|
|
3216
3727
|
hooks: { worktreeContext: contextProjection.store },
|
|
3217
3728
|
manager,
|
|
3218
3729
|
createWorkspace: async () => {
|