zcode-pro 0.20.3 → 1.1.0
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.en.md +9 -6
- package/README.md +8 -5
- package/dist/inject.js +2658 -1318
- package/package.json +1 -1
- package/src/host/helper.mjs +156 -60
- package/src/host/main.mjs +7 -4
- package/src/host/taskIndex.mjs +97 -0
- package/src/host/version.mjs +51 -0
- package/src/inject/core.js +177 -24
- package/src/inject/features/alias-migration.js +470 -0
- package/src/inject/features/alias.js +6 -1
- package/src/inject/features/idle-reclaim.js +23 -48
- package/src/inject/features/pinned-collapse.js +4 -3
- package/src/inject/features/project-menu.js +209 -19
- package/src/inject/features/sandbox-reclaim.js +121 -0
- package/src/inject/features/session-switch.js +164 -25
- package/src/inject/features/settings-dialog.js +225 -61
- package/src/inject/features/styles.js +8 -1
- package/src/inject/features/title-lock.js +20 -2
- package/src/inject/features/toolbar-icons.js +85 -45
- package/src/inject/features/ws-rows.js +62 -0
- package/src/inject/features/ws-running.js +391 -27
- package/src/inject/index.js +3 -2
- package/src/inject/ui.js +34 -11
- package/src/inject/features/pinned-expand.js +0 -142
package/dist/inject.js
CHANGED
|
@@ -30,6 +30,47 @@
|
|
|
30
30
|
function clearConfigCache() {
|
|
31
31
|
configCache = { value: null, at: 0 };
|
|
32
32
|
}
|
|
33
|
+
var DEFAULT_SHORTCUTS = {
|
|
34
|
+
switchLast: "z",
|
|
35
|
+
// 立即切到上次会话
|
|
36
|
+
switchPrev: "x",
|
|
37
|
+
// 弹窗中上移
|
|
38
|
+
switchNext: "c",
|
|
39
|
+
// 弹窗中下移
|
|
40
|
+
switchRecent: "e",
|
|
41
|
+
// 打开最近 10 条
|
|
42
|
+
switchAttention: "r"
|
|
43
|
+
// 打开运行中 / 未查看
|
|
44
|
+
};
|
|
45
|
+
function zcodeAppVersion() {
|
|
46
|
+
const v = liveBoot().zcodeVersion;
|
|
47
|
+
return typeof v === "string" && v ? v : "";
|
|
48
|
+
}
|
|
49
|
+
function zcodeVersionGte(version, major, minor, patch = 0) {
|
|
50
|
+
const m = String(version || "").match(/^(\d+)\.(\d+)\.(\d+)/);
|
|
51
|
+
if (!m) return false;
|
|
52
|
+
const a = Number(m[1]), b = Number(m[2]), c = Number(m[3]);
|
|
53
|
+
return a > major || a === major && (b > minor || b === minor && c >= patch);
|
|
54
|
+
}
|
|
55
|
+
function officialRenameSupported() {
|
|
56
|
+
return zcodeVersionGte(zcodeAppVersion(), 3, 16, 1);
|
|
57
|
+
}
|
|
58
|
+
var newSidebarCached = false;
|
|
59
|
+
function isNewProjectSidebar() {
|
|
60
|
+
if (newSidebarCached) return true;
|
|
61
|
+
if (officialRenameSupported()) {
|
|
62
|
+
newSidebarCached = true;
|
|
63
|
+
return true;
|
|
64
|
+
}
|
|
65
|
+
try {
|
|
66
|
+
if (document.querySelector("section[data-project-id]")) {
|
|
67
|
+
newSidebarCached = true;
|
|
68
|
+
return true;
|
|
69
|
+
}
|
|
70
|
+
} catch {
|
|
71
|
+
}
|
|
72
|
+
return false;
|
|
73
|
+
}
|
|
33
74
|
var zh = {
|
|
34
75
|
settingsTitle: "ZCode Pro",
|
|
35
76
|
tabFeatures: "\u529F\u80FD",
|
|
@@ -76,7 +117,7 @@
|
|
|
76
117
|
syncRecLink: "\u575A\u679C\u4E91 WebDAV",
|
|
77
118
|
syncRecSuffix: "\uFF1A\u767B\u5F55\u4E0E\u5BC6\u7801\u586B\u201C\u5E94\u7528\u5BC6\u7801\u201D\uFF0C\u4E0D\u662F\u8D26\u53F7\u5BC6\u7801\u3002",
|
|
78
119
|
syncIncludeZcp: "ZCode Pro \u8BBE\u7F6E",
|
|
79
|
-
syncIncludeZcpDesc: "\u529F\u80FD\u5F00\u5173\u3001\u6837\u5F0F\u8C03\u6574\
|
|
120
|
+
syncIncludeZcpDesc: "\u529F\u80FD\u5F00\u5173\u3001\u6837\u5F0F\u8C03\u6574\u4E0E\u4EE3\u7406\u8BBE\u7F6E\uFF1B\u540C\u6B65\u914D\u7F6E\u4E0E\u51ED\u636E\u672C\u8EAB\u4E0D\u53C2\u4E0E\u540C\u6B65\u3002\u9879\u76EE\u522B\u540D\u4E0D\u540C\u6B65\uFF08\u5B98\u65B9\u5DF2\u652F\u6301\u6539\u9879\u76EE\u540D\uFF09\u3002",
|
|
80
121
|
syncIncludeModel: "\u6A21\u578B\u8BBE\u7F6E",
|
|
81
122
|
syncIncludeModelDesc: "\u81EA\u5B9A\u4E49\u4F9B\u5E94\u5546\u4E0E\u6A21\u578B\u914D\u7F6E\uFF08config.json \u4E0E provider_config.json\uFF0C\u542B API Key\uFF09\u3002\u8D26\u53F7\u767B\u5F55\u7684\u51ED\u636E\uFF08\u5982 BigModel \u8BA2\u9605\uFF09\u4E0D\u53C2\u4E0E\u540C\u6B65\uFF0C\u5404\u673A\u5668\u7528\u5404\u81EA\u8D26\u53F7\u767B\u5F55\u3002",
|
|
82
123
|
syncUpload: "\u4E0A\u4F20\u5230\u4E91\u7AEF",
|
|
@@ -149,7 +190,7 @@
|
|
|
149
190
|
featureTaskOrder: "\u4FA7\u8FB9\u680F\u4F1A\u8BDD\u62D6\u52A8\u6392\u5E8F",
|
|
150
191
|
featureTaskOrderDesc: "\u8BA9\u7F6E\u9876\u3001\u9879\u76EE\u4E0E\u5206\u7EC4\u4E2D\u7684\u4F1A\u8BDD\u62D6\u52A8\u540E\u8BB0\u4F4F\u987A\u5E8F\uFF0C\u5237\u65B0\u540E\u4FDD\u6301\u3002",
|
|
151
192
|
featureSessionSwitch: "\u4F1A\u8BDD\u5FEB\u6377\u5207\u6362",
|
|
152
|
-
featureSessionSwitchDesc: "
|
|
193
|
+
featureSessionSwitchDesc: "{last} \u5728\u5F53\u524D\u4E0E\u4E0A\u6B21\u4F1A\u8BDD\u95F4\u6765\u56DE\u5207\u6362\uFF1B\u6309\u4F4F alt \u518D\u6309 {prev}/{next} \u5F39\u51FA\u6700\u8FD1\u4F1A\u8BDD\u5217\u8868\u524D\u540E\u9009\u62E9\uFF08\u521D\u59CB 10 \u6761\uFF0C{next} \u5230\u5E95\u518D\u52A0\u8F7D 5 \u6761\uFF09\uFF0C{recent} \u76F4\u63A5\u6253\u5F00\u6700\u8FD1 10 \u6761\uFF0C{attention} \u6253\u5F00\u8FD0\u884C\u4E2D\u4E0E\u8FD0\u884C\u5B8C\u672A\u67E5\u770B\u7684\u4EFB\u52A1\uFF1B\u65B9\u5411\u952E\u540C\u6837\u53EF\u9009\uFF0CEnter \u6216\u677E\u5F00 alt \u5207\u6362\uFF08\u7C7B alt+tab\uFF09",
|
|
153
194
|
featureTitleLock: "\u91CD\u547D\u540D\u4F1A\u8BDD\u540D\u9501\u5B9A",
|
|
154
195
|
featureTitleLockDesc: "\u624B\u52A8\u91CD\u547D\u540D\u8FC7\u7684\u4F1A\u8BDD\u4E0D\u518D\u88AB\u81EA\u52A8\u6807\u9898\u8986\u76D6\uFF1A\u4F1A\u8BDD\u6709\u65B0\u56DE\u7B54\u540E\u754C\u9762\u53EF\u80FD\u6539\u663E\u81EA\u52A8\u6807\u9898\uFF0C\u91CD\u542F\u540E\u53C8\u53D8\u56DE\uFF0C\u672C\u529F\u80FD\u8BA9\u4FA7\u680F\u59CB\u7EC8\u663E\u793A\u91CD\u547D\u540D\u540E\u7684\u540D\u5B57\u3002",
|
|
155
196
|
tabTitleGen: "\u4EFB\u52A1\u540D\u63D0\u793A\u8BCD",
|
|
@@ -176,8 +217,8 @@
|
|
|
176
217
|
titleGenTesting: "\u751F\u6210\u4E2D\u2026",
|
|
177
218
|
titleGenTestOk: "\u751F\u6210\u7ED3\u679C\uFF1A",
|
|
178
219
|
titleGenTestFailed: "\u751F\u6210\u5931\u8D25",
|
|
179
|
-
featureWsRunning: "\u6298\u53E0\
|
|
180
|
-
featureWsRunningDesc: "\
|
|
220
|
+
featureWsRunning: "\u6298\u53E0\u65F6\u4EFB\u52A1\u8FD0\u884C\u4E2D\u63D0\u793A",
|
|
221
|
+
featureWsRunningDesc: "\u6709\u4F1A\u8BDD\u5728\u8FD0\u884C\u65F6\uFF0C\u6298\u53E0\u7684\u9879\u76EE\u4E0E\u201C\u4EFB\u52A1\u201D\u201C\u5DF2\u7F6E\u9876\u201D\u7B49\u5206\u533A\u5934\u663E\u793A\u4E0E\u4EFB\u52A1\u8FD0\u884C\u4E2D\u540C\u6B3E\u7684\u52A0\u8F7D\u56FE\u6807\uFF0C\u5168\u90E8\u7ED3\u675F\u540E\u6D88\u5931\u3002",
|
|
181
222
|
tabPerformance: "\u6027\u80FD",
|
|
182
223
|
perfDesc: "ZCode \u4E3A\u6BCF\u4E2A\u6253\u5F00\u8FC7\u7684\u9879\u76EE\u5E38\u9A7B\u4E00\u4E2A\u4F1A\u8BDD\u8FDB\u7A0B\uFF0C\u5E94\u7528\u81EA\u8EAB\u4E0D\u4F1A\u56DE\u6536\uFF0C\u9879\u76EE\u591A\u4E86\u5185\u5B58\u5360\u7528\u5C31\u9AD8\u3002\u5F00\u542F\u540E\uFF0C\u957F\u65F6\u95F4\u672A\u4F7F\u7528\u4E14\u6CA1\u6709\u4EFB\u52A1\u5728\u8DD1\u7684\u9879\u76EE\u4F1A\u88AB\u81EA\u52A8\u91CA\u653E\uFF1A\u4F1A\u8BDD\u8BB0\u5F55\u4E0D\u53D7\u5F71\u54CD\uFF0C\u518D\u6B21\u6253\u5F00\u65F6\u81EA\u52A8\u6062\u590D\uFF0C\u4EC5\u9996\u6B21\u56DE\u590D\u6709\u51E0\u79D2\u7B49\u5F85\u3002\u6B63\u5728\u4F7F\u7528\u7684\u9879\u76EE\u3001\u8FD0\u884C\u4E2D\u7684\u4F1A\u8BDD\u4E0E\u540E\u53F0\u547D\u4EE4\u3001\u5B9A\u65F6\u4EFB\u52A1\u90FD\u4E0D\u4F1A\u88AB\u56DE\u6536\u3002\u540E\u53F0\u547D\u4EE4\u68C0\u6D4B\u4F9D\u8D56\u7CFB\u7EDF\u8FDB\u7A0B\u4FE1\u606F\uFF08Linux / macOS / Windows \u5404\u8D70\u7CFB\u7EDF\u81EA\u5E26\u5DE5\u5177\uFF09\uFF0C\u68C0\u6D4B\u4E0D\u53EF\u7528\u65F6\u529F\u80FD\u81EA\u52A8\u505C\u7528\u3002",
|
|
183
224
|
featureIdleReclaim: "\u7A7A\u95F2\u9879\u76EE\u5185\u5B58\u56DE\u6536",
|
|
@@ -205,10 +246,40 @@
|
|
|
205
246
|
userFontDesc: "\u4F1A\u8BDD\u4E2D\u63D0\u95EE\u5185\u5BB9\u7684\u5B57\u4F53\uFF1B\u9009\u201C\u9ED8\u8BA4\u201D\u65F6\u8DDF\u968F\u754C\u9762\u5B57\u4F53\u3002",
|
|
206
247
|
assistantFontName: "\u56DE\u7B54\u5B57\u4F53",
|
|
207
248
|
assistantFontDesc: "\u4F1A\u8BDD\u4E2D\u56DE\u7B54\u6B63\u6587\u7684\u5B57\u4F53\uFF08\u4EE3\u7801\u5757\u4ECD\u7528\u7B49\u5BBD\u5B57\u4F53\uFF09\uFF1B\u9009\u201C\u9ED8\u8BA4\u201D\u65F6\u8DDF\u968F\u754C\u9762\u5B57\u4F53\u3002",
|
|
208
|
-
switcherHint: "
|
|
249
|
+
switcherHint: "{prev} / {next} \u6216 \u2191 / \u2193 \u9009\u62E9\uFF0CEnter \u6216\u677E\u5F00 alt \u5207\u6362\uFF0CEsc \u53D6\u6D88",
|
|
209
250
|
switcherCurrent: "\u5F53\u524D",
|
|
210
251
|
switcherEmpty: "\u6682\u65E0\u4E0A\u6B21\u4F1A\u8BDD\uFF08\u5207\u6362\u8FC7\u4F1A\u8BDD\u540E\u53EF\u7528\uFF09",
|
|
211
252
|
switcherFailed: "\u672A\u80FD\u5207\u6362\u5230\u8BE5\u4F1A\u8BDD\uFF08\u53EF\u80FD\u5DF2\u5220\u9664\uFF09",
|
|
253
|
+
switcherMore: "\u8FD8\u6709 {n} \u6761 \xB7 \u6309 c \u52A0\u8F7D",
|
|
254
|
+
switcherRunning: "\u8FD0\u884C\u4E2D",
|
|
255
|
+
switcherUnseen: "\u672A\u67E5\u770B",
|
|
256
|
+
switcherAttentionHint: "\u8FD0\u884C\u4E2D / \u8FD0\u884C\u5B8C\u672A\u67E5\u770B\u7684\u4EFB\u52A1 \xB7 {prev} / {next} \u6216 \u2191 / \u2193 \u9009\u62E9\uFF0CEnter \u6216\u677E\u5F00 alt \u5207\u6362",
|
|
257
|
+
switcherAttentionEmpty: "\u6682\u65E0\u8FD0\u884C\u4E2D\u6216\u672A\u67E5\u770B\u7684\u4EFB\u52A1",
|
|
258
|
+
tabShortcuts: "\u5FEB\u6377\u952E",
|
|
259
|
+
hkTitle: "\u4F1A\u8BDD\u5FEB\u6377\u5207\u6362",
|
|
260
|
+
hkAltZ: "\u5728\u5F53\u524D\u4E0E\u4E0A\u6B21\u4F7F\u7528\u7684\u4F1A\u8BDD\u95F4\u6765\u56DE\u5207\u6362",
|
|
261
|
+
hkAltX: "\u5F39\u7A97\u4E2D\u4E0A\u79FB\u9AD8\u4EAE\uFF08\u66F4\u65E9\u7684\u4F1A\u8BDD\uFF09",
|
|
262
|
+
hkAltC: "\u5F39\u7A97\u4E2D\u4E0B\u79FB\u9AD8\u4EAE\uFF08\u66F4\u65B0\u7684\u4F1A\u8BDD\uFF09\uFF1B\u5230\u5E95\u4E14\u8FD8\u6709\u66F4\u591A\u65F6\u52A0\u8F7D 5 \u6761\u5E76\u9009\u4E2D\u65B0\u52A0\u8F7D\u7684\u7B2C\u4E00\u6761",
|
|
263
|
+
hkAltE: "\u6253\u5F00\u6700\u8FD1 10 \u6761\u4EFB\u52A1\u5217\u8868",
|
|
264
|
+
hkAltR: "\u6253\u5F00\u6B63\u5728\u8FD0\u884C\u4E0E\u8FD0\u884C\u5B8C\u672A\u67E5\u770B\u7684\u4EFB\u52A1\u5217\u8868",
|
|
265
|
+
hkArrow: "\u5F39\u7A97\u6253\u5F00\u65F6\u79FB\u52A8\u9AD8\u4EAE\uFF08\u4E0E alt + {prev} / alt + {next} \u540C\u89C4\u5219\uFF09",
|
|
266
|
+
hkEnter: "\u786E\u8BA4\u5207\u6362\u5230\u9AD8\u4EAE\u7684\u4F1A\u8BDD",
|
|
267
|
+
hkEsc: "\u53D6\u6D88\u5E76\u5173\u95ED\u5F39\u7A97",
|
|
268
|
+
hkRelease: "\u79FB\u52A8\u8FC7\u9AD8\u4EAE\u65F6\u677E\u5F00\u5373\u5207\u6362\uFF1B\u4ECE\u672A\u79FB\u52A8\u5219\u5F39\u7A97\u4FDD\u6301\u6253\u5F00\uFF0C\u7EE7\u7EED\u9009\u62E9",
|
|
269
|
+
hkReleaseKey: "\u677E\u5F00 alt",
|
|
270
|
+
hkModify: "\u4FEE\u6539",
|
|
271
|
+
hkRecording: "\u6309\u4E0B\u65B0\u952E\u2026",
|
|
272
|
+
hkInvalid: "\u5FEB\u6377\u952E\u53EA\u652F\u6301\u5355\u4E2A\u5B57\u6BCD\u6216\u6570\u5B57",
|
|
273
|
+
hkConflict: "alt+{k} \u5DF2\u7528\u4E8E\u201C{name}\u201D",
|
|
274
|
+
hkSaved: "\u5FEB\u6377\u952E\u5DF2\u66F4\u65B0",
|
|
275
|
+
hkNameLast: "\u5207\u6362\u4E0A\u6B21\u4F1A\u8BDD",
|
|
276
|
+
hkNamePrev: "\u4E0A\u79FB\u9AD8\u4EAE",
|
|
277
|
+
hkNameNext: "\u4E0B\u79FB\u9AD8\u4EAE",
|
|
278
|
+
hkNameRecent: "\u6700\u8FD1 10 \u6761",
|
|
279
|
+
hkNameAttention: "\u8FD0\u884C\u4E2D / \u672A\u67E5\u770B",
|
|
280
|
+
hkEditHint: "\u70B9\u51FB\u201C\u4FEE\u6539\u201D\u540E\u6309\u4E0B\u65B0\u6309\u952E\uFF08\u5B57\u6BCD\u6216\u6570\u5B57\uFF09\uFF0CEsc \u53D6\u6D88",
|
|
281
|
+
hkReset: "\u91CD\u7F6E\u4E3A\u9ED8\u8BA4",
|
|
282
|
+
hkResetDone: "\u5DF2\u6062\u590D\u9ED8\u8BA4\u952E\u4F4D",
|
|
212
283
|
featureFileActions: "\u6587\u4EF6\u83DC\u5355\u589E\u5F3A",
|
|
213
284
|
featureFileActionsDesc: "\u5728\u4F1A\u8BDD\u4E2D\u6587\u4EF6\u94FE\u63A5\u7684\u53F3\u952E\u83DC\u5355\u91CC\u65B0\u589E\u201C\u9ED8\u8BA4\u5E94\u7528\u6253\u5F00\u201D\u4E0E\u201C\u6253\u5F00\u6240\u5728\u76EE\u5F55\u201D\u3002",
|
|
214
285
|
featureImageCopy: "\u56FE\u7247\u53F3\u952E\u590D\u5236",
|
|
@@ -217,17 +288,16 @@
|
|
|
217
288
|
imageCopied: "\u56FE\u7247\u5DF2\u590D\u5236\u5230\u526A\u8D34\u677F",
|
|
218
289
|
imageCopyFailed: "\u590D\u5236\u56FE\u7247\u5931\u8D25",
|
|
219
290
|
openFolderItem: "\u6253\u5F00\u6587\u4EF6\u5939",
|
|
291
|
+
openFolderPrimary: "\u4E3B\u76EE\u5F55",
|
|
220
292
|
copyPathItem: "\u590D\u5236\u8DEF\u5F84",
|
|
221
293
|
pathCopied: "\u8DEF\u5F84\u5DF2\u590D\u5236\u5230\u526A\u8D34\u677F",
|
|
222
294
|
pathCopyFailed: "\u590D\u5236\u8DEF\u5F84\u5931\u8D25",
|
|
223
295
|
fileOpenDefault: "\u9ED8\u8BA4\u5E94\u7528\u6253\u5F00",
|
|
224
296
|
fileReveal: "\u6253\u5F00\u6240\u5728\u76EE\u5F55",
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
pluginsUpdateTitle: "\u63D2\u4EF6\u66F4\u65B0 \xB7 zcode-plugins",
|
|
230
|
-
pluginsCheckNow: "\u68C0\u67E5\u5E76\u66F4\u65B0",
|
|
297
|
+
featureAutoUpdatePlugins: "\u81EA\u52A8\u66F4\u65B0",
|
|
298
|
+
featureAutoUpdatePluginsRepo: "duanluan/zcode-plugins",
|
|
299
|
+
featureAutoUpdatePluginsDesc: "",
|
|
300
|
+
pluginsCheckNow: "\u68C0\u67E5\u66F4\u65B0",
|
|
231
301
|
pluginsUpdating: "\u6B63\u5728\u66F4\u65B0\u63D2\u4EF6\u2026",
|
|
232
302
|
pluginsUpToDate: "\u63D2\u4EF6\u5DF2\u662F\u6700\u65B0",
|
|
233
303
|
pluginsUpdatesFound: "{n} \u4E2A\u63D2\u4EF6\u53EF\u66F4\u65B0",
|
|
@@ -305,6 +375,8 @@
|
|
|
305
375
|
hrUsageNone: "\u5F53\u524D\u6CA1\u6709\u8D70 headroom \u7684\u4F9B\u5E94\u5546\uFF0C\u672A\u5207\u6362",
|
|
306
376
|
headroomLoadFailed: "\u8BFB\u53D6 Headroom \u914D\u7F6E\u5931\u8D25",
|
|
307
377
|
headroomStatusTitle: "\u8FD0\u884C\u72B6\u6001",
|
|
378
|
+
hrInstRunning: "\u8FD0\u884C\u4E2D",
|
|
379
|
+
hrInstStopped: "\u672A\u8FD0\u884C",
|
|
308
380
|
headroomStatusLoadFailed: "\u8BFB\u53D6\u8FD0\u884C\u72B6\u6001\u5931\u8D25",
|
|
309
381
|
headroomProxyUp: "\u4EE3\u7406\u8FD0\u884C\u4E2D",
|
|
310
382
|
headroomProxyDown: "\u4EE3\u7406\u672A\u8FD0\u884C",
|
|
@@ -332,7 +404,7 @@
|
|
|
332
404
|
headroomStoppedWarn: "\u4EE3\u7406\u5DF2\u505C\u6B62\uFF1B\u6307\u5411 127.0.0.1 \u7684\u4F9B\u5E94\u5546\u5C06\u65E0\u6CD5\u8FDE\u63A5",
|
|
333
405
|
headroomBackend: "\u538B\u7F29\u8BBE\u5907",
|
|
334
406
|
headroomBackendAuto: "\u81EA\u52A8 \xB7 \u663E\u5361\u4F18\u5148",
|
|
335
|
-
headroomBackendCpu: "
|
|
407
|
+
headroomBackendCpu: "\u7701\u7535 \xB7 CPU \u4F18\u5148",
|
|
336
408
|
headroomBackendNative: "\uFF08\u539F\u751F\u503C\uFF09",
|
|
337
409
|
headroomBackendDesc: "\u81EA\u52A8\uFF1Aheadroom \u9009\u6700\u5FEB\u8BBE\u5907\uFF08CUDA/MPS \u663E\u5361\u4F18\u5148\uFF09\uFF1BCPU\uFF1A\u5F3A\u5236 CPU \u538B\u7F29\uFF0C\u7701\u7535\u4E14\u4E0D\u5360\u663E\u5B58\u3002\u4E5F\u652F\u6301 headroom \u539F\u751F\u503C\uFF08onnx\u3001pytorch_mps \u7B49\uFF09\u3002\u5207\u6362\u4F1A\u91CD\u542F\u4EE3\u7406\u7ACB\u5373\u751F\u6548\u3002",
|
|
338
410
|
headroomPower: "\u7701\u7535\u81EA\u52A8\u5207\u6362",
|
|
@@ -370,6 +442,30 @@
|
|
|
370
442
|
aliasSaved: "\u522B\u540D\u5DF2\u66F4\u65B0",
|
|
371
443
|
aliasCleared: "\u5DF2\u6062\u590D\u771F\u5B9E\u540D\u79F0",
|
|
372
444
|
aliasHint: "\u78C1\u76D8\u76EE\u5F55\u540D\u4E0D\u53D8\uFF1A\u7EC8\u7AEF\u3001\u6587\u4EF6\u7BA1\u7406\u5668\u4E0E\u5176\u4ED6\u5F15\u7528\u771F\u5B9E\u8DEF\u5F84\u7684\u754C\u9762\u4ECD\u663E\u793A\u539F\u540D\u3002",
|
|
445
|
+
featureProjectMenuDescNew: "\u9879\u76EE\u201C\u66F4\u591A\u201D\u83DC\u5355\u4E2D\u7684\u6253\u5F00\u6587\u4EF6\u5939\u4E0E\u590D\u5236\u8DEF\u5F84\u3002\u5B98\u65B9\u5DF2\u652F\u6301\u4FEE\u6539\u9879\u76EE\u540D\u79F0\uFF08\u7F16\u8F91\u9879\u76EE\uFF09\uFF0C\u81EA\u5B9A\u4E49\u522B\u540D\u5DF2\u505C\u7528\u3002",
|
|
446
|
+
aliasMigrateTitle: "\u8FC1\u79FB\u9879\u76EE\u522B\u540D",
|
|
447
|
+
aliasMigrateDesc: "\u5F53\u524D ZCode \u5DF2\u652F\u6301\u4FEE\u6539\u9879\u76EE\u540D\u79F0\uFF08\u9879\u76EE\u201C\u66F4\u591A\u201D\u83DC\u5355 \u2192 \u7F16\u8F91\u9879\u76EE\uFF09\uFF0C\u81EA\u5B9A\u4E49\u522B\u540D\u529F\u80FD\u5DF2\u505C\u7528\u3002\u53EF\u628A\u5DF2\u4FDD\u5B58\u7684\u522B\u540D\u5199\u5165\u5B98\u65B9\u9879\u76EE\u540D\u79F0\uFF0C\u52FE\u9009\u8981\u8FC1\u79FB\u7684\u9879\u76EE\uFF1B\u8FC1\u79FB\u53EA\u6539\u9879\u76EE\u540D\u79F0\uFF0C\u78C1\u76D8\u76EE\u5F55\u4E0D\u53D7\u5F71\u54CD\u3002",
|
|
448
|
+
aliasMigrateItemHint: "\u8FC1\u79FB\u540E\u5C06\u4F5C\u4E3A\u9879\u76EE\u540D\u79F0\u4FDD\u5B58\uFF08\u53EF\u968F\u65F6\u5728\u201C\u7F16\u8F91\u9879\u76EE\u201D\u4E2D\u518D\u6539\uFF09\u3002\u4EC5\u65E0\u6807\u8BB0\u7684\u6761\u76EE\u53EF\u52FE\u9009\uFF1B\u5DF2\u8FC1\u79FB\u3001\u5DF2\u5E76\u5165\u3001\u9879\u76EE\u5DF2\u5220\u9664\u3001\u672C\u673A\u4E0D\u5B58\u5728\uFF08\u65E7\u673A\u5668\u8DEF\u5F84\uFF09\u4EE5\u53CA\u9879\u76EE\u5DF2\u91CD\u547D\u540D\u7684\u90FD\u4E0D\u53EF\u52FE\u9009\u2014\u2014\u8981\u6539\u8FD9\u4E9B\u9879\u76EE\u7684\u540D\u5B57\uFF0C\u76F4\u63A5\u7528\u9879\u76EE\u201C\u66F4\u591A\u201D\u83DC\u5355\u91CC\u7684\u201C\u7F16\u8F91\u9879\u76EE\u201D\u3002",
|
|
449
|
+
aliasMigrateStateDone: "\u5DF2\u8FC1\u79FB",
|
|
450
|
+
aliasMigrateStateMerged: "\u5DF2\u5E76\u5165\u300C{name}\u300D",
|
|
451
|
+
aliasMigrateStateDeleted: "\u9879\u76EE\u5DF2\u5220\u9664",
|
|
452
|
+
aliasMigrateStateMissing: "\u672C\u673A\u4E0D\u5B58\u5728",
|
|
453
|
+
aliasMigrateStateRenamed: "\u9879\u76EE\u5DF2\u91CD\u547D\u540D",
|
|
454
|
+
aliasMigrateDeadSummary: "\u5DF2\u5931\u6548 {n} \u6761\uFF08\u672C\u673A\u4E0D\u5B58\u5728 / \u9879\u76EE\u5DF2\u5220\u9664\uFF0C\u591A\u4E3A\u8BBE\u7F6E\u540C\u6B65\u5E26\u6765\u7684\u65E7\u673A\u5668\u8DEF\u5F84\uFF09",
|
|
455
|
+
aliasMigrateClearDead: "\u6E05\u9664\u5931\u6548\u6761\u76EE",
|
|
456
|
+
aliasMigrateDeadCleared: "\u5DF2\u6E05\u9664 {n} \u6761\u5931\u6548\u522B\u540D",
|
|
457
|
+
aliasMigrateDeadClearFailed: "\u90E8\u5206\u5931\u6548\u522B\u540D\u672A\u80FD\u6E05\u9664\uFF0C\u8BF7\u91CD\u8BD5",
|
|
458
|
+
aliasMigrateGo: "\u8FC1\u79FB\u6240\u9009",
|
|
459
|
+
aliasMigrateRunning: "\u8FC1\u79FB\u4E2D\u2026",
|
|
460
|
+
aliasMigrateProgress: "\u6B63\u5728\u8FC1\u79FB {i}/{n}\uFF1A{name}",
|
|
461
|
+
aliasMigrateStateFailed: "\u5931\u8D25",
|
|
462
|
+
aliasMigrateSkip: "\u6682\u4E0D\u8FC1\u79FB",
|
|
463
|
+
aliasMigrateDone: "\u5DF2\u8FC1\u79FB {n} \u4E2A\u522B\u540D",
|
|
464
|
+
aliasMigratePartial: "{n} \u4E2A\u5DF2\u8FC1\u79FB\uFF0C{m} \u4E2A\u672A\u6210\u529F\uFF1B\u672A\u6210\u529F\u7684\u53EF\u7A0D\u540E\u5728 ZCode Pro \u8BBE\u7F6E\u4E2D\u91CD\u8BD5",
|
|
465
|
+
aliasMigrateAllFailed: "\u522B\u540D\u8FC1\u79FB\u672A\u6210\u529F\uFF0C\u53EF\u7A0D\u540E\u5728 ZCode Pro \u8BBE\u7F6E\u4E2D\u91CD\u8BD5",
|
|
466
|
+
aliasMigrateCardName: "\u522B\u540D\u8FC1\u79FB",
|
|
467
|
+
aliasMigrateCardDesc: "\u5B98\u65B9\u5DF2\u652F\u6301\u4FEE\u6539\u9879\u76EE\u540D\u79F0\uFF0C\u8FD8\u6709 {n} \u4E2A\u81EA\u5B9A\u4E49\u522B\u540D\u672A\u8FC1\u79FB\u3002",
|
|
468
|
+
aliasMigrateRun: "\u8FC1\u79FB",
|
|
373
469
|
taskOrderSaved: "\u987A\u5E8F\u5DF2\u66F4\u65B0",
|
|
374
470
|
qqGroupTitle: "QQ \u7FA4\uFF1A428403354",
|
|
375
471
|
qqGroupDesc: "\u95EE\u9898\u53CD\u9988\u4E0E\u4EA4\u6D41",
|
|
@@ -441,7 +537,7 @@
|
|
|
441
537
|
syncRecLink: "Jianguoyun WebDAV",
|
|
442
538
|
syncRecSuffix: " \u2014 use the app password, not your account password.",
|
|
443
539
|
syncIncludeZcp: "ZCode Pro settings",
|
|
444
|
-
syncIncludeZcpDesc: "Feature toggles, style adjustments
|
|
540
|
+
syncIncludeZcpDesc: "Feature toggles, style adjustments and the proxy setting; the sync config and credentials themselves are never synced. Project aliases are not synced (renaming is built in now).",
|
|
445
541
|
syncIncludeModel: "Model settings",
|
|
446
542
|
syncIncludeModelDesc: "Custom providers and model config (config.json and provider_config.json, API keys included). Account sign-in credentials (e.g. the BigModel subscription) are not synced; each computer signs in with its own account.",
|
|
447
543
|
syncUpload: "Upload",
|
|
@@ -514,7 +610,7 @@
|
|
|
514
610
|
featureTaskOrder: "Sidebar session drag ordering",
|
|
515
611
|
featureTaskOrderDesc: "Makes session drags in Pinned, Projects and Groups persist across refreshes.",
|
|
516
612
|
featureSessionSwitch: "Session quick switch",
|
|
517
|
-
featureSessionSwitchDesc: "
|
|
613
|
+
featureSessionSwitchDesc: "{last} toggles between the current and the last session; hold alt and press {prev}/{next} to move the highlight across recently used sessions (10 shown initially, pressing {next} at the bottom loads 5 more), {recent} opens the last 10 directly, {attention} opens running / finished-but-unseen tasks; arrow keys also move the highlight, Enter or release alt to switch (like alt+tab)",
|
|
518
614
|
featureTitleLock: "Keep renamed session titles",
|
|
519
615
|
featureTitleLockDesc: "Sessions you renamed keep their custom title: after new replies the app may show an auto-generated title instead, which reverts after a restart; this keeps the renamed title in the sidebar.",
|
|
520
616
|
tabTitleGen: "Task name prompt",
|
|
@@ -541,8 +637,8 @@
|
|
|
541
637
|
titleGenTesting: "Generating\u2026",
|
|
542
638
|
titleGenTestOk: "Result: ",
|
|
543
639
|
titleGenTestFailed: "Generation failed",
|
|
544
|
-
featureWsRunning: "Running indicator
|
|
545
|
-
featureWsRunningDesc: "
|
|
640
|
+
featureWsRunning: "Running indicator when collapsed",
|
|
641
|
+
featureWsRunningDesc: "Shows the same spinning loader as running tasks on collapsed projects and on section headers (\u201CTasks\u201D, \u201CPinned\u201D) while any session is running; clears when they all finish.",
|
|
546
642
|
tabPerformance: "Performance",
|
|
547
643
|
perfDesc: "ZCode keeps a session process resident for every project you have opened and never reclaims it, so memory grows with projects. When enabled, projects unused for a while with nothing running release their memory automatically: sessions are untouched and reload when reopened, with a few seconds wait on the first reply. The project in use, running sessions, background commands and scheduled tasks are never reclaimed. Background-command detection reads system process info via built-in tools (Linux / macOS / Windows); when unavailable, the feature disables itself.",
|
|
548
644
|
featureIdleReclaim: "Idle project memory reclaim",
|
|
@@ -570,10 +666,40 @@
|
|
|
570
666
|
userFontDesc: 'Font of question text in conversations; "default" follows the UI font.',
|
|
571
667
|
assistantFontName: "Answer font",
|
|
572
668
|
assistantFontDesc: 'Font of answer text in conversations (code blocks stay monospaced); "default" follows the UI font.',
|
|
573
|
-
switcherHint: "
|
|
669
|
+
switcherHint: "{prev} / {next} or \u2191 / \u2193 to choose, Enter or release alt to switch, Esc to cancel",
|
|
574
670
|
switcherCurrent: "current",
|
|
575
671
|
switcherEmpty: "No previous session yet (available after you switch sessions)",
|
|
576
672
|
switcherFailed: "Failed to switch to that session (it may have been deleted)",
|
|
673
|
+
switcherMore: "{n} more \xB7 press c to load",
|
|
674
|
+
switcherRunning: "running",
|
|
675
|
+
switcherUnseen: "unseen",
|
|
676
|
+
switcherAttentionHint: "Running / finished but unseen tasks \xB7 {prev} / {next} or \u2191 / \u2193 to choose, Enter or release alt to switch",
|
|
677
|
+
switcherAttentionEmpty: "No running or unseen tasks",
|
|
678
|
+
tabShortcuts: "Shortcuts",
|
|
679
|
+
hkTitle: "Session quick switch",
|
|
680
|
+
hkAltZ: "Toggle between the current and the last-used session",
|
|
681
|
+
hkAltX: "Move the highlight up (earlier sessions) in the popup",
|
|
682
|
+
hkAltC: "Move the highlight down (recent sessions); at the bottom it loads 5 more and highlights the first newly loaded entry",
|
|
683
|
+
hkAltE: "Open the last 10 tasks",
|
|
684
|
+
hkAltR: "Open running / finished-but-unseen tasks",
|
|
685
|
+
hkArrow: "Move the highlight while the popup is open (same rules as alt + {prev} / alt + {next})",
|
|
686
|
+
hkEnter: "Switch to the highlighted session",
|
|
687
|
+
hkEsc: "Cancel and close the popup",
|
|
688
|
+
hkRelease: "Releasing alt switches once the highlight has moved; otherwise the popup stays open for further selection",
|
|
689
|
+
hkReleaseKey: "release alt",
|
|
690
|
+
hkModify: "Change",
|
|
691
|
+
hkRecording: "press a key\u2026",
|
|
692
|
+
hkInvalid: "Shortcuts accept a single letter or digit only",
|
|
693
|
+
hkConflict: 'alt+{k} is already used by "{name}"',
|
|
694
|
+
hkSaved: "Shortcut updated",
|
|
695
|
+
hkNameLast: "last session",
|
|
696
|
+
hkNamePrev: "move up",
|
|
697
|
+
hkNameNext: "move down",
|
|
698
|
+
hkNameRecent: "last 10 tasks",
|
|
699
|
+
hkNameAttention: "running / unseen",
|
|
700
|
+
hkEditHint: 'Click "Change", press a new key (letter or digit); Esc cancels',
|
|
701
|
+
hkReset: "Reset to defaults",
|
|
702
|
+
hkResetDone: "Shortcuts reset to defaults",
|
|
577
703
|
featureFileActions: "File menu actions",
|
|
578
704
|
featureFileActionsDesc: 'Adds "Open with default app" and "Reveal in file manager" to the right-click menu of file links in chat.',
|
|
579
705
|
featureImageCopy: "Image right-click copy",
|
|
@@ -582,17 +708,16 @@
|
|
|
582
708
|
imageCopied: "Image copied to the clipboard.",
|
|
583
709
|
imageCopyFailed: "Failed to copy the image.",
|
|
584
710
|
openFolderItem: "Open folder",
|
|
711
|
+
openFolderPrimary: "primary",
|
|
585
712
|
copyPathItem: "Copy path",
|
|
586
713
|
pathCopied: "Path copied to the clipboard.",
|
|
587
714
|
pathCopyFailed: "Failed to copy the path.",
|
|
588
715
|
fileOpenDefault: "Open with default app",
|
|
589
716
|
fileReveal: "Reveal in file manager",
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
pluginsUpdateTitle: "Plugin updates \xB7 zcode-plugins",
|
|
595
|
-
pluginsCheckNow: "Check & update",
|
|
717
|
+
featureAutoUpdatePlugins: "Auto-update",
|
|
718
|
+
featureAutoUpdatePluginsRepo: "duanluan/zcode-plugins",
|
|
719
|
+
featureAutoUpdatePluginsDesc: "",
|
|
720
|
+
pluginsCheckNow: "Check for updates",
|
|
596
721
|
pluginsUpdating: "Updating plugins\u2026",
|
|
597
722
|
pluginsUpToDate: "Plugins are up to date",
|
|
598
723
|
pluginsUpdatesFound: "{n} plugin(s) can be updated",
|
|
@@ -670,6 +795,8 @@
|
|
|
670
795
|
hrUsageNone: "No providers route through headroom; nothing changed",
|
|
671
796
|
headroomLoadFailed: "Failed to load the Headroom config",
|
|
672
797
|
headroomStatusTitle: "Status",
|
|
798
|
+
hrInstRunning: "running",
|
|
799
|
+
hrInstStopped: "down",
|
|
673
800
|
headroomStatusLoadFailed: "Failed to load the status",
|
|
674
801
|
headroomProxyUp: "Proxy running",
|
|
675
802
|
headroomProxyDown: "Proxy down",
|
|
@@ -697,7 +824,7 @@
|
|
|
697
824
|
headroomStoppedWarn: "Proxy stopped; providers pointing at 127.0.0.1 cannot connect.",
|
|
698
825
|
headroomBackend: "Compression device",
|
|
699
826
|
headroomBackendAuto: "Auto \xB7 GPU first",
|
|
700
|
-
headroomBackendCpu: "
|
|
827
|
+
headroomBackendCpu: "Power saving \xB7 CPU first",
|
|
701
828
|
headroomBackendNative: " (native)",
|
|
702
829
|
headroomBackendDesc: "Auto lets headroom pick the fastest device (CUDA/MPS); CPU forces CPU compression (power saving, no VRAM). Native headroom values (onnx, pytorch_mps, \u2026) also work. Switching restarts the proxy to apply.",
|
|
703
830
|
headroomPower: "Power-save auto switch",
|
|
@@ -735,6 +862,30 @@
|
|
|
735
862
|
aliasSaved: "Alias updated.",
|
|
736
863
|
aliasCleared: "Real name restored.",
|
|
737
864
|
aliasHint: "The directory name on disk is unchanged: terminals, file managers and other path-based UI still show the real name.",
|
|
865
|
+
featureProjectMenuDescNew: 'Open folder and copy path in the project "More" menu. Renaming is built in since ZCode 3.16.1 ("Edit project"), so the custom alias is retired.',
|
|
866
|
+
aliasMigrateTitle: "Migrate project aliases",
|
|
867
|
+
aliasMigrateDesc: 'This ZCode supports renaming projects (project "More" menu \u2192 Edit project), so the custom alias feature is retired. Write your saved aliases into the official project names by picking the projects below; only the project name changes, folders on disk are untouched.',
|
|
868
|
+
aliasMigrateItemHint: 'The alias becomes the project name (re-editable anytime via "Edit project"). Only unmarked entries can be checked; migrated, merged, deleted, not-on-this-machine and manually-renamed ones cannot \u2014 to rename those projects, use "Edit project" in the project "More" menu directly.',
|
|
869
|
+
aliasMigrateStateDone: "Migrated",
|
|
870
|
+
aliasMigrateStateMerged: 'Merged into "{name}"',
|
|
871
|
+
aliasMigrateStateDeleted: "Project deleted",
|
|
872
|
+
aliasMigrateStateMissing: "Not on this machine",
|
|
873
|
+
aliasMigrateStateRenamed: "Project renamed",
|
|
874
|
+
aliasMigrateDeadSummary: "{n} stale entries (not on this machine / project deleted \u2014 usually old-machine paths from settings sync)",
|
|
875
|
+
aliasMigrateClearDead: "Clear stale entries",
|
|
876
|
+
aliasMigrateDeadCleared: "Removed {n} stale alias(es)",
|
|
877
|
+
aliasMigrateDeadClearFailed: "Some stale aliases could not be removed; please retry",
|
|
878
|
+
aliasMigrateGo: "Migrate selected",
|
|
879
|
+
aliasMigrateRunning: "Migrating\u2026",
|
|
880
|
+
aliasMigrateProgress: "Migrating {i}/{n}: {name}",
|
|
881
|
+
aliasMigrateStateFailed: "Failed",
|
|
882
|
+
aliasMigrateSkip: "Not now",
|
|
883
|
+
aliasMigrateDone: "Migrated {n} alias(es)",
|
|
884
|
+
aliasMigratePartial: "{n} migrated, {m} failed; retry the rest later in ZCode Pro settings",
|
|
885
|
+
aliasMigrateAllFailed: "Alias migration failed; retry later in ZCode Pro settings",
|
|
886
|
+
aliasMigrateCardName: "Alias migration",
|
|
887
|
+
aliasMigrateCardDesc: "Project renaming is built in now; {n} custom alias(es) are not migrated yet.",
|
|
888
|
+
aliasMigrateRun: "Migrate",
|
|
738
889
|
taskOrderSaved: "Order updated.",
|
|
739
890
|
qqGroupTitle: "QQ group: 428403354",
|
|
740
891
|
qqGroupDesc: "Feedback & discussion",
|
|
@@ -918,7 +1069,7 @@
|
|
|
918
1069
|
var overlayClassBare = "fixed inset-0 isolate z-50 flex items-center justify-center duration-100 p-4 platform-linux-desktop:top-12";
|
|
919
1070
|
var contentClass = "w-full sm:max-w-md rounded-2xl border-none bg-popover/98 p-5 text-ui-base/relaxed text-foreground ring-border shadow-2xl";
|
|
920
1071
|
var dialogStack = [];
|
|
921
|
-
function openDialog({ title, description, onMount, onClose, width = "sm:max-w-md", overlay = "dim", draggable = false, posKey = "", dismissOnOutside = true, bodyClass = "" }) {
|
|
1072
|
+
function openDialog({ title, description, onMount, onClose, width = "sm:max-w-md", overlay = "dim", draggable = false, posKey = "", dismissOnOutside = true, bodyClass = "", closable = false }) {
|
|
922
1073
|
const L = t();
|
|
923
1074
|
const prevActive = document.activeElement;
|
|
924
1075
|
let cleanupDrag = null;
|
|
@@ -958,8 +1109,25 @@
|
|
|
958
1109
|
content.style.pointerEvents = "auto";
|
|
959
1110
|
}
|
|
960
1111
|
const titleEl = h("h2", { class: "text-lg font-semibold leading-none tracking-tight text-foreground" }, title);
|
|
961
|
-
|
|
1112
|
+
const titleRow = closable ? h(
|
|
1113
|
+
"div",
|
|
1114
|
+
{ class: "flex items-start justify-between gap-2" },
|
|
962
1115
|
titleEl,
|
|
1116
|
+
h("button", {
|
|
1117
|
+
type: "button",
|
|
1118
|
+
class: "zcodepro-close",
|
|
1119
|
+
title: L.close,
|
|
1120
|
+
"aria-label": L.close,
|
|
1121
|
+
onMousedown: (e) => {
|
|
1122
|
+
e.stopPropagation();
|
|
1123
|
+
},
|
|
1124
|
+
onClick: () => {
|
|
1125
|
+
close();
|
|
1126
|
+
}
|
|
1127
|
+
}, "\u2715")
|
|
1128
|
+
) : titleEl;
|
|
1129
|
+
content.append(
|
|
1130
|
+
titleRow,
|
|
963
1131
|
...description ? [h("p", { class: "mt-2 text-ui-sm/relaxed text-foreground-subtle" }, description)] : []
|
|
964
1132
|
);
|
|
965
1133
|
const body = h("div", { class: "zcodepro-dialog-body " + (bodyClass || "mt-4") });
|
|
@@ -1154,13 +1322,13 @@
|
|
|
1154
1322
|
}
|
|
1155
1323
|
function unitField({ value = null, fallback = { value: 100, unit: "%" }, step = { px: 10, "%": 1 }, onCommit }) {
|
|
1156
1324
|
const RANGES = { px: [320, 3840], "%": [20, 100] };
|
|
1157
|
-
const
|
|
1325
|
+
const norm3 = (v) => {
|
|
1158
1326
|
if (!v || !RANGES[v.unit]) return null;
|
|
1159
1327
|
const [min, max] = RANGES[v.unit];
|
|
1160
1328
|
const n = v.unit === "px" ? Math.round(v.value) : Math.round(v.value * 10) / 10;
|
|
1161
1329
|
return Number.isFinite(n) ? { value: Math.min(max, Math.max(min, n)), unit: v.unit } : null;
|
|
1162
1330
|
};
|
|
1163
|
-
let current2 =
|
|
1331
|
+
let current2 = norm3(value) || norm3(fallback) || { value: 100, unit: "%" };
|
|
1164
1332
|
const input = h("input", {
|
|
1165
1333
|
type: "text",
|
|
1166
1334
|
inputmode: "decimal",
|
|
@@ -1171,7 +1339,7 @@
|
|
|
1171
1339
|
input.value = `${current2.value}${current2.unit}`;
|
|
1172
1340
|
};
|
|
1173
1341
|
const commit = (v) => {
|
|
1174
|
-
const next =
|
|
1342
|
+
const next = norm3(v);
|
|
1175
1343
|
if (!next || next.value === current2.value && next.unit === current2.unit) {
|
|
1176
1344
|
display();
|
|
1177
1345
|
return;
|
|
@@ -1208,7 +1376,7 @@
|
|
|
1208
1376
|
return {
|
|
1209
1377
|
el: input,
|
|
1210
1378
|
reset() {
|
|
1211
|
-
current2 =
|
|
1379
|
+
current2 = norm3(fallback) || current2;
|
|
1212
1380
|
display();
|
|
1213
1381
|
},
|
|
1214
1382
|
get() {
|
|
@@ -1247,7 +1415,7 @@
|
|
|
1247
1415
|
"div",
|
|
1248
1416
|
{ class: "min-w-0 flex-1" },
|
|
1249
1417
|
h("div", { class: "text-ui-sm font-medium text-foreground" }, name),
|
|
1250
|
-
|
|
1418
|
+
h("div", { class: "mt-0.5 text-ui-xs/relaxed text-foreground-subtle", "data-zcodepro-row-desc": "" }, desc ?? "")
|
|
1251
1419
|
),
|
|
1252
1420
|
...extraEl ? [extraEl] : [],
|
|
1253
1421
|
h("button", {
|
|
@@ -1505,6 +1673,20 @@
|
|
|
1505
1673
|
background-color: color-mix(in oklab, var(--color-primary, #111) 12%, transparent);
|
|
1506
1674
|
color: var(--color-foreground-subtle, #666);
|
|
1507
1675
|
}
|
|
1676
|
+
/* attention \u5F39\u7A97\uFF08alt+r\uFF09\u7684\u884C\u72B6\u6001\u6807\u7B7E\uFF1A\u8FD0\u884C\u4E2D\u7EFF\u3001\u672A\u67E5\u770B\u7425\u73C0 */
|
|
1677
|
+
.zcodepro-switcher-tag-run {
|
|
1678
|
+
background-color: color-mix(in oklab, var(--color-emerald-500, #10b981) 20%, transparent);
|
|
1679
|
+
}
|
|
1680
|
+
.zcodepro-switcher-tag-new {
|
|
1681
|
+
background-color: color-mix(in oklab, var(--color-amber-500, #f59e0b) 22%, transparent);
|
|
1682
|
+
}
|
|
1683
|
+
/* \u5217\u8868\u5E95\u90E8\u201C\u8FD8\u6709 N \u6761\u201D\u63D0\u793A\u884C */
|
|
1684
|
+
.zcodepro-switcher-more {
|
|
1685
|
+
padding: 6px 12px 2px;
|
|
1686
|
+
font-size: 11px;
|
|
1687
|
+
text-align: center;
|
|
1688
|
+
color: var(--color-muted-foreground, #888);
|
|
1689
|
+
}
|
|
1508
1690
|
.zcodepro-switcher-ws {
|
|
1509
1691
|
font-size: 11px;
|
|
1510
1692
|
color: var(--color-muted-foreground, #888);
|
|
@@ -1525,13 +1707,9 @@
|
|
|
1525
1707
|
.zcodepro-imgmenu-item:hover {
|
|
1526
1708
|
background-color: var(--color-accent, color-mix(in oklab, var(--color-foreground, #888) 10%, transparent));
|
|
1527
1709
|
}
|
|
1528
|
-
/* \u6298\u53E0\u9879\u76EE\u8FD0\u884C\u63D0\u793A\
|
|
1529
|
-
\
|
|
1530
|
-
|
|
1531
|
-
span.zcodepro-ws-running > svg {
|
|
1532
|
-
animation: zcodepro-ws-spin 1s linear infinite;
|
|
1533
|
-
transform-origin: center;
|
|
1534
|
-
}
|
|
1710
|
+
/* \u6298\u53E0\u9879\u76EE\u8FD0\u884C\u63D0\u793A\uFF1Afolder \u56FE\u6807\u8BA9\u4F4D\u7ED9 loader\uFF08loader \u7531\u811A\u672C\u63D2\u5165\uFF0C
|
|
1711
|
+
folder \u53EF\u80FD\u88AB React \u968F\u65F6\u91CD\u5EFA\uFF0C\u9760\u7C7B\u9009\u62E9\u5668\u7EDF\u4E00\u9690\u85CF\uFF0C\u540E\u4EE3\u5199\u6CD5\u517C\u5BB9\u5305\u88C5\u5C42\uFF09 */
|
|
1712
|
+
span.zcodepro-ws-running svg:not(.zcodepro-ws-loader) { display: none !important; }
|
|
1535
1713
|
/* \u65E0\u611F\u63A2\u67E5\u671F\u95F4\u76D6\u5728\u9879\u76EE\u884C\u4E0A\u7684\u51BB\u7ED3\u514B\u9686\uFF1A\u56FA\u5B9A\u5B9A\u4F4D\u3001\u4E0D\u54CD\u5E94\u6307\u9488 */
|
|
1536
1714
|
.zcodepro-ws-frozen {
|
|
1537
1715
|
position: fixed;
|
|
@@ -1645,12 +1823,82 @@
|
|
|
1645
1823
|
}
|
|
1646
1824
|
.zcodepro-pin-head:hover .zcodepro-pin-chevron svg { opacity: 1; }
|
|
1647
1825
|
.zcodepro-pin-collapsed .zcodepro-pin-chevron svg { transform: rotate(-90deg); }
|
|
1648
|
-
.zcodepro-pin-collapsed > ul { display: none !important; }
|
|
1826
|
+
.zcodepro-pin-collapsed > :is(ul, div):has(li[data-task-item-key]) { display: none !important; }
|
|
1649
1827
|
/* \u6298\u53E0\u540E\u53BB\u6389\u6807\u9898\u81EA\u5E26\u7684\u5E95\u90E8\u7559\u767D\uFF0C\u4E0E\u4E0B\u4E00\u5206\u533A\u7684\u95F4\u9694\u548C\u5176\u4ED6\u5206\u533A\u8282\u594F\u4E00\u81F4 */
|
|
1650
1828
|
.zcodepro-pin-collapsed .zcodepro-pin-head { padding-bottom: 0; }
|
|
1651
1829
|
`));
|
|
1652
1830
|
}
|
|
1653
1831
|
|
|
1832
|
+
// src/inject/features/copy-path.js
|
|
1833
|
+
async function appendCopyPathItem(menu, anchorItem, project) {
|
|
1834
|
+
if (menu.querySelector('[data-zcodepro-item="copy-path"]')) return;
|
|
1835
|
+
const L = t();
|
|
1836
|
+
const item = anchorItem.cloneNode(true);
|
|
1837
|
+
item.removeAttribute("data-testid");
|
|
1838
|
+
item.removeAttribute("data-highlighted");
|
|
1839
|
+
item.setAttribute("data-zcodepro-item", "copy-path");
|
|
1840
|
+
for (const child of [...item.childNodes]) child.remove();
|
|
1841
|
+
const origIcon = anchorItem.querySelector("svg");
|
|
1842
|
+
const iconClass = origIcon ? origIcon.getAttribute("class") : "h-3.5 w-3.5";
|
|
1843
|
+
item.append(hCopyIcon(iconClass), document.createTextNode(L.copyPathItem));
|
|
1844
|
+
item.addEventListener("mouseenter", () => {
|
|
1845
|
+
for (const el of menu.querySelectorAll('[role="menuitem"]')) el.removeAttribute("data-highlighted");
|
|
1846
|
+
item.setAttribute("data-highlighted", "");
|
|
1847
|
+
});
|
|
1848
|
+
item.addEventListener("mouseleave", () => item.removeAttribute("data-highlighted"));
|
|
1849
|
+
item.addEventListener("click", () => {
|
|
1850
|
+
closeRadixMenu(menu);
|
|
1851
|
+
void copyText(project.path);
|
|
1852
|
+
});
|
|
1853
|
+
anchorItem.before(item);
|
|
1854
|
+
}
|
|
1855
|
+
async function copyText(text) {
|
|
1856
|
+
const L = t();
|
|
1857
|
+
if (await copyToClipboard(text)) showToast(L.pathCopied);
|
|
1858
|
+
else showToast(L.pathCopyFailed, "error");
|
|
1859
|
+
}
|
|
1860
|
+
async function copyToClipboard(text) {
|
|
1861
|
+
try {
|
|
1862
|
+
await navigator.clipboard.writeText(text);
|
|
1863
|
+
return true;
|
|
1864
|
+
} catch {
|
|
1865
|
+
return copyViaHiddenInput(text);
|
|
1866
|
+
}
|
|
1867
|
+
}
|
|
1868
|
+
function copyViaHiddenInput(text) {
|
|
1869
|
+
try {
|
|
1870
|
+
const input = h("input", { type: "text", style: "position:fixed;left:-9999px;top:0;opacity:0" });
|
|
1871
|
+
input.value = text;
|
|
1872
|
+
document.body.append(input);
|
|
1873
|
+
input.select();
|
|
1874
|
+
const ok = document.execCommand("copy");
|
|
1875
|
+
input.remove();
|
|
1876
|
+
return ok;
|
|
1877
|
+
} catch {
|
|
1878
|
+
return false;
|
|
1879
|
+
}
|
|
1880
|
+
}
|
|
1881
|
+
function hCopyIcon(cls) {
|
|
1882
|
+
const ns = "http://www.w3.org/2000/svg";
|
|
1883
|
+
const svg = document.createElementNS(ns, "svg");
|
|
1884
|
+
svg.setAttribute("viewBox", "0 0 24 24");
|
|
1885
|
+
svg.setAttribute("fill", "none");
|
|
1886
|
+
svg.setAttribute("stroke", "currentColor");
|
|
1887
|
+
svg.setAttribute("stroke-width", "2");
|
|
1888
|
+
svg.setAttribute("stroke-linecap", "round");
|
|
1889
|
+
svg.setAttribute("stroke-linejoin", "round");
|
|
1890
|
+
svg.setAttribute("class", cls);
|
|
1891
|
+
for (const d of [
|
|
1892
|
+
"M8 8h12a2 2 0 0 1 2 2v12a2 2 0 0 1-2 2H8a2 2 0 0 1-2-2V10a2 2 0 0 1 2-2Z",
|
|
1893
|
+
"M4 16c-1.1 0-2-.9-2-2V4a2 2 0 0 1 2-2h12a2 2 0 0 1 2 2"
|
|
1894
|
+
]) {
|
|
1895
|
+
const p = document.createElementNS(ns, "path");
|
|
1896
|
+
p.setAttribute("d", d);
|
|
1897
|
+
svg.append(p);
|
|
1898
|
+
}
|
|
1899
|
+
return svg;
|
|
1900
|
+
}
|
|
1901
|
+
|
|
1654
1902
|
// src/inject/features/alias.js
|
|
1655
1903
|
var norm = (p) => String(p || "").replace(/[\\/]+$/, "");
|
|
1656
1904
|
var basenameOf = (p) => norm(p).split(/[\\/]/).pop() || "";
|
|
@@ -1679,6 +1927,7 @@
|
|
|
1679
1927
|
return false;
|
|
1680
1928
|
}
|
|
1681
1929
|
async function startAliasWatcher() {
|
|
1930
|
+
if (isNewProjectSidebar()) return;
|
|
1682
1931
|
await syncFromConfig();
|
|
1683
1932
|
if (observer) return;
|
|
1684
1933
|
observer = new MutationObserver((muts) => {
|
|
@@ -2053,76 +2302,6 @@
|
|
|
2053
2302
|
return svg;
|
|
2054
2303
|
}
|
|
2055
2304
|
|
|
2056
|
-
// src/inject/features/copy-path.js
|
|
2057
|
-
async function appendCopyPathItem(menu, anchorItem, project) {
|
|
2058
|
-
if (menu.querySelector('[data-zcodepro-item="copy-path"]')) return;
|
|
2059
|
-
const L = t();
|
|
2060
|
-
const item = anchorItem.cloneNode(true);
|
|
2061
|
-
item.removeAttribute("data-testid");
|
|
2062
|
-
item.removeAttribute("data-highlighted");
|
|
2063
|
-
item.setAttribute("data-zcodepro-item", "copy-path");
|
|
2064
|
-
for (const child of [...item.childNodes]) child.remove();
|
|
2065
|
-
const origIcon = anchorItem.querySelector("svg");
|
|
2066
|
-
const iconClass = origIcon ? origIcon.getAttribute("class") : "h-3.5 w-3.5";
|
|
2067
|
-
item.append(hCopyIcon(iconClass), document.createTextNode(L.copyPathItem));
|
|
2068
|
-
item.addEventListener("mouseenter", () => {
|
|
2069
|
-
for (const el of menu.querySelectorAll('[role="menuitem"]')) el.removeAttribute("data-highlighted");
|
|
2070
|
-
item.setAttribute("data-highlighted", "");
|
|
2071
|
-
});
|
|
2072
|
-
item.addEventListener("mouseleave", () => item.removeAttribute("data-highlighted"));
|
|
2073
|
-
item.addEventListener("click", () => {
|
|
2074
|
-
closeRadixMenu(menu);
|
|
2075
|
-
void copyText(project.path);
|
|
2076
|
-
});
|
|
2077
|
-
anchorItem.before(item);
|
|
2078
|
-
}
|
|
2079
|
-
async function copyText(text) {
|
|
2080
|
-
const L = t();
|
|
2081
|
-
if (await copyToClipboard(text)) showToast(L.pathCopied);
|
|
2082
|
-
else showToast(L.pathCopyFailed, "error");
|
|
2083
|
-
}
|
|
2084
|
-
async function copyToClipboard(text) {
|
|
2085
|
-
try {
|
|
2086
|
-
await navigator.clipboard.writeText(text);
|
|
2087
|
-
return true;
|
|
2088
|
-
} catch {
|
|
2089
|
-
return copyViaHiddenInput(text);
|
|
2090
|
-
}
|
|
2091
|
-
}
|
|
2092
|
-
function copyViaHiddenInput(text) {
|
|
2093
|
-
try {
|
|
2094
|
-
const input = h("input", { type: "text", style: "position:fixed;left:-9999px;top:0;opacity:0" });
|
|
2095
|
-
input.value = text;
|
|
2096
|
-
document.body.append(input);
|
|
2097
|
-
input.select();
|
|
2098
|
-
const ok = document.execCommand("copy");
|
|
2099
|
-
input.remove();
|
|
2100
|
-
return ok;
|
|
2101
|
-
} catch {
|
|
2102
|
-
return false;
|
|
2103
|
-
}
|
|
2104
|
-
}
|
|
2105
|
-
function hCopyIcon(cls) {
|
|
2106
|
-
const ns = "http://www.w3.org/2000/svg";
|
|
2107
|
-
const svg = document.createElementNS(ns, "svg");
|
|
2108
|
-
svg.setAttribute("viewBox", "0 0 24 24");
|
|
2109
|
-
svg.setAttribute("fill", "none");
|
|
2110
|
-
svg.setAttribute("stroke", "currentColor");
|
|
2111
|
-
svg.setAttribute("stroke-width", "2");
|
|
2112
|
-
svg.setAttribute("stroke-linecap", "round");
|
|
2113
|
-
svg.setAttribute("stroke-linejoin", "round");
|
|
2114
|
-
svg.setAttribute("class", cls);
|
|
2115
|
-
for (const d of [
|
|
2116
|
-
"M8 8h12a2 2 0 0 1 2 2v12a2 2 0 0 1-2 2H8a2 2 0 0 1-2-2V10a2 2 0 0 1 2-2Z",
|
|
2117
|
-
"M4 16c-1.1 0-2-.9-2-2V4a2 2 0 0 1 2-2h12a2 2 0 0 1 2 2"
|
|
2118
|
-
]) {
|
|
2119
|
-
const p = document.createElementNS(ns, "path");
|
|
2120
|
-
p.setAttribute("d", d);
|
|
2121
|
-
svg.append(p);
|
|
2122
|
-
}
|
|
2123
|
-
return svg;
|
|
2124
|
-
}
|
|
2125
|
-
|
|
2126
2305
|
// src/inject/features/project-menu.js
|
|
2127
2306
|
var REMOVE_TEXTS = ["\u79FB\u9664", "Remove"];
|
|
2128
2307
|
function extractPathFromTestId2(testid) {
|
|
@@ -2131,37 +2310,213 @@
|
|
|
2131
2310
|
m = testid.match(/[-:=,|]([A-Za-z]:\\.*)$/);
|
|
2132
2311
|
return m ? m[1] : null;
|
|
2133
2312
|
}
|
|
2134
|
-
function
|
|
2135
|
-
|
|
2313
|
+
function openMenuProjectRow() {
|
|
2314
|
+
const trigger = document.querySelector(
|
|
2315
|
+
'[data-testid="virtual-project-menu"][aria-expanded="true"], [data-testid="virtual-project-menu"][data-state="open"], [data-testid="virtual-project-row"][data-state="open"], [data-testid="virtual-project-row"][aria-expanded="true"]'
|
|
2316
|
+
);
|
|
2317
|
+
const row = trigger ? trigger.closest("section[data-project-id]") : null;
|
|
2318
|
+
if (!row) return null;
|
|
2319
|
+
const host = row.getAttribute("data-project-host");
|
|
2320
|
+
return host === null || host === "local" ? row : null;
|
|
2136
2321
|
}
|
|
2137
2322
|
async function resolveProjectPath(removeItem) {
|
|
2138
|
-
const
|
|
2139
|
-
const extracted = extractPathFromTestId2(testid);
|
|
2323
|
+
const extracted = extractPathFromTestId2(removeItem.getAttribute("data-testid") || "");
|
|
2140
2324
|
if (!extracted) return null;
|
|
2141
2325
|
const res = await rpc("/projects");
|
|
2142
2326
|
if (res.ok && Array.isArray(res.projects)) {
|
|
2143
|
-
const
|
|
2144
|
-
const hit = res.projects.find((p) =>
|
|
2327
|
+
const norm3 = (p) => String(p).replace(/[\\/]+$/, "");
|
|
2328
|
+
const hit = res.projects.find((p) => norm3(p.path) === norm3(extracted));
|
|
2145
2329
|
if (hit) return hit;
|
|
2146
2330
|
}
|
|
2147
|
-
return { path: extracted, name:
|
|
2331
|
+
return { path: extracted, name: String(extracted).replace(/[\\/]+$/, "").split(/[\\/]/).pop() || "" };
|
|
2332
|
+
}
|
|
2333
|
+
function cloneMenuItem(anchor, testid, label) {
|
|
2334
|
+
const item = anchor.cloneNode(true);
|
|
2335
|
+
item.removeAttribute("data-testid");
|
|
2336
|
+
item.removeAttribute("data-highlighted");
|
|
2337
|
+
item.removeAttribute("id");
|
|
2338
|
+
item.setAttribute("data-zcodepro-item", testid);
|
|
2339
|
+
for (const child of [...item.childNodes]) child.remove();
|
|
2340
|
+
const origIcon = anchor.querySelector("svg");
|
|
2341
|
+
const iconClass = origIcon ? origIcon.getAttribute("class") : "h-3.5 w-3.5";
|
|
2342
|
+
const ns = "http://www.w3.org/2000/svg";
|
|
2343
|
+
const svg = document.createElementNS(ns, "svg");
|
|
2344
|
+
svg.setAttribute("viewBox", "0 0 24 24");
|
|
2345
|
+
svg.setAttribute("fill", "none");
|
|
2346
|
+
svg.setAttribute("stroke", "currentColor");
|
|
2347
|
+
svg.setAttribute("stroke-width", "2");
|
|
2348
|
+
svg.setAttribute("stroke-linecap", "round");
|
|
2349
|
+
svg.setAttribute("stroke-linejoin", "round");
|
|
2350
|
+
svg.setAttribute("class", iconClass);
|
|
2351
|
+
const p = document.createElementNS(ns, "path");
|
|
2352
|
+
p.setAttribute("d", "M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z");
|
|
2353
|
+
svg.append(p);
|
|
2354
|
+
item.append(svg, document.createTextNode(label));
|
|
2355
|
+
return item;
|
|
2356
|
+
}
|
|
2357
|
+
function wireHighlight(menu, item) {
|
|
2358
|
+
item.addEventListener("mouseenter", () => {
|
|
2359
|
+
for (const el of menu.querySelectorAll('[role="menuitem"]')) el.removeAttribute("data-highlighted");
|
|
2360
|
+
item.setAttribute("data-highlighted", "");
|
|
2361
|
+
});
|
|
2362
|
+
item.addEventListener("mouseleave", () => item.removeAttribute("data-highlighted"));
|
|
2363
|
+
}
|
|
2364
|
+
function attachFolderHover(menu, item, roots) {
|
|
2365
|
+
const L = t();
|
|
2366
|
+
let sub = null;
|
|
2367
|
+
let subHovered = false;
|
|
2368
|
+
let hideTimer = 0;
|
|
2369
|
+
let aliveTimer = 0;
|
|
2370
|
+
const removeSub = () => {
|
|
2371
|
+
clearTimeout(hideTimer);
|
|
2372
|
+
clearInterval(aliveTimer);
|
|
2373
|
+
sub?.remove();
|
|
2374
|
+
sub = null;
|
|
2375
|
+
subHovered = false;
|
|
2376
|
+
};
|
|
2377
|
+
const position = () => {
|
|
2378
|
+
const rect = item.getBoundingClientRect();
|
|
2379
|
+
sub.style.left = rect.right + "px";
|
|
2380
|
+
sub.style.top = rect.top + "px";
|
|
2381
|
+
const r = sub.getBoundingClientRect();
|
|
2382
|
+
if (r.right > window.innerWidth - 8) {
|
|
2383
|
+
sub.style.left = "";
|
|
2384
|
+
sub.style.right = window.innerWidth - rect.left + "px";
|
|
2385
|
+
}
|
|
2386
|
+
};
|
|
2387
|
+
const ensureSub = () => {
|
|
2388
|
+
if (sub) {
|
|
2389
|
+
position();
|
|
2390
|
+
return;
|
|
2391
|
+
}
|
|
2392
|
+
sub = document.createElement("div");
|
|
2393
|
+
sub.setAttribute("role", "menu");
|
|
2394
|
+
sub.setAttribute("data-zcodepro-item", "open-folder-sub");
|
|
2395
|
+
sub.className = "zcodepro-card flex flex-col gap-0.5 rounded-lg border border-border bg-menu p-1 text-ui-sm shadow-lg";
|
|
2396
|
+
sub.style.cssText = "position:fixed;z-index:60;min-width:14rem;";
|
|
2397
|
+
for (const root of roots) {
|
|
2398
|
+
const base = String(root.path).replace(/[\\/]+$/, "").split(/[\\/]/).pop() || root.path;
|
|
2399
|
+
const row = document.createElement("div");
|
|
2400
|
+
row.setAttribute("role", "menuitem");
|
|
2401
|
+
row.className = "flex cursor-pointer items-center gap-2 truncate rounded-md px-2 py-1.5 text-foreground transition-colors hover:bg-surface-hover";
|
|
2402
|
+
row.title = root.path;
|
|
2403
|
+
row.append(document.createTextNode(base + (root.primary ? ` \xB7 ${L.openFolderPrimary}` : "")));
|
|
2404
|
+
row.addEventListener("click", () => {
|
|
2405
|
+
try {
|
|
2406
|
+
menu.dispatchEvent(new KeyboardEvent("keydown", { key: "Escape", code: "Escape", bubbles: true, cancelable: true }));
|
|
2407
|
+
} catch {
|
|
2408
|
+
}
|
|
2409
|
+
removeSub();
|
|
2410
|
+
void rpc("/open-folder", { method: "POST", body: { path: root.path } });
|
|
2411
|
+
});
|
|
2412
|
+
sub.append(row);
|
|
2413
|
+
}
|
|
2414
|
+
sub.addEventListener("mouseenter", () => {
|
|
2415
|
+
subHovered = true;
|
|
2416
|
+
clearTimeout(hideTimer);
|
|
2417
|
+
});
|
|
2418
|
+
sub.addEventListener("mouseleave", () => {
|
|
2419
|
+
subHovered = false;
|
|
2420
|
+
scheduleHide();
|
|
2421
|
+
});
|
|
2422
|
+
document.body.append(sub);
|
|
2423
|
+
position();
|
|
2424
|
+
aliveTimer = setInterval(() => {
|
|
2425
|
+
if (!menu.isConnected) removeSub();
|
|
2426
|
+
}, 400);
|
|
2427
|
+
};
|
|
2428
|
+
const scheduleHide = () => {
|
|
2429
|
+
clearTimeout(hideTimer);
|
|
2430
|
+
hideTimer = setTimeout(() => {
|
|
2431
|
+
if (!subHovered) removeSub();
|
|
2432
|
+
}, 300);
|
|
2433
|
+
};
|
|
2434
|
+
item.addEventListener("mouseenter", () => {
|
|
2435
|
+
clearTimeout(hideTimer);
|
|
2436
|
+
ensureSub();
|
|
2437
|
+
});
|
|
2438
|
+
item.addEventListener("mouseleave", scheduleHide);
|
|
2439
|
+
item.addEventListener("click", () => {
|
|
2440
|
+
clearTimeout(hideTimer);
|
|
2441
|
+
ensureSub();
|
|
2442
|
+
});
|
|
2443
|
+
}
|
|
2444
|
+
async function injectNewMenuItems(content, menuRow) {
|
|
2445
|
+
const L = t();
|
|
2446
|
+
const projectId = menuRow.getAttribute("data-project-id");
|
|
2447
|
+
const editItem = content.querySelector('[data-testid="virtual-project-edit"]');
|
|
2448
|
+
if (!editItem || !projectId) return;
|
|
2449
|
+
if (content.querySelector("[data-zcodepro-item]")) return;
|
|
2450
|
+
const config = await getConfig();
|
|
2451
|
+
if (config.features && config.features.projectMenu === false) return;
|
|
2452
|
+
const res = await rpc("/projects-v2");
|
|
2453
|
+
if (!res.ok || !res.available) return;
|
|
2454
|
+
const proj = (res.projects || []).find((p) => p.id === projectId);
|
|
2455
|
+
if (!proj) return;
|
|
2456
|
+
const roots = (proj.roots || []).slice().sort((a, b) => (b.primary ? 1 : 0) - (a.primary ? 1 : 0));
|
|
2457
|
+
if (!roots.length) return;
|
|
2458
|
+
const primary = roots.find((r) => r.primary) || roots[0];
|
|
2459
|
+
const openItem = cloneMenuItem(editItem, "open-folder", L.openFolderItem);
|
|
2460
|
+
wireHighlight(content, openItem);
|
|
2461
|
+
if (roots.length === 1) {
|
|
2462
|
+
openItem.addEventListener("click", () => {
|
|
2463
|
+
try {
|
|
2464
|
+
content.dispatchEvent(new KeyboardEvent("keydown", { key: "Escape", code: "Escape", bubbles: true, cancelable: true }));
|
|
2465
|
+
} catch {
|
|
2466
|
+
}
|
|
2467
|
+
void rpc("/open-folder", { method: "POST", body: { path: primary.path } });
|
|
2468
|
+
});
|
|
2469
|
+
} else {
|
|
2470
|
+
const ns = "http://www.w3.org/2000/svg";
|
|
2471
|
+
const chev = document.createElementNS(ns, "svg");
|
|
2472
|
+
chev.setAttribute("viewBox", "0 0 24 24");
|
|
2473
|
+
chev.setAttribute("fill", "none");
|
|
2474
|
+
chev.setAttribute("stroke", "currentColor");
|
|
2475
|
+
chev.setAttribute("stroke-width", "2");
|
|
2476
|
+
chev.setAttribute("stroke-linecap", "round");
|
|
2477
|
+
chev.setAttribute("stroke-linejoin", "round");
|
|
2478
|
+
chev.setAttribute("class", "ml-auto size-3.5 shrink-0 text-foreground-subtle");
|
|
2479
|
+
const chevPath = document.createElementNS(ns, "path");
|
|
2480
|
+
chevPath.setAttribute("d", "m9 18 6-6-6-6");
|
|
2481
|
+
chev.append(chevPath);
|
|
2482
|
+
openItem.append(chev);
|
|
2483
|
+
attachFolderHover(content, openItem, roots);
|
|
2484
|
+
}
|
|
2485
|
+
editItem.after(openItem);
|
|
2486
|
+
const copyItem = cloneMenuItem(editItem, "copy-path", L.copyPathItem);
|
|
2487
|
+
wireHighlight(content, copyItem);
|
|
2488
|
+
copyItem.addEventListener("click", () => {
|
|
2489
|
+
try {
|
|
2490
|
+
content.dispatchEvent(new KeyboardEvent("keydown", { key: "Escape", code: "Escape", bubbles: true, cancelable: true }));
|
|
2491
|
+
} catch {
|
|
2492
|
+
}
|
|
2493
|
+
void copyToClipboard(primary.path).then((ok) => showToast(ok ? L.pathCopied : L.pathCopyFailed, ok ? void 0 : "error"));
|
|
2494
|
+
});
|
|
2495
|
+
openItem.after(copyItem);
|
|
2148
2496
|
}
|
|
2149
2497
|
function handleProjectMenu(content) {
|
|
2150
|
-
if (content.querySelector(
|
|
2498
|
+
if (content.querySelector("[data-zcodepro-item]")) return;
|
|
2151
2499
|
const items = itemsOf(content);
|
|
2152
|
-
const
|
|
2500
|
+
const newUi = isNewProjectSidebar();
|
|
2501
|
+
const menuRow = newUi ? openMenuProjectRow() : null;
|
|
2502
|
+
const anchor = newUi ? items.find((el) => el.getAttribute("data-testid") === "virtual-project-edit") : items.find(
|
|
2153
2503
|
(el) => el.hasAttribute("data-testid") && REMOVE_TEXTS.some((x) => itemText(el).startsWith(x))
|
|
2154
2504
|
);
|
|
2155
|
-
if (!
|
|
2505
|
+
if (!anchor) return;
|
|
2506
|
+
if (newUi) {
|
|
2507
|
+
if (!menuRow) return;
|
|
2508
|
+
void injectNewMenuItems(content, menuRow);
|
|
2509
|
+
return;
|
|
2510
|
+
}
|
|
2156
2511
|
void (async () => {
|
|
2157
2512
|
const config = await getConfig();
|
|
2158
2513
|
if (config.features && config.features.projectMenu === false) return;
|
|
2159
|
-
const project = await resolveProjectPath(
|
|
2514
|
+
const project = await resolveProjectPath(anchor);
|
|
2160
2515
|
if (!project) return;
|
|
2161
|
-
appendAliasItem(content,
|
|
2162
|
-
appendRelocateItem(content,
|
|
2163
|
-
appendOpenFolderItem(content,
|
|
2164
|
-
appendCopyPathItem(content,
|
|
2516
|
+
appendAliasItem(content, anchor, project);
|
|
2517
|
+
appendRelocateItem(content, anchor, project);
|
|
2518
|
+
appendOpenFolderItem(content, anchor, project);
|
|
2519
|
+
appendCopyPathItem(content, anchor, project);
|
|
2165
2520
|
})();
|
|
2166
2521
|
}
|
|
2167
2522
|
|
|
@@ -2554,40 +2909,523 @@
|
|
|
2554
2909
|
return v === "" || v !== "session" && !providers.some((p) => p.id === v);
|
|
2555
2910
|
}
|
|
2556
2911
|
|
|
2557
|
-
// src/inject/features/
|
|
2558
|
-
var
|
|
2559
|
-
|
|
2560
|
-
|
|
2561
|
-
|
|
2562
|
-
|
|
2563
|
-
|
|
2564
|
-
|
|
2565
|
-
|
|
2566
|
-
|
|
2567
|
-
|
|
2568
|
-
|
|
2569
|
-
|
|
2570
|
-
|
|
2571
|
-
|
|
2572
|
-
|
|
2573
|
-
|
|
2574
|
-
|
|
2575
|
-
|
|
2576
|
-
|
|
2577
|
-
|
|
2578
|
-
|
|
2579
|
-
|
|
2580
|
-
|
|
2581
|
-
|
|
2582
|
-
|
|
2583
|
-
|
|
2584
|
-
|
|
2585
|
-
|
|
2586
|
-
|
|
2587
|
-
|
|
2588
|
-
|
|
2589
|
-
|
|
2590
|
-
|
|
2912
|
+
// src/inject/features/ws-rows.js
|
|
2913
|
+
var norm2 = (p) => String(p || "").replace(/[\\/]+$/, "");
|
|
2914
|
+
var NEW_ROW_SEL = "section[data-project-id]";
|
|
2915
|
+
var OLD_ROW_SEL = '[data-testid^="workspace-item-"]';
|
|
2916
|
+
var pathByProjectId = /* @__PURE__ */ new Map();
|
|
2917
|
+
function projectRowSelector() {
|
|
2918
|
+
return isNewProjectSidebar() ? NEW_ROW_SEL : OLD_ROW_SEL;
|
|
2919
|
+
}
|
|
2920
|
+
function projectRows(root = document) {
|
|
2921
|
+
return [...root.querySelectorAll(projectRowSelector())];
|
|
2922
|
+
}
|
|
2923
|
+
function rowPath(row) {
|
|
2924
|
+
if (!row) return null;
|
|
2925
|
+
if (row.hasAttribute && row.hasAttribute("data-project-id")) {
|
|
2926
|
+
const host = row.getAttribute("data-project-host");
|
|
2927
|
+
if (host !== null && host !== "local") return null;
|
|
2928
|
+
const id = row.getAttribute("data-project-id");
|
|
2929
|
+
let found = null;
|
|
2930
|
+
for (const el of row.querySelectorAll("[data-task-item-key]")) {
|
|
2931
|
+
const key = el.getAttribute("data-task-item-key") || "";
|
|
2932
|
+
const cut = key.lastIndexOf(":");
|
|
2933
|
+
if (cut > 1) {
|
|
2934
|
+
found = key.slice(0, cut);
|
|
2935
|
+
break;
|
|
2936
|
+
}
|
|
2937
|
+
}
|
|
2938
|
+
if (found) pathByProjectId.set(id, found);
|
|
2939
|
+
return found || pathByProjectId.get(id) || null;
|
|
2940
|
+
}
|
|
2941
|
+
const testid = row.getAttribute && row.getAttribute("data-testid");
|
|
2942
|
+
if (!testid || !testid.startsWith("workspace-item-")) return null;
|
|
2943
|
+
return norm2(testid.slice("workspace-item-".length)) || null;
|
|
2944
|
+
}
|
|
2945
|
+
function findProjectRow(path) {
|
|
2946
|
+
const want = norm2(path);
|
|
2947
|
+
if (!want) return null;
|
|
2948
|
+
for (const row of projectRows()) {
|
|
2949
|
+
const p = rowPath(row);
|
|
2950
|
+
if (p && norm2(p) === want) return row;
|
|
2951
|
+
}
|
|
2952
|
+
return null;
|
|
2953
|
+
}
|
|
2954
|
+
|
|
2955
|
+
// src/inject/features/alias-migration.js
|
|
2956
|
+
var sleep = (ms) => new Promise((r) => setTimeout(r, ms));
|
|
2957
|
+
var basenameOf2 = (p) => String(p || "").replace(/[\\/]+$/, "").split(/[\\/]/).pop() || "";
|
|
2958
|
+
function waitFor(getter, timeoutMs, step) {
|
|
2959
|
+
const start = Date.now();
|
|
2960
|
+
return new Promise((resolve, reject) => {
|
|
2961
|
+
const tick2 = () => {
|
|
2962
|
+
let v = null;
|
|
2963
|
+
try {
|
|
2964
|
+
v = getter();
|
|
2965
|
+
} catch {
|
|
2966
|
+
}
|
|
2967
|
+
if (v) {
|
|
2968
|
+
resolve(v);
|
|
2969
|
+
return;
|
|
2970
|
+
}
|
|
2971
|
+
if (Date.now() - start >= timeoutMs) {
|
|
2972
|
+
reject(new Error(step));
|
|
2973
|
+
return;
|
|
2974
|
+
}
|
|
2975
|
+
setTimeout(tick2, 120);
|
|
2976
|
+
};
|
|
2977
|
+
tick2();
|
|
2978
|
+
});
|
|
2979
|
+
}
|
|
2980
|
+
function setReactInputValue(input, value) {
|
|
2981
|
+
const setter = Object.getOwnPropertyDescriptor(input.constructor.prototype, "value")?.set || Object.getOwnPropertyDescriptor(window.HTMLInputElement.prototype, "value")?.set;
|
|
2982
|
+
if (!setter) throw new Error("input-setter");
|
|
2983
|
+
setter.call(input, value);
|
|
2984
|
+
input.dispatchEvent(new Event("input", { bubbles: true }));
|
|
2985
|
+
}
|
|
2986
|
+
function pressEscape() {
|
|
2987
|
+
try {
|
|
2988
|
+
document.dispatchEvent(new KeyboardEvent("keydown", { key: "Escape", code: "Escape", bubbles: true, cancelable: true }));
|
|
2989
|
+
} catch {
|
|
2990
|
+
}
|
|
2991
|
+
}
|
|
2992
|
+
async function markDismissed() {
|
|
2993
|
+
await rpc("/config", { method: "POST", body: { migrations: { aliasRenameDismissed: true } } });
|
|
2994
|
+
clearConfigCache();
|
|
2995
|
+
}
|
|
2996
|
+
var MIGRATE_LOCK_KEY = "zcodepro:alias-migrate-lock";
|
|
2997
|
+
var MIGRATE_LOCK_MS = 5 * 6e4;
|
|
2998
|
+
function migrateLockFresh() {
|
|
2999
|
+
try {
|
|
3000
|
+
const at = Number(localStorage.getItem(MIGRATE_LOCK_KEY));
|
|
3001
|
+
return Number.isFinite(at) && Date.now() - at < MIGRATE_LOCK_MS;
|
|
3002
|
+
} catch {
|
|
3003
|
+
return false;
|
|
3004
|
+
}
|
|
3005
|
+
}
|
|
3006
|
+
function touchMigrateLock() {
|
|
3007
|
+
try {
|
|
3008
|
+
localStorage.setItem(MIGRATE_LOCK_KEY, String(Date.now()));
|
|
3009
|
+
} catch {
|
|
3010
|
+
}
|
|
3011
|
+
}
|
|
3012
|
+
async function migrateOne(path, alias) {
|
|
3013
|
+
if (document.querySelector('[data-testid="virtual-project-name"], [role="menu"]')) {
|
|
3014
|
+
pressEscape();
|
|
3015
|
+
await sleep(300);
|
|
3016
|
+
}
|
|
3017
|
+
let row = findProjectRow(path);
|
|
3018
|
+
if (!row) {
|
|
3019
|
+
const byName = [...document.querySelectorAll("section[data-project-id]")].filter((el) => {
|
|
3020
|
+
const host = el.getAttribute("data-project-host");
|
|
3021
|
+
return (host === null || host === "local") && el.getAttribute("data-project-name") === basenameOf2(path);
|
|
3022
|
+
});
|
|
3023
|
+
if (byName.length === 1) row = byName[0];
|
|
3024
|
+
}
|
|
3025
|
+
if (!row) throw new Error("project-row");
|
|
3026
|
+
const projectId = row.getAttribute("data-project-id");
|
|
3027
|
+
const rowById = () => document.querySelector(`section[data-project-id="${CSS.escape(projectId)}"]`);
|
|
3028
|
+
try {
|
|
3029
|
+
row.scrollIntoView({ block: "center" });
|
|
3030
|
+
} catch {
|
|
3031
|
+
}
|
|
3032
|
+
const trigger = await waitFor(
|
|
3033
|
+
() => rowById()?.querySelector('[data-testid="virtual-project-menu"]'),
|
|
3034
|
+
4e3,
|
|
3035
|
+
"menu-trigger"
|
|
3036
|
+
);
|
|
3037
|
+
trigger.dispatchEvent(new PointerEvent("pointerdown", { bubbles: true, cancelable: true, pointerId: 1, isPrimary: true, button: 0 }));
|
|
3038
|
+
trigger.dispatchEvent(new PointerEvent("pointerup", { bubbles: true, cancelable: true, pointerId: 1, isPrimary: true, button: 0 }));
|
|
3039
|
+
trigger.click();
|
|
3040
|
+
const menu = await waitFor(() => {
|
|
3041
|
+
for (const m of document.querySelectorAll('[role="menu"]')) {
|
|
3042
|
+
if (m.querySelector('[data-testid="virtual-project-edit"]')) return m;
|
|
3043
|
+
}
|
|
3044
|
+
return null;
|
|
3045
|
+
}, 4e3, "menu-open");
|
|
3046
|
+
menu.querySelector('[data-testid="virtual-project-edit"]').click();
|
|
3047
|
+
const input = await waitFor(
|
|
3048
|
+
() => document.querySelector('[data-testid="virtual-project-name"]'),
|
|
3049
|
+
5e3,
|
|
3050
|
+
"editor-open"
|
|
3051
|
+
);
|
|
3052
|
+
const wantName = alias.trim();
|
|
3053
|
+
setReactInputValue(input, wantName);
|
|
3054
|
+
const save = await waitFor(
|
|
3055
|
+
() => {
|
|
3056
|
+
const btn = document.querySelector('[data-testid="virtual-project-save"]');
|
|
3057
|
+
return btn && !btn.disabled ? btn : null;
|
|
3058
|
+
},
|
|
3059
|
+
4e3,
|
|
3060
|
+
"save-ready"
|
|
3061
|
+
);
|
|
3062
|
+
save.click();
|
|
3063
|
+
await waitFor(() => {
|
|
3064
|
+
const r = rowById();
|
|
3065
|
+
return r && r.getAttribute("data-project-name") === wantName ? r : null;
|
|
3066
|
+
}, 8e3, "name-updated");
|
|
3067
|
+
await sleep(250);
|
|
3068
|
+
if (document.querySelector('[data-testid="virtual-project-name"]')) pressEscape();
|
|
3069
|
+
const res = await rpc("/project/alias", { method: "POST", body: { path, alias: "" } });
|
|
3070
|
+
if (!res.ok) throw new Error("alias-clear");
|
|
3071
|
+
}
|
|
3072
|
+
async function classifyEntry(path, alias, db) {
|
|
3073
|
+
const want = norm0(path);
|
|
3074
|
+
if (db) {
|
|
3075
|
+
let alsoDeleted = false;
|
|
3076
|
+
for (const proj of db.projects || []) {
|
|
3077
|
+
const hit = (proj.roots || []).find((r) => norm0(r.path) === want);
|
|
3078
|
+
if (!hit) continue;
|
|
3079
|
+
if (hit.primary) {
|
|
3080
|
+
if (proj.name === alias) return { state: "done", note: "" };
|
|
3081
|
+
return { state: "", note: "", overridden: !!proj.overridden };
|
|
3082
|
+
}
|
|
3083
|
+
alsoDeleted = (db.deletedRoots || []).some((p) => norm0(p) === want);
|
|
3084
|
+
return { state: "merged", note: proj.name, alsoDeleted };
|
|
3085
|
+
}
|
|
3086
|
+
if ((db.deletedRoots || []).some((p) => norm0(p) === want)) return { state: "deleted", note: "" };
|
|
3087
|
+
return { state: "missing", note: "" };
|
|
3088
|
+
}
|
|
3089
|
+
const localRows = [...document.querySelectorAll("section[data-project-id]")].filter((el) => {
|
|
3090
|
+
const host = el.getAttribute("data-project-host");
|
|
3091
|
+
return host === null || host === "local";
|
|
3092
|
+
});
|
|
3093
|
+
const byPath = localRows.find((el) => norm0(rowPath(el)) === want);
|
|
3094
|
+
if (byPath) {
|
|
3095
|
+
return (byPath.getAttribute("data-project-name") || "") === alias ? { state: "done", note: "" } : { state: "", note: "" };
|
|
3096
|
+
}
|
|
3097
|
+
const byName = localRows.filter((el) => el.getAttribute("data-project-name") === alias);
|
|
3098
|
+
if (byName.length === 1) return { state: "done", note: "" };
|
|
3099
|
+
for (const task of document.querySelectorAll("[data-task-item-key]")) {
|
|
3100
|
+
const key = task.getAttribute("data-task-item-key") || "";
|
|
3101
|
+
const cut = key.lastIndexOf(":");
|
|
3102
|
+
if (cut <= 1 || norm0(key.slice(0, cut)) !== want) continue;
|
|
3103
|
+
const owner = task.closest("section[data-project-id]");
|
|
3104
|
+
const ownerName = owner ? owner.getAttribute("data-project-name") || "" : "";
|
|
3105
|
+
if (ownerName) return { state: "merged", note: ownerName };
|
|
3106
|
+
}
|
|
3107
|
+
return { state: "missing", note: "" };
|
|
3108
|
+
}
|
|
3109
|
+
async function fetchProjectDb() {
|
|
3110
|
+
const res = await rpc("/projects-v2");
|
|
3111
|
+
return res.ok && res.available ? res : null;
|
|
3112
|
+
}
|
|
3113
|
+
var norm0 = (p) => String(p || "").replace(/[\\/]+$/, "");
|
|
3114
|
+
function openMigrationDialog() {
|
|
3115
|
+
ensureStyle();
|
|
3116
|
+
const L = t();
|
|
3117
|
+
let running = false;
|
|
3118
|
+
let decided = false;
|
|
3119
|
+
const decide = () => {
|
|
3120
|
+
if (decided) return;
|
|
3121
|
+
decided = true;
|
|
3122
|
+
void markDismissed();
|
|
3123
|
+
};
|
|
3124
|
+
touchMigrateLock();
|
|
3125
|
+
openDialog({
|
|
3126
|
+
title: L.aliasMigrateTitle,
|
|
3127
|
+
description: L.aliasMigrateDesc,
|
|
3128
|
+
width: "sm:max-w-md",
|
|
3129
|
+
// 迁移不可中途撤销且过程可见:点遮罩不关闭(防误触),右上角 ✕ 关闭
|
|
3130
|
+
dismissOnOutside: false,
|
|
3131
|
+
closable: true,
|
|
3132
|
+
onClose: () => {
|
|
3133
|
+
decide();
|
|
3134
|
+
window.dispatchEvent(new CustomEvent("zcodepro:aliases-changed"));
|
|
3135
|
+
},
|
|
3136
|
+
onMount: ({ body, close }) => {
|
|
3137
|
+
void (async () => {
|
|
3138
|
+
const config = await getConfig(true);
|
|
3139
|
+
const db = await fetchProjectDb();
|
|
3140
|
+
const entries = [];
|
|
3141
|
+
for (const [path, aliasRaw] of Object.entries(config.aliases || {})) {
|
|
3142
|
+
const alias = String(aliasRaw || "").trim();
|
|
3143
|
+
if (!alias) continue;
|
|
3144
|
+
const cls = await classifyEntry(path, alias, db);
|
|
3145
|
+
entries.push({
|
|
3146
|
+
path,
|
|
3147
|
+
alias,
|
|
3148
|
+
checked: cls.state === "" && !cls.overridden,
|
|
3149
|
+
state: cls.state,
|
|
3150
|
+
note: cls.note || "",
|
|
3151
|
+
overridden: !!cls.overridden,
|
|
3152
|
+
alsoDeleted: !!cls.alsoDeleted
|
|
3153
|
+
});
|
|
3154
|
+
}
|
|
3155
|
+
if (!entries.length) {
|
|
3156
|
+
close();
|
|
3157
|
+
return;
|
|
3158
|
+
}
|
|
3159
|
+
const badgesOf = (e) => {
|
|
3160
|
+
const out = [];
|
|
3161
|
+
if (e.state === "run") out.push({ text: L.aliasMigrateRunning, cls: "text-amber-500" });
|
|
3162
|
+
if (e.state === "ok") out.push({ text: L.aliasMigrateStateDone, cls: "text-emerald-600" });
|
|
3163
|
+
if (e.state === "fail") out.push({ text: L.aliasMigrateStateFailed, cls: "text-destructive" });
|
|
3164
|
+
if (e.state === "done") out.push({ text: L.aliasMigrateStateDone, cls: "text-emerald-600" });
|
|
3165
|
+
if (e.state === "merged") out.push({ text: L.aliasMigrateStateMerged.replace("{name}", e.note), cls: "text-amber-500" });
|
|
3166
|
+
if (e.state === "deleted" || e.state === "merged" && e.alsoDeleted) out.push({ text: L.aliasMigrateStateDeleted, cls: "text-foreground-subtle/70" });
|
|
3167
|
+
if (e.state === "missing") out.push({ text: L.aliasMigrateStateMissing, cls: "text-foreground-subtle/70" });
|
|
3168
|
+
if (e.state === "" && e.overridden) out.push({ text: L.aliasMigrateStateRenamed, cls: "text-foreground-subtle/70" });
|
|
3169
|
+
return out;
|
|
3170
|
+
};
|
|
3171
|
+
const progressEl = h("div", { class: "mb-1 text-ui-xs text-foreground-subtle", style: "display:none" });
|
|
3172
|
+
const listEl = h("div", { class: "max-h-[50vh] space-y-1.5 overflow-y-auto" });
|
|
3173
|
+
let deadOpen = false;
|
|
3174
|
+
const renderList = () => {
|
|
3175
|
+
const alive = entries.filter((e) => e.state !== "missing" && e.state !== "deleted");
|
|
3176
|
+
const dead = entries.filter((e) => e.state === "missing" || e.state === "deleted");
|
|
3177
|
+
const rowOf = (e, deadRow) => {
|
|
3178
|
+
const cb = h("input", { type: "checkbox" });
|
|
3179
|
+
cb.checked = e.checked;
|
|
3180
|
+
cb.disabled = running || e.state !== "" && e.state !== "fail" || e.overridden;
|
|
3181
|
+
cb.addEventListener("change", () => {
|
|
3182
|
+
e.checked = cb.checked;
|
|
3183
|
+
});
|
|
3184
|
+
const badges = badgesOf(e);
|
|
3185
|
+
const dim = deadRow || e.state !== "" && e.state !== "fail" && e.state !== "run" || e.overridden;
|
|
3186
|
+
return h(
|
|
3187
|
+
"label",
|
|
3188
|
+
{ class: "flex cursor-pointer items-start gap-2 rounded-lg p-2 transition-colors hover:bg-surface-hover" + (dim ? " opacity-60" : "") },
|
|
3189
|
+
h("span", { class: "mt-0.5" }, cb),
|
|
3190
|
+
h(
|
|
3191
|
+
"span",
|
|
3192
|
+
{ class: "min-w-0 flex-1" },
|
|
3193
|
+
h("span", { class: "block truncate text-ui-sm font-medium text-foreground" }, e.alias),
|
|
3194
|
+
h("span", { class: "block truncate font-mono text-ui-xs text-foreground-subtle" }, e.path)
|
|
3195
|
+
),
|
|
3196
|
+
...badges.map((b) => h("span", { class: "shrink-0 self-center text-ui-xs " + b.cls }, b.text))
|
|
3197
|
+
);
|
|
3198
|
+
};
|
|
3199
|
+
const parts = alive.map((e) => rowOf(e, false));
|
|
3200
|
+
if (dead.length) {
|
|
3201
|
+
const deadRows = h(
|
|
3202
|
+
"div",
|
|
3203
|
+
{ class: "space-y-1", style: deadOpen ? "" : "display:none" },
|
|
3204
|
+
...dead.map((e) => rowOf(e, true))
|
|
3205
|
+
);
|
|
3206
|
+
const toggle2 = h("button", {
|
|
3207
|
+
type: "button",
|
|
3208
|
+
class: "flex w-full items-center gap-1 rounded-lg p-2 text-left text-ui-xs text-foreground-subtle transition-colors hover:bg-surface-hover",
|
|
3209
|
+
onClick: () => {
|
|
3210
|
+
deadOpen = !deadOpen;
|
|
3211
|
+
renderList();
|
|
3212
|
+
}
|
|
3213
|
+
}, (deadOpen ? "\u25BE " : "\u25B8 ") + L.aliasMigrateDeadSummary.replace("{n}", String(dead.length)));
|
|
3214
|
+
parts.push(toggle2, deadRows);
|
|
3215
|
+
}
|
|
3216
|
+
listEl.replaceChildren(...parts);
|
|
3217
|
+
};
|
|
3218
|
+
renderList();
|
|
3219
|
+
const clearDead = async () => {
|
|
3220
|
+
if (running) return;
|
|
3221
|
+
const dead = entries.filter((e) => e.state === "missing" || e.state === "deleted");
|
|
3222
|
+
if (!dead.length) return;
|
|
3223
|
+
running = true;
|
|
3224
|
+
goBtn.setAttribute("disabled", "true");
|
|
3225
|
+
let ok = 0;
|
|
3226
|
+
for (const e of dead) {
|
|
3227
|
+
const r = await rpc("/project/alias", { method: "POST", body: { path: e.path, alias: "" } });
|
|
3228
|
+
if (r.ok) {
|
|
3229
|
+
ok++;
|
|
3230
|
+
entries.splice(entries.indexOf(e), 1);
|
|
3231
|
+
}
|
|
3232
|
+
}
|
|
3233
|
+
running = false;
|
|
3234
|
+
goBtn.removeAttribute("disabled");
|
|
3235
|
+
goBtn.textContent = L.aliasMigrateGo;
|
|
3236
|
+
clearConfigCache();
|
|
3237
|
+
renderList();
|
|
3238
|
+
window.dispatchEvent(new CustomEvent("zcodepro:aliases-changed"));
|
|
3239
|
+
if (ok === dead.length) showToast(L.aliasMigrateDeadCleared.replace("{n}", String(ok)));
|
|
3240
|
+
else showToast(L.aliasMigrateDeadClearFailed, "error");
|
|
3241
|
+
};
|
|
3242
|
+
const goBtn = btnPrimary(L.aliasMigrateGo, () => {
|
|
3243
|
+
void run();
|
|
3244
|
+
}, "min-w-24");
|
|
3245
|
+
const run = async () => {
|
|
3246
|
+
if (running) return;
|
|
3247
|
+
const todo = entries.filter((e) => e.checked);
|
|
3248
|
+
if (!todo.length) return;
|
|
3249
|
+
running = true;
|
|
3250
|
+
goBtn.setAttribute("disabled", "true");
|
|
3251
|
+
goBtn.textContent = L.aliasMigrateRunning;
|
|
3252
|
+
let ok = 0;
|
|
3253
|
+
const failed = [];
|
|
3254
|
+
for (let i = 0; i < todo.length; i++) {
|
|
3255
|
+
const e = todo[i];
|
|
3256
|
+
progressEl.style.display = "";
|
|
3257
|
+
progressEl.textContent = L.aliasMigrateProgress.replace("{i}", String(i + 1)).replace("{n}", String(todo.length)).replace("{name}", e.alias);
|
|
3258
|
+
e.state = "run";
|
|
3259
|
+
renderList();
|
|
3260
|
+
try {
|
|
3261
|
+
await migrateOne(e.path, e.alias);
|
|
3262
|
+
e.state = "ok";
|
|
3263
|
+
e.checked = false;
|
|
3264
|
+
ok++;
|
|
3265
|
+
} catch (err) {
|
|
3266
|
+
console.warn("[zcodepro] alias-migrate: " + e.path + " \u5931\u8D25\u4E8E " + (err && err.message));
|
|
3267
|
+
e.state = "fail";
|
|
3268
|
+
failed.push(e);
|
|
3269
|
+
}
|
|
3270
|
+
renderList();
|
|
3271
|
+
}
|
|
3272
|
+
running = false;
|
|
3273
|
+
progressEl.style.display = "none";
|
|
3274
|
+
goBtn.removeAttribute("disabled");
|
|
3275
|
+
goBtn.textContent = L.aliasMigrateGo;
|
|
3276
|
+
decide();
|
|
3277
|
+
close();
|
|
3278
|
+
if (!failed.length) {
|
|
3279
|
+
showToast(L.aliasMigrateDone.replace("{n}", String(ok)), "ok");
|
|
3280
|
+
} else if (ok) {
|
|
3281
|
+
showToast(L.aliasMigratePartial.replace("{n}", String(ok)).replace("{m}", String(failed.length)), "error");
|
|
3282
|
+
} else {
|
|
3283
|
+
showToast(L.aliasMigrateAllFailed, "error");
|
|
3284
|
+
}
|
|
3285
|
+
};
|
|
3286
|
+
body.append(
|
|
3287
|
+
progressEl,
|
|
3288
|
+
listEl,
|
|
3289
|
+
h("p", { class: "text-ui-xs/relaxed text-foreground-subtle" }, L.aliasMigrateItemHint),
|
|
3290
|
+
(() => {
|
|
3291
|
+
const footer = document.createElement("div");
|
|
3292
|
+
footer.className = "mt-6 flex flex-col-reverse gap-2 sm:flex-row sm:justify-end";
|
|
3293
|
+
const hasDead = entries.some((e) => e.state === "missing" || e.state === "deleted");
|
|
3294
|
+
if (hasDead) {
|
|
3295
|
+
const clearBtn = btnSecondary(L.aliasMigrateClearDead, () => {
|
|
3296
|
+
void clearDead().then(() => {
|
|
3297
|
+
if (!entries.some((e) => e.state === "missing" || e.state === "deleted")) clearBtn.style.display = "none";
|
|
3298
|
+
});
|
|
3299
|
+
});
|
|
3300
|
+
footer.append(clearBtn);
|
|
3301
|
+
}
|
|
3302
|
+
footer.append(
|
|
3303
|
+
btnSecondary(L.aliasMigrateSkip, () => {
|
|
3304
|
+
if (running) return;
|
|
3305
|
+
decide();
|
|
3306
|
+
close();
|
|
3307
|
+
}),
|
|
3308
|
+
goBtn
|
|
3309
|
+
);
|
|
3310
|
+
return footer;
|
|
3311
|
+
})()
|
|
3312
|
+
);
|
|
3313
|
+
})();
|
|
3314
|
+
}
|
|
3315
|
+
});
|
|
3316
|
+
}
|
|
3317
|
+
function migrationCard() {
|
|
3318
|
+
const L = t();
|
|
3319
|
+
const card = h("div", {
|
|
3320
|
+
class: "flex items-center gap-2 rounded-lg p-2",
|
|
3321
|
+
"data-zcodepro-migration-card": ""
|
|
3322
|
+
});
|
|
3323
|
+
const render = (count) => {
|
|
3324
|
+
card.replaceChildren(
|
|
3325
|
+
h(
|
|
3326
|
+
"div",
|
|
3327
|
+
{ class: "min-w-0 flex-1" },
|
|
3328
|
+
h("div", { class: "text-ui-sm font-medium text-foreground" }, L.aliasMigrateCardName),
|
|
3329
|
+
h(
|
|
3330
|
+
"div",
|
|
3331
|
+
{ class: "mt-0.5 text-ui-xs/relaxed text-foreground-subtle" },
|
|
3332
|
+
count === null ? "\u2026" : L.aliasMigrateCardDesc.replace("{n}", String(count))
|
|
3333
|
+
)
|
|
3334
|
+
),
|
|
3335
|
+
btnSmall(L.aliasMigrateRun, () => {
|
|
3336
|
+
openMigrationDialog();
|
|
3337
|
+
})
|
|
3338
|
+
);
|
|
3339
|
+
};
|
|
3340
|
+
render(null);
|
|
3341
|
+
const refresh = async () => {
|
|
3342
|
+
const config = await getConfig(true);
|
|
3343
|
+
const db = await fetchProjectDb();
|
|
3344
|
+
let count = 0;
|
|
3345
|
+
for (const [p, a] of Object.entries(config.aliases || {})) {
|
|
3346
|
+
if (!String(a || "").trim()) continue;
|
|
3347
|
+
const cls = await classifyEntry(p, String(a).trim(), db);
|
|
3348
|
+
if (cls.state === "" && !cls.overridden) count++;
|
|
3349
|
+
}
|
|
3350
|
+
if (!count) {
|
|
3351
|
+
card.remove();
|
|
3352
|
+
return;
|
|
3353
|
+
}
|
|
3354
|
+
render(count);
|
|
3355
|
+
};
|
|
3356
|
+
const onAliasesChanged = () => {
|
|
3357
|
+
if (!card.isConnected) {
|
|
3358
|
+
window.removeEventListener("zcodepro:aliases-changed", onAliasesChanged);
|
|
3359
|
+
return;
|
|
3360
|
+
}
|
|
3361
|
+
void refresh();
|
|
3362
|
+
};
|
|
3363
|
+
window.addEventListener("zcodepro:aliases-changed", onAliasesChanged);
|
|
3364
|
+
void refresh();
|
|
3365
|
+
return card;
|
|
3366
|
+
}
|
|
3367
|
+
function startAliasMigrationWatcher() {
|
|
3368
|
+
if (!officialRenameSupported() && !isNewProjectSidebar()) return;
|
|
3369
|
+
void (async () => {
|
|
3370
|
+
try {
|
|
3371
|
+
const config = await getConfig();
|
|
3372
|
+
const hasAliases = Object.values(config.aliases || {}).some((a) => String(a || "").trim());
|
|
3373
|
+
if (!hasAliases) return;
|
|
3374
|
+
if (config.migrations && config.migrations.aliasRenameDismissed) return;
|
|
3375
|
+
await waitFor(() => document.querySelector("section[data-project-id]"), 45e3, "sidebar");
|
|
3376
|
+
let focused = false;
|
|
3377
|
+
for (let i = 0; i < 600; i++) {
|
|
3378
|
+
if (document.visibilityState === "visible" && document.hasFocus()) {
|
|
3379
|
+
focused = true;
|
|
3380
|
+
break;
|
|
3381
|
+
}
|
|
3382
|
+
await sleep(500);
|
|
3383
|
+
}
|
|
3384
|
+
if (!focused) return;
|
|
3385
|
+
if (migrateLockFresh()) return;
|
|
3386
|
+
await waitFor(() => document.querySelector(".zcodepro-overlay") ? null : true, 12e4, "dialog-busy");
|
|
3387
|
+
const fresh = await getConfig(true);
|
|
3388
|
+
const still = Object.values(fresh.aliases || {}).some((a) => String(a || "").trim());
|
|
3389
|
+
if (still && !(fresh.migrations && fresh.migrations.aliasRenameDismissed)) openMigrationDialog();
|
|
3390
|
+
} catch {
|
|
3391
|
+
}
|
|
3392
|
+
})();
|
|
3393
|
+
}
|
|
3394
|
+
|
|
3395
|
+
// src/inject/features/styles.js
|
|
3396
|
+
var STYLE_DEFAULTS = {
|
|
3397
|
+
rowGap: 20,
|
|
3398
|
+
// 段落间距:会话内各块之间的垂直间距
|
|
3399
|
+
listSpacing: 12,
|
|
3400
|
+
// 列表上下留白(my-3)
|
|
3401
|
+
listItemSpacing: 6,
|
|
3402
|
+
// 列表项之间的间距(space-y-1.5)
|
|
3403
|
+
quoteCodeSpacing: 16,
|
|
3404
|
+
// 引用块上下留白(my-4;代码块同规则)
|
|
3405
|
+
codeLineHeight: 1.65,
|
|
3406
|
+
// 代码块行高(应用默认 12px 字号 × 20px 行盒)
|
|
3407
|
+
tableSpacing: 20,
|
|
3408
|
+
// 表格上下边距(未设置时跟随段落间距)
|
|
3409
|
+
tableCellPaddingV: 3,
|
|
3410
|
+
// 单元格上下边距(应用默认 3px)
|
|
3411
|
+
tableCellPaddingH: 3,
|
|
3412
|
+
// 单元格左右边距(应用默认 3px)
|
|
3413
|
+
lineHeight: 1.75,
|
|
3414
|
+
// 回答行高(leading-[1.75],挂在答案内容容器上)
|
|
3415
|
+
thinkingLineHeight: 1.5,
|
|
3416
|
+
// 思考行高:“已工作/工作中”过程视图的行距(实测应用默认 1.5;范围见 buildCss 注释)
|
|
3417
|
+
userLineHeight: 1.5,
|
|
3418
|
+
// 提问行高(用户消息文本容器,默认 normal=1.5)
|
|
3419
|
+
contentWidth: null,
|
|
3420
|
+
// 内容宽度:默认 100%(跟随应用,不覆盖)
|
|
3421
|
+
sidebarProjectSpacing: 20,
|
|
3422
|
+
// 侧栏项目间距:项目行视觉间距(行内留白 12 + 边距 8)
|
|
3423
|
+
sidebarTaskSpacing: 10,
|
|
3424
|
+
// 侧栏任务间距:行内留白加行间边距(py-1 + space-y-0.5)
|
|
3425
|
+
uiFont: null,
|
|
3426
|
+
// 界面字体:除终端外所有界面文字(null = 跟随应用默认)
|
|
3427
|
+
userFont: null,
|
|
3428
|
+
// 提问字体:会话中提问内容
|
|
2591
3429
|
assistantFont: null
|
|
2592
3430
|
// 回答字体:会话中回答正文(代码块仍用等宽字体)
|
|
2593
3431
|
};
|
|
@@ -2728,7 +3566,10 @@
|
|
|
2728
3566
|
`${LIST} [data-testid^="workspace-item-"]{height:auto !important;min-height:${28 + 2 * pad}px !important;padding-block:${pad}px !important;padding-top:${pad}px !important;padding-bottom:${pad}px !important;}`,
|
|
2729
3567
|
`${LIST} [data-testid^="workspace-item-"] > div:first-child{align-self:stretch !important;}`,
|
|
2730
3568
|
`${SCROLL} [data-slot="collapsible-trigger"],${SCROLL} .flex.h-7{height:auto !important;}`,
|
|
2731
|
-
`${SCROLL} [data-slot="collapsible-trigger"]{min-height:${28 + 2 * pad}px !important;padding-block:${pad}px !important;padding-top:${pad}px !important;padding-bottom:${pad}px !important;}
|
|
3569
|
+
`${SCROLL} [data-slot="collapsible-trigger"]{min-height:${28 + 2 * pad}px !important;padding-block:${pad}px !important;padding-top:${pad}px !important;padding-bottom:${pad}px !important;}`,
|
|
3570
|
+
// 3.16.1 新结构:项目行(virtual-project-row,固定 h-8)按视觉总量放行内留白;
|
|
3571
|
+
// 分区间距由新侧栏容器自己的布局管理,不动
|
|
3572
|
+
`section[data-project-id] [data-testid="virtual-project-row"]{height:auto !important;min-height:${28 + 2 * pad}px !important;padding-block:${Math.round(pad)}px !important;}`
|
|
2732
3573
|
);
|
|
2733
3574
|
}
|
|
2734
3575
|
const sts = styles.sidebarTaskSpacing;
|
|
@@ -2739,7 +3580,10 @@
|
|
|
2739
3580
|
`ul.space-y-0\\.5:has(> li[data-task-item-key]) > :not(:last-child){margin-block-end:${m}px !important;margin-bottom:${m}px !important;}`,
|
|
2740
3581
|
`ul.space-y-0\\.5:has(> li[data-task-item-key]) > li{padding-block:${pad}px !important;padding-top:${pad}px !important;padding-bottom:${pad}px !important;}`,
|
|
2741
3582
|
`${SCROLL} .flex.flex-col.gap-2{gap:${m}px !important;row-gap:${m}px !important;}`,
|
|
2742
|
-
`${SCROLL} div.cursor-pointer[class*="pl-8"]{padding-block:${pad}px !important;padding-top:${pad}px !important;padding-bottom:${pad}px !important;}
|
|
3583
|
+
`${SCROLL} div.cursor-pointer[class*="pl-8"]{padding-block:${pad}px !important;padding-top:${pad}px !important;padding-bottom:${pad}px !important;}`,
|
|
3584
|
+
// 3.16.1 新结构:任务行(li[data-task-item-key])行内留白 + 相邻行间距
|
|
3585
|
+
`li[data-task-item-key]{padding-block:${Math.max(1, Math.round(pad))}px !important;}`,
|
|
3586
|
+
`li[data-task-item-key] + li[data-task-item-key]{margin-block-start:${m}px !important;}`
|
|
2743
3587
|
);
|
|
2744
3588
|
}
|
|
2745
3589
|
return parts.join("");
|
|
@@ -2780,7 +3624,8 @@
|
|
|
2780
3624
|
thinkingLineHeight: `[data-testid^="chat-assistant-history-content"]`,
|
|
2781
3625
|
userLineHeight: `${CONV} [class*="user-row"] .whitespace-pre-wrap`,
|
|
2782
3626
|
contentWidth: "[data-v4-timeline-content-column]",
|
|
2783
|
-
|
|
3627
|
+
// 双结构:新侧栏项目行 / 旧 testid 行
|
|
3628
|
+
sidebarProjectSpacing: 'section[data-project-id] [data-testid="virtual-project-row"], [data-testid^="workspace-item-"]',
|
|
2784
3629
|
sidebarTaskSpacing: "li[data-task-item-key]"
|
|
2785
3630
|
};
|
|
2786
3631
|
var HL_MARGIN = {
|
|
@@ -2824,6 +3669,7 @@
|
|
|
2824
3669
|
} catch {
|
|
2825
3670
|
}
|
|
2826
3671
|
}
|
|
3672
|
+
var PLUGINS_REPO_URL = "https://github.com/duanluan/zcode-plugins";
|
|
2827
3673
|
function makeUpgradeControls({ endpoint, metaRefresh, idleText }) {
|
|
2828
3674
|
const L = t();
|
|
2829
3675
|
const state = h("span", { class: "min-w-0 flex-1 truncate text-left text-ui-xs/relaxed text-foreground-subtle" });
|
|
@@ -3050,10 +3896,72 @@
|
|
|
3050
3896
|
h("span", { class: "text-foreground-subtle/70" }, `${health.version} \xB7 ${HELPER_URL}`)
|
|
3051
3897
|
);
|
|
3052
3898
|
const rows = h("div", { class: "divide-y divide-border rounded-xl border border-border" });
|
|
3899
|
+
const pluginsStatusLine = h("span", { class: "max-w-40 truncate text-ui-xs/relaxed text-foreground-subtle" }, "\u2026");
|
|
3900
|
+
const pluginsBtn = btnSmall(L.pluginsCheckNow, () => {
|
|
3901
|
+
void runPluginsUpdate();
|
|
3902
|
+
});
|
|
3903
|
+
let pluginsUpdating = false;
|
|
3904
|
+
const runPluginsUpdate = async () => {
|
|
3905
|
+
if (pluginsUpdating) return;
|
|
3906
|
+
pluginsUpdating = true;
|
|
3907
|
+
pluginsBtn.disabled = true;
|
|
3908
|
+
pluginsStatusLine.textContent = L.pluginsUpdating;
|
|
3909
|
+
const res = await rpc("/plugins/update", { method: "POST", body: {} });
|
|
3910
|
+
pluginsUpdating = false;
|
|
3911
|
+
pluginsBtn.disabled = false;
|
|
3912
|
+
if (!res.ok) {
|
|
3913
|
+
pluginsStatusLine.textContent = "";
|
|
3914
|
+
showToast(L.pluginsUpdateFailed + ": " + errText(res), "error");
|
|
3915
|
+
return;
|
|
3916
|
+
}
|
|
3917
|
+
pluginsStatusLine.textContent = res.updated > 0 ? L.pluginsUpdatedDone.replaceAll("{n}", String(res.updated)) : L.pluginsUpToDate;
|
|
3918
|
+
showToast(pluginsStatusLine.textContent, "success");
|
|
3919
|
+
};
|
|
3920
|
+
void (async () => {
|
|
3921
|
+
const cfg = await getConfig(true).catch(() => null);
|
|
3922
|
+
const res = await rpc("/plugins/status");
|
|
3923
|
+
if (!res.ok) {
|
|
3924
|
+
pluginsStatusLine.textContent = "";
|
|
3925
|
+
return;
|
|
3926
|
+
}
|
|
3927
|
+
const n = (res.updates || []).length;
|
|
3928
|
+
if (cfg && (cfg.features || {}).autoUpdatePlugins === true && n > 0) {
|
|
3929
|
+
void runPluginsUpdate();
|
|
3930
|
+
return;
|
|
3931
|
+
}
|
|
3932
|
+
pluginsStatusLine.textContent = n > 0 ? L.pluginsUpdatesFound.replaceAll("{n}", String(n)) : L.pluginsUpToDate;
|
|
3933
|
+
})();
|
|
3934
|
+
const HK_ACTIONS = [
|
|
3935
|
+
["switchLast", "hkAltZ"],
|
|
3936
|
+
["switchPrev", "hkAltX"],
|
|
3937
|
+
["switchNext", "hkAltC"],
|
|
3938
|
+
["switchRecent", "hkAltE"],
|
|
3939
|
+
["switchAttention", "hkAltR"]
|
|
3940
|
+
];
|
|
3941
|
+
const hkNames = () => ({
|
|
3942
|
+
switchLast: L.hkNameLast,
|
|
3943
|
+
switchPrev: L.hkNamePrev,
|
|
3944
|
+
switchNext: L.hkNameNext,
|
|
3945
|
+
switchRecent: L.hkNameRecent,
|
|
3946
|
+
switchAttention: L.hkNameAttention
|
|
3947
|
+
});
|
|
3948
|
+
const hkKeys = () => {
|
|
3949
|
+
const sc = config.shortcuts || {};
|
|
3950
|
+
const keys = {};
|
|
3951
|
+
for (const [a] of HK_ACTIONS) {
|
|
3952
|
+
keys[a] = /^[a-z0-9]$/.test(sc[a]) ? sc[a] : DEFAULT_SHORTCUTS[a];
|
|
3953
|
+
}
|
|
3954
|
+
return keys;
|
|
3955
|
+
};
|
|
3956
|
+
const sessionSwitchDesc = () => {
|
|
3957
|
+
const k = hkKeys();
|
|
3958
|
+
return L.featureSessionSwitchDesc.replaceAll("{last}", "alt+" + k.switchLast).replaceAll("{prev}", k.switchPrev).replaceAll("{next}", k.switchNext).replaceAll("{recent}", "alt+" + k.switchRecent).replaceAll("{attention}", "alt+" + k.switchAttention);
|
|
3959
|
+
};
|
|
3053
3960
|
const refreshRows = () => {
|
|
3054
3961
|
const f = config.features || {};
|
|
3055
3962
|
rows.replaceChildren(
|
|
3056
|
-
|
|
3963
|
+
...isNewProjectSidebar() ? [migrationCard()] : [],
|
|
3964
|
+
settingRow(L.featureProjectMenu, isNewProjectSidebar() ? L.featureProjectMenuDescNew : L.featureProjectMenuDesc, f.projectMenu !== false, async () => {
|
|
3057
3965
|
const next = !(f.projectMenu !== false);
|
|
3058
3966
|
if (await setFeature("projectMenu", next)) f.projectMenu = next;
|
|
3059
3967
|
refreshRows();
|
|
@@ -3064,7 +3972,7 @@
|
|
|
3064
3972
|
if (await setFeature("taskOrder", next)) f.taskOrder = next;
|
|
3065
3973
|
refreshRows();
|
|
3066
3974
|
}),
|
|
3067
|
-
settingRow(L.featureSessionSwitch,
|
|
3975
|
+
settingRow(L.featureSessionSwitch, sessionSwitchDesc(), f.sessionSwitch !== false, async () => {
|
|
3068
3976
|
const next = !(f.sessionSwitch !== false);
|
|
3069
3977
|
if (await setFeature("sessionSwitch", next)) f.sessionSwitch = next;
|
|
3070
3978
|
refreshRows();
|
|
@@ -3094,16 +4002,32 @@
|
|
|
3094
4002
|
if (await setFeature("wsRunningSpin", next)) f.wsRunningSpin = next;
|
|
3095
4003
|
refreshRows();
|
|
3096
4004
|
}),
|
|
3097
|
-
|
|
3098
|
-
const
|
|
3099
|
-
|
|
3100
|
-
|
|
3101
|
-
|
|
3102
|
-
|
|
3103
|
-
|
|
3104
|
-
|
|
3105
|
-
|
|
3106
|
-
|
|
4005
|
+
(() => {
|
|
4006
|
+
const repoLink = h("span", {
|
|
4007
|
+
class: "cursor-pointer underline-offset-4 hover:underline",
|
|
4008
|
+
title: PLUGINS_REPO_URL,
|
|
4009
|
+
onClick: (ev) => {
|
|
4010
|
+
ev.stopPropagation();
|
|
4011
|
+
openExternal(PLUGINS_REPO_URL);
|
|
4012
|
+
}
|
|
4013
|
+
}, L.featureAutoUpdatePluginsRepo);
|
|
4014
|
+
const row = settingRow("", "", f.autoUpdatePlugins === true, async () => {
|
|
4015
|
+
const next = !(f.autoUpdatePlugins === true);
|
|
4016
|
+
if (await setFeature("autoUpdatePlugins", next)) f.autoUpdatePlugins = next;
|
|
4017
|
+
refreshRows();
|
|
4018
|
+
}, h("div", { class: "flex items-center gap-2" }, pluginsBtn));
|
|
4019
|
+
const nameEl = row.querySelector(".text-ui-sm.font-medium");
|
|
4020
|
+
if (nameEl) {
|
|
4021
|
+
nameEl.replaceChildren(
|
|
4022
|
+
document.createTextNode(L.featureAutoUpdatePlugins + " "),
|
|
4023
|
+
repoLink,
|
|
4024
|
+
document.createTextNode(" \u63D2\u4EF6")
|
|
4025
|
+
);
|
|
4026
|
+
}
|
|
4027
|
+
const descEl = row.querySelector("[data-zcodepro-row-desc]");
|
|
4028
|
+
if (descEl) descEl.replaceChildren(pluginsStatusLine);
|
|
4029
|
+
return row;
|
|
4030
|
+
})()
|
|
3107
4031
|
);
|
|
3108
4032
|
};
|
|
3109
4033
|
refreshRows();
|
|
@@ -3154,89 +4078,157 @@
|
|
|
3154
4078
|
)
|
|
3155
4079
|
);
|
|
3156
4080
|
let activeTab = "features";
|
|
3157
|
-
const pluginsStatusLine = h("span", { class: "text-ui-xs/relaxed text-foreground-subtle" }, "\u2026");
|
|
3158
|
-
const pluginsBtn = btnSmall(L.pluginsCheckNow, () => {
|
|
3159
|
-
void runPluginsUpdate();
|
|
3160
|
-
});
|
|
3161
|
-
const runPluginsUpdate = async () => {
|
|
3162
|
-
pluginsBtn.disabled = true;
|
|
3163
|
-
pluginsStatusLine.textContent = L.pluginsUpdating;
|
|
3164
|
-
const res = await rpc("/plugins/update", { method: "POST", body: {} });
|
|
3165
|
-
pluginsBtn.disabled = false;
|
|
3166
|
-
if (!res.ok) {
|
|
3167
|
-
pluginsStatusLine.textContent = "";
|
|
3168
|
-
showToast(L.pluginsUpdateFailed + ": " + errText(res), "error");
|
|
3169
|
-
return;
|
|
3170
|
-
}
|
|
3171
|
-
pluginsStatusLine.textContent = res.updated > 0 ? L.pluginsUpdatedDone.replaceAll("{n}", String(res.updated)) : L.pluginsUpToDate;
|
|
3172
|
-
showToast(pluginsStatusLine.textContent, "success");
|
|
3173
|
-
};
|
|
3174
|
-
void (async () => {
|
|
3175
|
-
const res = await rpc("/plugins/status");
|
|
3176
|
-
if (!res.ok) {
|
|
3177
|
-
pluginsStatusLine.textContent = "";
|
|
3178
|
-
return;
|
|
3179
|
-
}
|
|
3180
|
-
pluginsStatusLine.textContent = (res.updates || []).length > 0 ? L.pluginsUpdatesFound.replaceAll("{n}", String(res.updates.length)) : L.pluginsUpToDate;
|
|
3181
|
-
})();
|
|
3182
|
-
const PLUGINS_REPO_URL = "https://github.com/duanluan/zcode-plugins";
|
|
3183
|
-
const repoName = "zcode-plugins";
|
|
3184
|
-
const titleParts = L.pluginsUpdateTitle.split(repoName);
|
|
3185
|
-
const pluginsTitle = h("div", { class: "truncate text-ui-sm font-medium text-foreground" });
|
|
3186
|
-
if (titleParts.length === 2 && typeof window.zcode?.openExternal === "function") {
|
|
3187
|
-
pluginsTitle.append(
|
|
3188
|
-
titleParts[0],
|
|
3189
|
-
h("span", {
|
|
3190
|
-
class: "cursor-pointer underline-offset-4 hover:underline",
|
|
3191
|
-
title: PLUGINS_REPO_URL,
|
|
3192
|
-
onClick: () => openExternal(PLUGINS_REPO_URL)
|
|
3193
|
-
}, repoName),
|
|
3194
|
-
titleParts[1]
|
|
3195
|
-
);
|
|
3196
|
-
} else {
|
|
3197
|
-
pluginsTitle.append(L.pluginsUpdateTitle);
|
|
3198
|
-
}
|
|
3199
|
-
const pluginsCard = h(
|
|
3200
|
-
"div",
|
|
3201
|
-
{ class: "mt-3 flex items-center justify-between gap-2 rounded-xl border border-border p-2" },
|
|
3202
|
-
h(
|
|
3203
|
-
"div",
|
|
3204
|
-
{ class: "min-w-0" },
|
|
3205
|
-
pluginsTitle,
|
|
3206
|
-
h("div", { class: "mt-0.5 truncate text-ui-xs/relaxed text-foreground-subtle" }, pluginsStatusLine)
|
|
3207
|
-
),
|
|
3208
|
-
pluginsBtn
|
|
3209
|
-
);
|
|
3210
4081
|
const paneFeatures = h(
|
|
3211
4082
|
"div",
|
|
3212
4083
|
{ role: "tabpanel", class: "mt-4" },
|
|
3213
4084
|
h("div", {}, rows),
|
|
3214
|
-
pluginsCard,
|
|
3215
4085
|
communityCards
|
|
3216
4086
|
);
|
|
3217
|
-
|
|
3218
|
-
|
|
3219
|
-
const
|
|
3220
|
-
const
|
|
3221
|
-
|
|
3222
|
-
|
|
3223
|
-
|
|
3224
|
-
|
|
3225
|
-
|
|
3226
|
-
|
|
3227
|
-
|
|
3228
|
-
|
|
3229
|
-
|
|
3230
|
-
|
|
3231
|
-
|
|
3232
|
-
|
|
3233
|
-
|
|
3234
|
-
|
|
3235
|
-
|
|
3236
|
-
|
|
3237
|
-
|
|
3238
|
-
|
|
3239
|
-
|
|
4087
|
+
let hkRecording = null;
|
|
4088
|
+
let hkKeyHandler = null;
|
|
4089
|
+
const hkCard = h("div", { class: "divide-y divide-border rounded-xl border border-border" });
|
|
4090
|
+
const hkCell = (keyLabel, desc, extra) => h(
|
|
4091
|
+
"div",
|
|
4092
|
+
{ class: "flex items-start gap-3 px-3 py-2.5" },
|
|
4093
|
+
h("kbd", {
|
|
4094
|
+
class: "shrink-0 min-w-20 rounded-md border border-border px-2 py-0.5 text-center text-ui-xs text-foreground-subtle",
|
|
4095
|
+
style: "font-family: ui-monospace, SFMono-Regular, Menlo, monospace; line-height: 1.5;"
|
|
4096
|
+
}, keyLabel),
|
|
4097
|
+
h("div", { class: "min-w-0 flex-1 text-ui-sm text-foreground-subtle" }, desc),
|
|
4098
|
+
extra ? h("div", { class: "ml-auto shrink-0 pl-3" }, extra) : null
|
|
4099
|
+
);
|
|
4100
|
+
const renderShortcuts = () => {
|
|
4101
|
+
const keys = hkKeys();
|
|
4102
|
+
const names = hkNames();
|
|
4103
|
+
hkCard.replaceChildren(
|
|
4104
|
+
...HK_ACTIONS.map(([a, descKey]) => {
|
|
4105
|
+
const recording = hkRecording === a;
|
|
4106
|
+
return hkCell(
|
|
4107
|
+
recording ? L.hkRecording : "alt + " + keys[a],
|
|
4108
|
+
L[descKey],
|
|
4109
|
+
btnSmall(recording ? L.hkRecording : L.hkModify, () => {
|
|
4110
|
+
recording ? stopHkRecording() : startHkRecording(a);
|
|
4111
|
+
})
|
|
4112
|
+
);
|
|
4113
|
+
}),
|
|
4114
|
+
hkCell("\u2191 / \u2193", L.hkArrow.replaceAll("{prev}", keys.switchPrev).replaceAll("{next}", keys.switchNext)),
|
|
4115
|
+
hkCell("Enter", L.hkEnter),
|
|
4116
|
+
hkCell("Esc", L.hkEsc),
|
|
4117
|
+
hkCell(L.hkReleaseKey, L.hkRelease)
|
|
4118
|
+
);
|
|
4119
|
+
};
|
|
4120
|
+
const stopHkRecording = () => {
|
|
4121
|
+
hkRecording = null;
|
|
4122
|
+
if (hkKeyHandler) {
|
|
4123
|
+
document.removeEventListener("keydown", hkKeyHandler, true);
|
|
4124
|
+
hkKeyHandler = null;
|
|
4125
|
+
}
|
|
4126
|
+
renderShortcuts();
|
|
4127
|
+
};
|
|
4128
|
+
const startHkRecording = (action) => {
|
|
4129
|
+
hkRecording = action;
|
|
4130
|
+
if (!hkKeyHandler) {
|
|
4131
|
+
const myOverlay = document.querySelector(".zcodepro-overlay");
|
|
4132
|
+
hkKeyHandler = (e) => {
|
|
4133
|
+
if (!myOverlay || !myOverlay.isConnected) {
|
|
4134
|
+
stopHkRecording();
|
|
4135
|
+
return;
|
|
4136
|
+
}
|
|
4137
|
+
if (e.isComposing) return;
|
|
4138
|
+
e.preventDefault();
|
|
4139
|
+
e.stopImmediatePropagation();
|
|
4140
|
+
if (e.key === "Escape") {
|
|
4141
|
+
stopHkRecording();
|
|
4142
|
+
return;
|
|
4143
|
+
}
|
|
4144
|
+
const k = e.key.toLowerCase();
|
|
4145
|
+
if (!/^[a-z0-9]$/.test(k)) {
|
|
4146
|
+
showToast(L.hkInvalid, "error");
|
|
4147
|
+
return;
|
|
4148
|
+
}
|
|
4149
|
+
const keys = hkKeys();
|
|
4150
|
+
const names = hkNames();
|
|
4151
|
+
const conflict = HK_ACTIONS.find(([a2]) => a2 !== hkRecording && keys[a2] === k);
|
|
4152
|
+
if (conflict) {
|
|
4153
|
+
showToast(L.hkConflict.replaceAll("{k}", k).replaceAll("{name}", names[conflict[0]]), "error");
|
|
4154
|
+
return;
|
|
4155
|
+
}
|
|
4156
|
+
const a = hkRecording;
|
|
4157
|
+
stopHkRecording();
|
|
4158
|
+
void (async () => {
|
|
4159
|
+
const res = await rpc("/config", { method: "POST", body: { shortcuts: { [a]: k } } });
|
|
4160
|
+
clearConfigCache();
|
|
4161
|
+
window.dispatchEvent(new CustomEvent("zcodepro:config-changed"));
|
|
4162
|
+
if (!res.ok) {
|
|
4163
|
+
showToast(L.failed + ": " + errText(res), "error");
|
|
4164
|
+
renderShortcuts();
|
|
4165
|
+
return;
|
|
4166
|
+
}
|
|
4167
|
+
if (res.config && res.config.shortcuts) config.shortcuts = res.config.shortcuts;
|
|
4168
|
+
showToast(L.hkSaved, "success");
|
|
4169
|
+
refreshRows();
|
|
4170
|
+
renderShortcuts();
|
|
4171
|
+
})();
|
|
4172
|
+
};
|
|
4173
|
+
document.addEventListener("keydown", hkKeyHandler, true);
|
|
4174
|
+
}
|
|
4175
|
+
renderShortcuts();
|
|
4176
|
+
};
|
|
4177
|
+
renderShortcuts();
|
|
4178
|
+
const resetShortcuts = async () => {
|
|
4179
|
+
stopHkRecording();
|
|
4180
|
+
const all = {};
|
|
4181
|
+
for (const [a] of HK_ACTIONS) all[a] = DEFAULT_SHORTCUTS[a];
|
|
4182
|
+
const res = await rpc("/config", { method: "POST", body: { shortcuts: all } });
|
|
4183
|
+
clearConfigCache();
|
|
4184
|
+
window.dispatchEvent(new CustomEvent("zcodepro:config-changed"));
|
|
4185
|
+
if (!res.ok) {
|
|
4186
|
+
showToast(L.failed + ": " + errText(res), "error");
|
|
4187
|
+
return;
|
|
4188
|
+
}
|
|
4189
|
+
if (res.config && res.config.shortcuts) config.shortcuts = res.config.shortcuts;
|
|
4190
|
+
showToast(L.hkResetDone, "success");
|
|
4191
|
+
refreshRows();
|
|
4192
|
+
renderShortcuts();
|
|
4193
|
+
};
|
|
4194
|
+
const paneShortcuts = h(
|
|
4195
|
+
"div",
|
|
4196
|
+
{ role: "tabpanel", class: "mt-4", style: "display:none" },
|
|
4197
|
+
h("div", { class: "mb-2 text-ui-sm font-medium" }, L.hkTitle),
|
|
4198
|
+
h(
|
|
4199
|
+
"div",
|
|
4200
|
+
{ class: "mb-2 flex items-center gap-2" },
|
|
4201
|
+
h("div", { class: "min-w-0 flex-1 text-ui-xs/relaxed text-foreground-subtle" }, L.hkEditHint),
|
|
4202
|
+
h("div", { class: "shrink-0" }, btnSmall(L.hkReset, () => {
|
|
4203
|
+
void resetShortcuts();
|
|
4204
|
+
}))
|
|
4205
|
+
),
|
|
4206
|
+
hkCard
|
|
4207
|
+
);
|
|
4208
|
+
const paneStyles = h("div", { role: "tabpanel", class: "mt-4", style: "display:none" });
|
|
4209
|
+
const panePerf = h("div", { role: "tabpanel", class: "mt-4", style: "display:none" });
|
|
4210
|
+
const paneAgents = h("div", { role: "tabpanel", class: "mt-2", style: "display:none" });
|
|
4211
|
+
const paneProxy = h("div", { role: "tabpanel", class: "mt-4", style: "display:none" });
|
|
4212
|
+
const paneSync = h("div", { role: "tabpanel", class: "mt-4", style: "display:none" });
|
|
4213
|
+
const paneVision = h("div", { role: "tabpanel", class: "mt-4", style: "display:none" });
|
|
4214
|
+
const paneRtk = h("div", { role: "tabpanel", class: "mt-4", style: "display:none" });
|
|
4215
|
+
const paneHeadroom = h("div", { role: "tabpanel", class: "mt-4", style: "display:none" });
|
|
4216
|
+
const paneTitleGen = h("div", { role: "tabpanel", class: "mt-4", style: "display:none" });
|
|
4217
|
+
const paneDebug = h("div", { role: "tabpanel", class: "mt-4", style: "display:none" });
|
|
4218
|
+
const panes = { features: paneFeatures, shortcuts: paneShortcuts, styles: paneStyles, perf: panePerf, agents: paneAgents, proxy: paneProxy, sync: paneSync, vision: paneVision, headroom: paneHeadroom, rtk: paneRtk, debug: paneDebug };
|
|
4219
|
+
const tabDefs = [
|
|
4220
|
+
["features", L.tabFeatures],
|
|
4221
|
+
["shortcuts", L.tabShortcuts],
|
|
4222
|
+
["agents", L.tabBehavior],
|
|
4223
|
+
["styles", L.tabStyles],
|
|
4224
|
+
["perf", L.tabPerformance],
|
|
4225
|
+
["proxy", L.tabProxy],
|
|
4226
|
+
["sync", L.tabSync],
|
|
4227
|
+
["vision", L.tabVision],
|
|
4228
|
+
["headroom", L.tabHeadroom],
|
|
4229
|
+
["rtk", L.tabRtk],
|
|
4230
|
+
// “调试”标签页只对开发模式生效的用户显示(配置开关或 ZCODEPRO_DEV=1),
|
|
4231
|
+
// 普通用户不可见
|
|
3240
4232
|
...config.devMode === true || config.devActive === true ? [["debug", L.tabDebug]] : []
|
|
3241
4233
|
];
|
|
3242
4234
|
const tablist = h("div", { role: "tablist", "aria-orientation": "horizontal", class: "zcodepro-tablist mt-1" });
|
|
@@ -3250,6 +4242,7 @@
|
|
|
3250
4242
|
}, label)));
|
|
3251
4243
|
const switchTab = (name) => {
|
|
3252
4244
|
activeTab = name;
|
|
4245
|
+
if (name !== "shortcuts" && hkRecording) stopHkRecording();
|
|
3253
4246
|
for (const [id, pane] of Object.entries(panes)) pane.style.display = id === name ? "" : "none";
|
|
3254
4247
|
renderTabs();
|
|
3255
4248
|
};
|
|
@@ -3349,6 +4342,7 @@
|
|
|
3349
4342
|
)
|
|
3350
4343
|
};
|
|
3351
4344
|
const cells = [
|
|
4345
|
+
// 侧栏间距双结构:3.15.x 旧容器/行 + 3.16.1 新项目行(virtual-project-row)与任务行
|
|
3352
4346
|
styleCell(L.sidebarProjectSpacingName, L.sidebarProjectSpacingDesc, "sidebarProjectSpacing", { max: 24 }),
|
|
3353
4347
|
styleCell(L.sidebarTaskSpacingName, L.sidebarTaskSpacingDesc, "sidebarTaskSpacing", { max: 24 }),
|
|
3354
4348
|
widthCell,
|
|
@@ -4868,6 +5862,7 @@
|
|
|
4868
5862
|
h("span", { class: "text-ui-sm text-foreground-subtle/70" }, "\u2026")
|
|
4869
5863
|
);
|
|
4870
5864
|
const hrFacts = h("div", { class: "mt-1.5 grid grid-cols-2 gap-x-4 gap-y-1 sm:grid-cols-3" });
|
|
5865
|
+
const hrInstList = h("div", { class: "mt-1.5 space-y-1", style: "display:none" });
|
|
4871
5866
|
const hrHintLine = h("p", { class: "mt-1.5 text-ui-xs/relaxed text-amber-500", style: "display:none" });
|
|
4872
5867
|
const hrRefresh = async () => {
|
|
4873
5868
|
const res = await rpc("/headroom/status");
|
|
@@ -4876,6 +5871,8 @@
|
|
|
4876
5871
|
h("span", { class: "text-ui-sm text-destructive" }, L.headroomStatusLoadFailed + ": " + errText(res))
|
|
4877
5872
|
);
|
|
4878
5873
|
hrFacts.replaceChildren();
|
|
5874
|
+
hrInstList.replaceChildren();
|
|
5875
|
+
hrInstList.style.display = "none";
|
|
4879
5876
|
hrHintLine.style.display = "none";
|
|
4880
5877
|
return;
|
|
4881
5878
|
}
|
|
@@ -4895,9 +5892,23 @@
|
|
|
4895
5892
|
fact(L.headroomCurrentBackend, hrDevLabel(s.backend)),
|
|
4896
5893
|
fact(L.headroomDesiredBackend, hrDevLabel(s.desiredBackend)),
|
|
4897
5894
|
fact(L.headroomPowerState, HR_PM[s.powerMode] || s.powerMode),
|
|
4898
|
-
fact(L.headroomWatcher, s.watcherRunning ? L.headroomWatcherOn : L.headroomWatcherOff),
|
|
5895
|
+
fact(L.headroomWatcher, s.watcherRunning == null ? "\u2014" : s.watcherRunning ? L.headroomWatcherOn : L.headroomWatcherOff),
|
|
4899
5896
|
fact(L.headroomSaverDetect, HR_DETECT[s.saverDetect] || s.saverDetect)
|
|
4900
5897
|
);
|
|
5898
|
+
const insts = Array.isArray(s.instances) ? s.instances : [];
|
|
5899
|
+
hrInstList.replaceChildren(...insts.map((it) => h(
|
|
5900
|
+
"div",
|
|
5901
|
+
{ class: "flex min-w-0 items-center gap-2" },
|
|
5902
|
+
h("span", { class: "shrink-0 font-mono text-ui-xs text-foreground-subtle" }, `:${it.port}`),
|
|
5903
|
+
h(
|
|
5904
|
+
"span",
|
|
5905
|
+
{ class: "min-w-0 flex-1 truncate text-ui-xs text-foreground-subtle", title: `${it.upstream} | ${it.providers}` },
|
|
5906
|
+
`${it.format} \u2192 ${it.upstream}`
|
|
5907
|
+
),
|
|
5908
|
+
h("span", { class: "max-w-[40%] shrink-0 truncate text-ui-xs text-foreground-subtle/70", title: it.providers }, it.providers),
|
|
5909
|
+
h("span", { class: "shrink-0 text-ui-xs " + (it.up ? "text-emerald-600" : "text-destructive") }, it.up ? L.hrInstRunning : L.hrInstStopped)
|
|
5910
|
+
)));
|
|
5911
|
+
hrInstList.style.display = insts.length ? "" : "none";
|
|
4901
5912
|
hrHintLine.textContent = s.saverHint || "";
|
|
4902
5913
|
hrHintLine.style.display = s.saverHint ? "" : "none";
|
|
4903
5914
|
};
|
|
@@ -5085,6 +6096,7 @@
|
|
|
5085
6096
|
),
|
|
5086
6097
|
hrStatusLine,
|
|
5087
6098
|
hrFacts,
|
|
6099
|
+
hrInstList,
|
|
5088
6100
|
hrHintLine
|
|
5089
6101
|
),
|
|
5090
6102
|
h(
|
|
@@ -5300,6 +6312,7 @@
|
|
|
5300
6312
|
statusLine,
|
|
5301
6313
|
tablist,
|
|
5302
6314
|
paneFeatures,
|
|
6315
|
+
paneShortcuts,
|
|
5303
6316
|
paneAgents,
|
|
5304
6317
|
paneStyles,
|
|
5305
6318
|
panePerf,
|
|
@@ -5392,1127 +6405,1453 @@
|
|
|
5392
6405
|
}
|
|
5393
6406
|
}
|
|
5394
6407
|
|
|
5395
|
-
// src/inject/features/
|
|
5396
|
-
var
|
|
6408
|
+
// src/inject/features/ws-running.js
|
|
6409
|
+
var installed2 = false;
|
|
6410
|
+
var enabled2 = true;
|
|
5397
6411
|
var SCAN_DEBOUNCE_MS = 150;
|
|
5398
6412
|
var SCAN_FALLBACK_MS = 5e3;
|
|
5399
|
-
var
|
|
5400
|
-
var
|
|
5401
|
-
var
|
|
5402
|
-
var
|
|
5403
|
-
var
|
|
5404
|
-
var
|
|
5405
|
-
var
|
|
5406
|
-
|
|
5407
|
-
|
|
5408
|
-
|
|
6413
|
+
var PEEK_FIRST_MS = 2e4;
|
|
6414
|
+
var PEEK_REPEAT_MS = 6e4;
|
|
6415
|
+
var PEEK_SETTLE_MS = 160;
|
|
6416
|
+
var PEEK_MAX_MS = 1500;
|
|
6417
|
+
var PEEK_UNMOUNT_WAIT_MS = 800;
|
|
6418
|
+
var CONFIG_POLL_MIN_MS = 5e3;
|
|
6419
|
+
var CONFIG_POLL_MAX_MS = 6e4;
|
|
6420
|
+
var TASK_SEL = "[data-task-item-key]";
|
|
6421
|
+
var WS_SEL = () => projectRowSelector();
|
|
6422
|
+
function findWsRow(ws) {
|
|
6423
|
+
return findProjectRow(ws);
|
|
6424
|
+
}
|
|
6425
|
+
var LOADER_FALLBACK_PATHS = [
|
|
6426
|
+
"M12 2v4",
|
|
6427
|
+
"m16.2 7.8 2.9-2.9",
|
|
6428
|
+
"M18 12h4",
|
|
6429
|
+
"m19.8 16.2-2.9 2.9",
|
|
6430
|
+
"M12 18v4",
|
|
6431
|
+
"m7.8 19.8-2.9-2.9",
|
|
6432
|
+
"M6 12H2",
|
|
6433
|
+
"m4.2 7.8 2.9-2.9"
|
|
6434
|
+
];
|
|
6435
|
+
function makeLoaderSvg(baseClass) {
|
|
6436
|
+
const ns = "http://www.w3.org/2000/svg";
|
|
6437
|
+
const proto = document.querySelector("svg.lucide-loader");
|
|
6438
|
+
if (proto) {
|
|
6439
|
+
const clone = proto.cloneNode(true);
|
|
6440
|
+
const origClass = proto.getAttribute("class") || "";
|
|
6441
|
+
const keep = origClass.split(/\s+/).filter((c) => /^(size-|text-)/.test(c)).join(" ");
|
|
6442
|
+
clone.setAttribute("class", ((keep || baseClass) + " animate-spin zcodepro-ws-loader").trim());
|
|
6443
|
+
return clone;
|
|
6444
|
+
}
|
|
6445
|
+
const svg = document.createElementNS(ns, "svg");
|
|
6446
|
+
svg.setAttribute("viewBox", "0 0 24 24");
|
|
6447
|
+
svg.setAttribute("fill", "none");
|
|
6448
|
+
svg.setAttribute("stroke", "currentColor");
|
|
6449
|
+
svg.setAttribute("stroke-width", "2");
|
|
6450
|
+
svg.setAttribute("stroke-linecap", "round");
|
|
6451
|
+
svg.setAttribute("stroke-linejoin", "round");
|
|
6452
|
+
svg.setAttribute("class", (baseClass + " animate-spin zcodepro-ws-loader").trim());
|
|
6453
|
+
for (const d of LOADER_FALLBACK_PATHS) {
|
|
6454
|
+
const path = document.createElementNS(ns, "path");
|
|
6455
|
+
path.setAttribute("d", d);
|
|
6456
|
+
svg.append(path);
|
|
6457
|
+
}
|
|
6458
|
+
return svg;
|
|
6459
|
+
}
|
|
6460
|
+
function setRunningIcon(holder, on) {
|
|
6461
|
+
if (!holder) return;
|
|
6462
|
+
if (on) {
|
|
6463
|
+
if (holder.querySelector(":scope > svg.zcodepro-ws-loader")) return;
|
|
6464
|
+
const orig0 = holder.querySelector(":scope > svg:not(.zcodepro-ws-loader)");
|
|
6465
|
+
const base = (orig0 ? orig0.getAttribute("class") || "" : "size-4").replace(/lucide-[a-z-]*/g, "").trim() || "size-4";
|
|
6466
|
+
holder.append(makeLoaderSvg(base));
|
|
6467
|
+
} else {
|
|
6468
|
+
holder.querySelectorAll(":scope > svg.zcodepro-ws-loader").forEach((el) => el.remove());
|
|
6469
|
+
}
|
|
6470
|
+
}
|
|
6471
|
+
function iconHolderOf(row) {
|
|
6472
|
+
if (row.hasAttribute && row.hasAttribute("data-project-id")) {
|
|
6473
|
+
const toggle2 = row.querySelector('[data-testid="virtual-project-toggle"]');
|
|
6474
|
+
return toggle2 ? toggle2.querySelector(":scope > span") : null;
|
|
6475
|
+
}
|
|
6476
|
+
return row.firstElementChild && row.firstElementChild.querySelector(":scope > span");
|
|
6477
|
+
}
|
|
6478
|
+
function isRunningRow(el) {
|
|
6479
|
+
const scope = el.firstElementChild;
|
|
6480
|
+
if (!scope) return false;
|
|
6481
|
+
const svg = scope.querySelector('svg[class*="lucide-loader"]');
|
|
6482
|
+
return !!svg;
|
|
6483
|
+
}
|
|
6484
|
+
var runningByWs = /* @__PURE__ */ new Map();
|
|
6485
|
+
var peekTimers = /* @__PURE__ */ new Map();
|
|
6486
|
+
var activePeeks = /* @__PURE__ */ new Set();
|
|
6487
|
+
var peekedWs = /* @__PURE__ */ new Set();
|
|
6488
|
+
var wsWithRows = /* @__PURE__ */ new Set();
|
|
6489
|
+
var servicesRef = null;
|
|
6490
|
+
function findServices() {
|
|
6491
|
+
if (servicesRef) return servicesRef;
|
|
6492
|
+
try {
|
|
6493
|
+
const rootEl = document.getElementById("root");
|
|
6494
|
+
const containerKey = rootEl && Object.keys(rootEl).find((k) => k.startsWith("__reactContainer$"));
|
|
6495
|
+
if (!containerKey) return null;
|
|
6496
|
+
const seen = /* @__PURE__ */ new Set();
|
|
6497
|
+
let found = null;
|
|
6498
|
+
const scanObj = (o) => {
|
|
6499
|
+
if (!o || typeof o !== "object" || seen.has(o) || found) return;
|
|
6500
|
+
seen.add(o);
|
|
6501
|
+
const ts = o.zcodeTaskService;
|
|
6502
|
+
if (ts && typeof ts === "object" && typeof ts.releaseWorkspacePreparation === "function") found = o;
|
|
6503
|
+
};
|
|
6504
|
+
let visited = 0;
|
|
6505
|
+
const visit = (f) => {
|
|
6506
|
+
if (!f || found || visited > 6e4) return;
|
|
6507
|
+
visited++;
|
|
6508
|
+
for (const holder of [f.memoizedProps, f.memoizedState]) {
|
|
6509
|
+
if (!holder || typeof holder !== "object") continue;
|
|
6510
|
+
scanObj(holder);
|
|
6511
|
+
for (const v of Object.values(holder)) {
|
|
6512
|
+
if (v && typeof v === "object") scanObj(v);
|
|
6513
|
+
}
|
|
6514
|
+
}
|
|
6515
|
+
visit(f.child);
|
|
6516
|
+
visit(f.sibling);
|
|
6517
|
+
};
|
|
6518
|
+
visit(rootEl[containerKey]);
|
|
6519
|
+
if (found) servicesRef = found;
|
|
6520
|
+
return found;
|
|
6521
|
+
} catch {
|
|
6522
|
+
return null;
|
|
6523
|
+
}
|
|
6524
|
+
}
|
|
6525
|
+
async function authoritativeIdle(ws) {
|
|
6526
|
+
const services = findServices();
|
|
6527
|
+
const ts = services && services.zcodeTaskService;
|
|
6528
|
+
if (!ts || typeof ts.listActiveTaskIds !== "function") return null;
|
|
6529
|
+
try {
|
|
6530
|
+
const base = String(ws).replace(/[\\/]+$/, "");
|
|
6531
|
+
const a = await ts.listActiveTaskIds({ workspacePath: base });
|
|
6532
|
+
const b = await ts.listActiveTaskIds({ workspacePath: base + "/" });
|
|
6533
|
+
const ids = [...Array.isArray(a) ? a : [], ...Array.isArray(b) ? b : []].map(String);
|
|
6534
|
+
if (!Array.isArray(a) || !Array.isArray(b)) return null;
|
|
6535
|
+
if (!ids.length) return true;
|
|
6536
|
+
const st = await rpc("/task-statuses?ids=" + encodeURIComponent(ids.join(","))).catch(() => null);
|
|
6537
|
+
const TERMINAL = /* @__PURE__ */ new Set(["completed", "error", "interrupted"]);
|
|
6538
|
+
const live = (id) => {
|
|
6539
|
+
const rec = st && st.ok && st.available ? st.statuses[id] : void 0;
|
|
6540
|
+
if (rec === void 0) return true;
|
|
6541
|
+
if (!TERMINAL.has(rec.status)) return true;
|
|
6542
|
+
return Date.now() - rec.updatedAt < 3e5;
|
|
6543
|
+
};
|
|
6544
|
+
return !ids.some(live);
|
|
6545
|
+
} catch {
|
|
6546
|
+
return null;
|
|
6547
|
+
}
|
|
5409
6548
|
}
|
|
5410
6549
|
function workspaceOf(key) {
|
|
5411
6550
|
const i = key.indexOf(":sess_");
|
|
5412
6551
|
return i > 0 ? key.slice(0, i) : key;
|
|
5413
6552
|
}
|
|
5414
|
-
function
|
|
5415
|
-
|
|
6553
|
+
function wsHead(row) {
|
|
6554
|
+
return row.matches("[aria-expanded]") ? row : row.querySelector("[aria-expanded]");
|
|
6555
|
+
}
|
|
6556
|
+
function domRowsOf(ws) {
|
|
6557
|
+
return [...document.querySelectorAll(TASK_SEL)].filter((e) => workspaceOf(e.getAttribute("data-task-item-key") || "") === ws);
|
|
6558
|
+
}
|
|
6559
|
+
function currentTaskRow() {
|
|
6560
|
+
for (const el of document.querySelectorAll(TASK_SEL)) {
|
|
5416
6561
|
if ((el.className + "").includes("bg-selected")) return el;
|
|
5417
6562
|
}
|
|
5418
6563
|
return null;
|
|
5419
6564
|
}
|
|
5420
|
-
|
|
5421
|
-
|
|
5422
|
-
|
|
5423
|
-
|
|
5424
|
-
mru.unshift(key);
|
|
5425
|
-
if (mru.length > MRU_LIMIT) mru.length = MRU_LIMIT;
|
|
6565
|
+
var synthClick = (el) => {
|
|
6566
|
+
try {
|
|
6567
|
+
el.dispatchEvent(new MouseEvent("click", { bubbles: true, cancelable: true }));
|
|
6568
|
+
} catch {
|
|
5426
6569
|
}
|
|
6570
|
+
};
|
|
6571
|
+
function toggleNavSafe(head) {
|
|
6572
|
+
const cur = currentTaskRow();
|
|
6573
|
+
const backKey = cur ? cur.getAttribute("data-task-item-key") : "";
|
|
6574
|
+
synthClick(head);
|
|
6575
|
+
if (!backKey) return;
|
|
6576
|
+
const back = cur && cur.isConnected ? cur : document.querySelector(`${TASK_SEL}[data-task-item-key="${CSS.escape(backKey)}"]`);
|
|
6577
|
+
if (back) synthClick(back);
|
|
5427
6578
|
}
|
|
5428
6579
|
function scan() {
|
|
5429
|
-
|
|
5430
|
-
|
|
5431
|
-
|
|
5432
|
-
|
|
5433
|
-
|
|
5434
|
-
|
|
5435
|
-
|
|
5436
|
-
|
|
5437
|
-
|
|
5438
|
-
|
|
5439
|
-
|
|
5440
|
-
|
|
5441
|
-
} else if (m.type === "characterData") {
|
|
5442
|
-
if (m.target.parentElement && inTaskRow(m.target.parentElement)) return true;
|
|
5443
|
-
} else if (inTaskRow(m.target)) {
|
|
5444
|
-
return true;
|
|
5445
|
-
} else {
|
|
5446
|
-
for (const n of m.addedNodes) {
|
|
5447
|
-
if (n instanceof Element && (n.matches(rowSel2) || !!n.querySelector(rowSel2))) return true;
|
|
6580
|
+
wsWithRows = /* @__PURE__ */ new Set();
|
|
6581
|
+
for (const el of document.querySelectorAll(TASK_SEL)) {
|
|
6582
|
+
const key = el.getAttribute("data-task-item-key") || "";
|
|
6583
|
+
const ws = workspaceOf(key);
|
|
6584
|
+
if (!ws) continue;
|
|
6585
|
+
wsWithRows.add(ws);
|
|
6586
|
+
const run = isRunningRow(el);
|
|
6587
|
+
let set = runningByWs.get(ws);
|
|
6588
|
+
if (run) {
|
|
6589
|
+
if (!set) {
|
|
6590
|
+
set = /* @__PURE__ */ new Set();
|
|
6591
|
+
runningByWs.set(ws, set);
|
|
5448
6592
|
}
|
|
6593
|
+
set.add(key);
|
|
6594
|
+
} else if (set) {
|
|
6595
|
+
set.delete(key);
|
|
5449
6596
|
}
|
|
5450
6597
|
}
|
|
5451
|
-
|
|
5452
|
-
|
|
5453
|
-
function scheduleScan() {
|
|
5454
|
-
if (scanDebounce) return;
|
|
5455
|
-
scanDebounce = setTimeout(() => {
|
|
5456
|
-
scanDebounce = 0;
|
|
5457
|
-
scan();
|
|
5458
|
-
}, SCAN_DEBOUNCE_MS);
|
|
6598
|
+
syncPeeks();
|
|
6599
|
+
apply();
|
|
5459
6600
|
}
|
|
5460
|
-
|
|
5461
|
-
const
|
|
5462
|
-
|
|
5463
|
-
|
|
5464
|
-
const
|
|
5465
|
-
|
|
5466
|
-
|
|
5467
|
-
|
|
5468
|
-
expander.dispatchEvent(new MouseEvent("click", { bubbles: true, cancelable: true }));
|
|
5469
|
-
for (let i = 0; i < 20 && !(item = find()); i++) await new Promise((r) => setTimeout(r, 100));
|
|
6601
|
+
function handleRemovals(muts) {
|
|
6602
|
+
const removed = [];
|
|
6603
|
+
for (const m of muts) {
|
|
6604
|
+
if (m.type !== "childList") continue;
|
|
6605
|
+
for (const n of m.removedNodes) {
|
|
6606
|
+
if (!(n instanceof Element)) continue;
|
|
6607
|
+
if (n.matches(TASK_SEL)) removed.push(n);
|
|
6608
|
+
else for (const r of n.querySelectorAll(TASK_SEL)) removed.push(r);
|
|
5470
6609
|
}
|
|
5471
6610
|
}
|
|
5472
|
-
if (!
|
|
5473
|
-
|
|
5474
|
-
|
|
5475
|
-
|
|
5476
|
-
|
|
5477
|
-
|
|
5478
|
-
if (!
|
|
5479
|
-
|
|
5480
|
-
|
|
5481
|
-
|
|
5482
|
-
|
|
5483
|
-
|
|
5484
|
-
|
|
5485
|
-
|
|
5486
|
-
|
|
5487
|
-
|
|
5488
|
-
|
|
5489
|
-
const item = document.querySelector(`[data-task-item-key="${CSS.escape(key)}"]`);
|
|
5490
|
-
if (item) titles.set(key, firstLineOf(item));
|
|
5491
|
-
const id = key.slice(key.indexOf(":sess_") + 1);
|
|
5492
|
-
return titles.get(key) || `sess ${id.slice(0, 8)}`;
|
|
5493
|
-
}
|
|
5494
|
-
function projLabelOf(key, aliases2) {
|
|
5495
|
-
const ws = workspaceOf(key);
|
|
5496
|
-
if (!ws) return "";
|
|
5497
|
-
return aliases2[ws] || ws.replace(/[\\/]+$/, "").split(/[\\/]/).pop();
|
|
5498
|
-
}
|
|
5499
|
-
function renderPopup() {
|
|
5500
|
-
if (!popupEl) return;
|
|
5501
|
-
const L = t();
|
|
5502
|
-
const list = popupEl.querySelector("[data-zcodepro-switcher-list]");
|
|
5503
|
-
list.replaceChildren(...mru.map((key, i) => {
|
|
5504
|
-
const proj = projLabelOf(key, aliasesCache);
|
|
5505
|
-
return h(
|
|
5506
|
-
"div",
|
|
5507
|
-
{
|
|
5508
|
-
class: "zcodepro-switcher-row",
|
|
5509
|
-
"data-active": i === highlight ? "" : void 0,
|
|
5510
|
-
onClick: () => {
|
|
5511
|
-
highlight = i;
|
|
5512
|
-
closePopup(true);
|
|
6611
|
+
if (!removed.length) return;
|
|
6612
|
+
const infos = removed.map((el) => {
|
|
6613
|
+
const key = el.getAttribute("data-task-item-key") || "";
|
|
6614
|
+
const ws = workspaceOf(key);
|
|
6615
|
+
return key && ws ? { key, ws, run: isRunningRow(el) } : null;
|
|
6616
|
+
}).filter(Boolean);
|
|
6617
|
+
if (!infos.length) return;
|
|
6618
|
+
setTimeout(() => {
|
|
6619
|
+
for (const info of infos) {
|
|
6620
|
+
const row = findWsRow(info.ws);
|
|
6621
|
+
const head = row && wsHead(row);
|
|
6622
|
+
const collapsed = !row || !head || head.getAttribute("aria-expanded") === "false";
|
|
6623
|
+
let set = runningByWs.get(info.ws);
|
|
6624
|
+
if (collapsed && info.run) {
|
|
6625
|
+
if (!set) {
|
|
6626
|
+
set = /* @__PURE__ */ new Set();
|
|
6627
|
+
runningByWs.set(info.ws, set);
|
|
5513
6628
|
}
|
|
5514
|
-
|
|
5515
|
-
|
|
5516
|
-
|
|
5517
|
-
"div",
|
|
5518
|
-
{ class: "zcodepro-switcher-title" },
|
|
5519
|
-
i === 0 ? h("span", { class: "zcodepro-switcher-tag" }, L.switcherCurrent) : null,
|
|
5520
|
-
h("span", null, findTitle(key))
|
|
5521
|
-
),
|
|
5522
|
-
// 无项目归属(如置顶)时不渲染空行
|
|
5523
|
-
proj ? h("div", { class: "zcodepro-switcher-ws" }, proj) : null
|
|
5524
|
-
);
|
|
5525
|
-
}));
|
|
5526
|
-
}
|
|
5527
|
-
async function openPopup() {
|
|
5528
|
-
if (popupEl) return;
|
|
5529
|
-
const cfg = await getConfig().catch(() => null);
|
|
5530
|
-
aliasesCache = cfg && cfg.aliases && typeof cfg.aliases === "object" ? cfg.aliases : {};
|
|
5531
|
-
ensureStyle();
|
|
5532
|
-
const L = t();
|
|
5533
|
-
highlight = 0;
|
|
5534
|
-
popupEl = h(
|
|
5535
|
-
"div",
|
|
5536
|
-
{
|
|
5537
|
-
class: "zcodepro-switcher-overlay",
|
|
5538
|
-
// 点弹窗外 = 取消(不切)
|
|
5539
|
-
onMousedown: (e) => {
|
|
5540
|
-
if (e.target === popupEl) closePopup(false);
|
|
6629
|
+
set.add(info.key);
|
|
6630
|
+
} else if (set) {
|
|
6631
|
+
set.delete(info.key);
|
|
5541
6632
|
}
|
|
5542
|
-
},
|
|
5543
|
-
h(
|
|
5544
|
-
"div",
|
|
5545
|
-
{ class: "zcodepro-switcher" },
|
|
5546
|
-
h("div", { class: "zcodepro-switcher-hint" }, L.switcherHint),
|
|
5547
|
-
h("div", { "data-zcodepro-switcher-list": "1", class: "zcodepro-switcher-list" })
|
|
5548
|
-
)
|
|
5549
|
-
);
|
|
5550
|
-
document.body.append(popupEl);
|
|
5551
|
-
renderPopup();
|
|
5552
|
-
}
|
|
5553
|
-
function moveHighlight(delta) {
|
|
5554
|
-
if (!popupEl || mru.length < 2) return;
|
|
5555
|
-
highlight = (highlight + delta + mru.length) % mru.length;
|
|
5556
|
-
renderPopup();
|
|
5557
|
-
const row = popupEl.querySelector("[data-active]");
|
|
5558
|
-
if (row) row.scrollIntoView({ block: "nearest" });
|
|
5559
|
-
}
|
|
5560
|
-
function startSessionSwitch() {
|
|
5561
|
-
scan();
|
|
5562
|
-
new MutationObserver((muts) => {
|
|
5563
|
-
if (taskRowMutations(muts)) scheduleScan();
|
|
5564
|
-
}).observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ["class"] });
|
|
5565
|
-
setInterval(() => {
|
|
5566
|
-
if (!document.hidden) scan();
|
|
5567
|
-
}, SCAN_FALLBACK_MS);
|
|
5568
|
-
document.addEventListener("visibilitychange", () => {
|
|
5569
|
-
if (!document.hidden) scan();
|
|
5570
|
-
});
|
|
5571
|
-
document.addEventListener("click", (e) => {
|
|
5572
|
-
const item = e.target instanceof Element && e.target.closest("[data-task-item-key]");
|
|
5573
|
-
if (item) record(item.getAttribute("data-task-item-key"));
|
|
5574
|
-
}, true);
|
|
5575
|
-
document.addEventListener("keydown", (e) => {
|
|
5576
|
-
if (e.key === "Escape" && popupEl) {
|
|
5577
|
-
e.preventDefault();
|
|
5578
|
-
e.stopImmediatePropagation();
|
|
5579
|
-
closePopup(false);
|
|
5580
|
-
return;
|
|
5581
6633
|
}
|
|
5582
|
-
|
|
5583
|
-
|
|
5584
|
-
|
|
5585
|
-
if (k !== "z" && k !== "x" && k !== "c") return;
|
|
5586
|
-
e.preventDefault();
|
|
5587
|
-
e.stopImmediatePropagation();
|
|
5588
|
-
void (async () => {
|
|
5589
|
-
const cfg = await getConfig();
|
|
5590
|
-
if (cfg.features && cfg.features.sessionSwitch === false) return;
|
|
5591
|
-
if (k === "z") {
|
|
5592
|
-
if (e.repeat) return;
|
|
5593
|
-
closePopup(false);
|
|
5594
|
-
const live = findCurrent();
|
|
5595
|
-
if (live) record(live.getAttribute("data-task-item-key"));
|
|
5596
|
-
const target = live ? mru[0] === current ? mru[1] : mru.find((mk) => mk !== current) : mru[0];
|
|
5597
|
-
if (!target) {
|
|
5598
|
-
showToast(t().switcherEmpty);
|
|
5599
|
-
return;
|
|
5600
|
-
}
|
|
5601
|
-
void switchTo(target).then((ok) => {
|
|
5602
|
-
if (!ok) showToast(t().switcherFailed, "error");
|
|
5603
|
-
});
|
|
5604
|
-
return;
|
|
5605
|
-
}
|
|
5606
|
-
if (mru.length < 2) {
|
|
5607
|
-
showToast(t().switcherEmpty);
|
|
5608
|
-
return;
|
|
5609
|
-
}
|
|
5610
|
-
if (!popupEl) await openPopup();
|
|
5611
|
-
moveHighlight(k === "x" ? 1 : -1);
|
|
5612
|
-
})();
|
|
5613
|
-
}, true);
|
|
5614
|
-
document.addEventListener("keyup", (e) => {
|
|
5615
|
-
if (e.key === "Alt" && popupEl) closePopup(true);
|
|
5616
|
-
}, true);
|
|
5617
|
-
window.addEventListener("blur", () => closePopup(false));
|
|
5618
|
-
}
|
|
5619
|
-
|
|
5620
|
-
// src/inject/features/title-lock.js
|
|
5621
|
-
var TASK_SEL = "[data-task-item-key]";
|
|
5622
|
-
var SCAN_DEBOUNCE_MS2 = 150;
|
|
5623
|
-
var SCAN_FALLBACK_MS2 = 5e3;
|
|
5624
|
-
var BOOT_RETRY_MS = 5e3;
|
|
5625
|
-
var RECHECK_DELAY_MS = 1e3;
|
|
5626
|
-
var REVERIFY_MS = 3e3;
|
|
5627
|
-
var MAP_REFRESH_MS = 6e4;
|
|
5628
|
-
var installed2 = false;
|
|
5629
|
-
var enabled2 = true;
|
|
5630
|
-
var pinned = null;
|
|
5631
|
-
var resolved = false;
|
|
5632
|
-
var fetching = null;
|
|
5633
|
-
var pendingKeys = /* @__PURE__ */ new Set();
|
|
5634
|
-
function sessIdOf(key) {
|
|
5635
|
-
const i = key.indexOf(":sess_");
|
|
5636
|
-
return i > 0 ? key.slice(i + 1) : key;
|
|
6634
|
+
syncPeeks();
|
|
6635
|
+
apply();
|
|
6636
|
+
}, 0);
|
|
5637
6637
|
}
|
|
5638
|
-
function
|
|
5639
|
-
const
|
|
5640
|
-
|
|
5641
|
-
|
|
5642
|
-
|
|
6638
|
+
function apply() {
|
|
6639
|
+
const seen = /* @__PURE__ */ new Set();
|
|
6640
|
+
for (const row of document.querySelectorAll(WS_SEL())) {
|
|
6641
|
+
const path = rowPath(row);
|
|
6642
|
+
if (!path) continue;
|
|
6643
|
+
seen.add(path);
|
|
6644
|
+
const head = wsHead(row);
|
|
6645
|
+
const collapsed = !head || head.getAttribute("aria-expanded") === "false";
|
|
6646
|
+
const domRunning = !!(runningByWs.get(path) && runningByWs.get(path).size);
|
|
6647
|
+
const normP = (v) => String(v || "").replace(/[\\/]+$/, "");
|
|
6648
|
+
const running = enabled2 && collapsed && (activeProjectPaths.size ? [...activeProjectPaths].some((p2) => normP(p2) === normP(path)) : domRunning);
|
|
6649
|
+
const icon = iconHolderOf(row);
|
|
6650
|
+
icon?.classList.toggle("zcodepro-ws-running", running);
|
|
6651
|
+
setRunningIcon(icon, running);
|
|
6652
|
+
}
|
|
6653
|
+
applySectionSpin();
|
|
6654
|
+
for (const ws of [...runningByWs.keys()]) if (!seen.has(ws)) runningByWs.delete(ws);
|
|
5643
6655
|
}
|
|
5644
|
-
|
|
5645
|
-
|
|
6656
|
+
var headInfoCache = /* @__PURE__ */ new WeakMap();
|
|
6657
|
+
var PROJECT_HEAD_TEXTS = /* @__PURE__ */ new Set(["\u9879\u76EE", "projects"]);
|
|
6658
|
+
var TASK_HEAD_TEXTS = /* @__PURE__ */ new Set(["\u4EFB\u52A1", "tasks"]);
|
|
6659
|
+
function kindFromHeadText(head) {
|
|
6660
|
+
const text = (head.textContent || "").trim().toLowerCase();
|
|
6661
|
+
if (PROJECT_HEAD_TEXTS.has(text)) return "project";
|
|
6662
|
+
if (TASK_HEAD_TEXTS.has(text)) return "task";
|
|
6663
|
+
return null;
|
|
5646
6664
|
}
|
|
5647
|
-
|
|
5648
|
-
|
|
5649
|
-
const
|
|
5650
|
-
const
|
|
5651
|
-
if (
|
|
5652
|
-
|
|
5653
|
-
|
|
5654
|
-
|
|
5655
|
-
|
|
5656
|
-
|
|
6665
|
+
function sectionHeads() {
|
|
6666
|
+
const heads = [];
|
|
6667
|
+
for (const sv of document.querySelectorAll("svg[data-purpose-section-chevron]")) {
|
|
6668
|
+
const btn = sv.closest("button");
|
|
6669
|
+
if (btn) heads.push(btn);
|
|
6670
|
+
}
|
|
6671
|
+
for (const h3 of document.querySelectorAll("h3")) heads.push(h3);
|
|
6672
|
+
return heads.map((head) => {
|
|
6673
|
+
const cached = headInfoCache.get(head);
|
|
6674
|
+
if (cached) return { head, cont: cached.cont, kind: cached.kind };
|
|
6675
|
+
const textKind = head.tagName === "BUTTON" ? kindFromHeadText(head) : "task";
|
|
6676
|
+
let cont = head.parentElement;
|
|
6677
|
+
while (cont && !cont.querySelector("li[data-task-item-key]") && cont !== document.body) cont = cont.parentElement;
|
|
6678
|
+
const contOk = cont && cont !== document.body;
|
|
6679
|
+
const kind = textKind || (contOk ? cont.querySelector("section[data-project-id]") ? "project" : "task" : null);
|
|
6680
|
+
headInfoCache.set(head, { cont: contOk ? cont : null, kind });
|
|
6681
|
+
return { head, cont: contOk ? cont : null, kind };
|
|
6682
|
+
}).filter((x) => x.head);
|
|
6683
|
+
}
|
|
6684
|
+
var SEC_SPIN_CLASS = "zcodepro-ws-sec-spin";
|
|
6685
|
+
var anyActiveCache = { at: 0, value: null, busy: false };
|
|
6686
|
+
var sectionActive = { task: false, project: false };
|
|
6687
|
+
var activeProjectPaths = /* @__PURE__ */ new Set();
|
|
6688
|
+
setInterval(() => {
|
|
6689
|
+
if (!anyActiveCache.busy && Date.now() - anyActiveCache.at >= 1e4) globalAnyActive();
|
|
6690
|
+
}, 1e4);
|
|
6691
|
+
function globalAnyActive() {
|
|
6692
|
+
if (anyActiveCache.value !== null && Date.now() - anyActiveCache.at < 1e4) return anyActiveCache.value;
|
|
6693
|
+
if (anyActiveCache.busy) return anyActiveCache.value === true;
|
|
6694
|
+
anyActiveCache.busy = true;
|
|
6695
|
+
sectionActive.task = false;
|
|
6696
|
+
sectionActive.project = false;
|
|
6697
|
+
activeProjectPaths = /* @__PURE__ */ new Set();
|
|
6698
|
+
void (async () => {
|
|
6699
|
+
let hit = null;
|
|
6700
|
+
try {
|
|
6701
|
+
const res = await rpc("/projects-v2").catch(() => null);
|
|
6702
|
+
const services = findServices();
|
|
6703
|
+
const ts = services && services.zcodeTaskService;
|
|
6704
|
+
if (res && res.ok && res.available && ts && typeof ts.listActiveTaskIds === "function") {
|
|
6705
|
+
hit = false;
|
|
6706
|
+
const projPaths = /* @__PURE__ */ new Set();
|
|
6707
|
+
for (const proj of res.projects || []) {
|
|
6708
|
+
for (const r of proj.roots || []) {
|
|
6709
|
+
const b = String(r.path || "").replace(/[\\/]+$/, "");
|
|
6710
|
+
if (b) projPaths.add(b);
|
|
6711
|
+
}
|
|
6712
|
+
}
|
|
6713
|
+
const taskSidePaths = /* @__PURE__ */ new Set();
|
|
6714
|
+
for (const el of document.querySelectorAll("[data-task-item-key]")) {
|
|
6715
|
+
const sec = el.closest("section[data-project-id]");
|
|
6716
|
+
if (sec) continue;
|
|
6717
|
+
const k = el.getAttribute("data-task-item-key") || "";
|
|
6718
|
+
const cut = k.lastIndexOf(":");
|
|
6719
|
+
if (cut > 1) taskSidePaths.add(k.slice(0, cut).replace(/[\\/]+$/, ""));
|
|
6720
|
+
}
|
|
6721
|
+
const scanPaths = /* @__PURE__ */ new Set([...projPaths, ...taskSidePaths]);
|
|
6722
|
+
const byKind = { task: /* @__PURE__ */ new Set(), project: /* @__PURE__ */ new Set() };
|
|
6723
|
+
const byKindByPath = /* @__PURE__ */ new Map();
|
|
6724
|
+
const rootToProject = /* @__PURE__ */ new Map();
|
|
6725
|
+
const projectPaths = /* @__PURE__ */ new Map();
|
|
6726
|
+
for (const proj of res.projects || []) {
|
|
6727
|
+
const names = [];
|
|
6728
|
+
for (const r of proj.roots || []) {
|
|
6729
|
+
const b = String(r.path || "").replace(/[\\/]+$/, "");
|
|
6730
|
+
if (b) {
|
|
6731
|
+
rootToProject.set(b, proj.name);
|
|
6732
|
+
names.push(b);
|
|
6733
|
+
}
|
|
6734
|
+
}
|
|
6735
|
+
projectPaths.set(proj.name, names);
|
|
6736
|
+
}
|
|
6737
|
+
for (const base of scanPaths) {
|
|
6738
|
+
const a = await ts.listActiveTaskIds({ workspacePath: base });
|
|
6739
|
+
const b = await ts.listActiveTaskIds({ workspacePath: base + "/" });
|
|
6740
|
+
const ids = [...Array.isArray(a) ? a : [], ...Array.isArray(b) ? b : []].map(String);
|
|
6741
|
+
if (!ids.length) continue;
|
|
6742
|
+
byKindByPath.set(base, ids);
|
|
6743
|
+
const kind = projPaths.has(base) ? "project" : "task";
|
|
6744
|
+
for (const id of ids) byKind[kind].add(id);
|
|
6745
|
+
}
|
|
6746
|
+
const allIds = [...byKind.task, ...byKind.project];
|
|
6747
|
+
const st = allIds.length ? await rpc("/task-statuses?ids=" + encodeURIComponent(allIds.join(","))).catch(() => null) : null;
|
|
6748
|
+
const TERMINAL = /* @__PURE__ */ new Set(["completed", "error", "interrupted"]);
|
|
6749
|
+
const live = (id) => {
|
|
6750
|
+
const rec = st && st.ok && st.available ? st.statuses[id] : void 0;
|
|
6751
|
+
if (rec === void 0) return true;
|
|
6752
|
+
if (!TERMINAL.has(rec.status)) return true;
|
|
6753
|
+
return Date.now() - rec.updatedAt < 3e5;
|
|
6754
|
+
};
|
|
6755
|
+
activeProjectPaths = /* @__PURE__ */ new Set();
|
|
6756
|
+
for (const [base, ids] of byKindByPath) {
|
|
6757
|
+
if (!projPaths.has(base)) continue;
|
|
6758
|
+
if (ids.some(live)) {
|
|
6759
|
+
const projName = rootToProject.get(base);
|
|
6760
|
+
if (projName) for (const p2 of projectPaths.get(projName) || []) activeProjectPaths.add(p2);
|
|
6761
|
+
}
|
|
6762
|
+
}
|
|
6763
|
+
const taskDomRunning = !!document.querySelector('[data-task-item-key]:not(section[data-project-id] *) svg[class*="lucide-loader"]');
|
|
6764
|
+
if (taskDomRunning && [...byKind.task].some(live)) sectionActive.task = true;
|
|
6765
|
+
if ([...byKind.project].some(live)) sectionActive.project = true;
|
|
6766
|
+
hit = sectionActive.task || sectionActive.project;
|
|
6767
|
+
}
|
|
6768
|
+
} catch {
|
|
5657
6769
|
}
|
|
5658
|
-
|
|
5659
|
-
|
|
6770
|
+
if (hit !== null) anyActiveCache = { at: Date.now(), value: hit, busy: false };
|
|
6771
|
+
else anyActiveCache.busy = false;
|
|
6772
|
+
apply();
|
|
5660
6773
|
})();
|
|
5661
|
-
|
|
5662
|
-
try {
|
|
5663
|
-
return await p;
|
|
5664
|
-
} finally {
|
|
5665
|
-
if (fetching === p) fetching = null;
|
|
5666
|
-
}
|
|
5667
|
-
}
|
|
5668
|
-
function isMismatch(item) {
|
|
5669
|
-
if (!enabled2 || !pinned) return null;
|
|
5670
|
-
const key = item.getAttribute("data-task-item-key") || "";
|
|
5671
|
-
const want = pinned.get(sessIdOf(key));
|
|
5672
|
-
if (want === void 0) return null;
|
|
5673
|
-
const els = titleElsOf(item);
|
|
5674
|
-
if (!els.length) return null;
|
|
5675
|
-
if ((els[0].textContent || "").trim() === String(want).trim()) return null;
|
|
5676
|
-
if (item.querySelector('input, textarea, [contenteditable="true"]')) return null;
|
|
5677
|
-
return key;
|
|
6774
|
+
return anyActiveCache.value === true;
|
|
5678
6775
|
}
|
|
5679
|
-
function
|
|
5680
|
-
|
|
5681
|
-
|
|
5682
|
-
|
|
5683
|
-
|
|
6776
|
+
function applySectionSpin() {
|
|
6777
|
+
if (!enabled2) {
|
|
6778
|
+
document.querySelectorAll("." + SEC_SPIN_CLASS).forEach((el) => el.remove());
|
|
6779
|
+
return;
|
|
6780
|
+
}
|
|
6781
|
+
for (const { head, cont, kind } of sectionHeads()) {
|
|
6782
|
+
const running = !!(cont && cont.querySelector('li[data-task-item-key] svg[class*="lucide-loader"]'));
|
|
6783
|
+
let expanded = true;
|
|
6784
|
+
if (head.tagName === "BUTTON") expanded = head.getAttribute("aria-expanded") !== "false";
|
|
6785
|
+
else {
|
|
6786
|
+
const list = head.nextElementSibling;
|
|
6787
|
+
expanded = !list || list.offsetHeight > 0;
|
|
6788
|
+
}
|
|
6789
|
+
if (!kind) return;
|
|
6790
|
+
const scoped = kind === "project" ? sectionActive.project : sectionActive.task;
|
|
6791
|
+
const want = !expanded && scoped;
|
|
6792
|
+
const existing = head.querySelector(":scope > ." + SEC_SPIN_CLASS);
|
|
6793
|
+
if (want && !existing) {
|
|
6794
|
+
const span = document.createElement("span");
|
|
6795
|
+
span.className = "flex size-4 shrink-0 items-center justify-center " + SEC_SPIN_CLASS;
|
|
6796
|
+
span.append(makeLoaderSvg("size-4"));
|
|
6797
|
+
head.prepend(span);
|
|
6798
|
+
} else if (!want && existing) {
|
|
6799
|
+
existing.remove();
|
|
6800
|
+
}
|
|
6801
|
+
}
|
|
5684
6802
|
}
|
|
5685
|
-
function
|
|
5686
|
-
|
|
5687
|
-
|
|
5688
|
-
|
|
5689
|
-
|
|
5690
|
-
|
|
5691
|
-
const map = await fetchPinned();
|
|
5692
|
-
if (!map) return;
|
|
5693
|
-
const want = map.get(sessIdOf(key));
|
|
5694
|
-
if (want === void 0) return;
|
|
5695
|
-
let wrote = false;
|
|
5696
|
-
for (const item of findRows(key)) {
|
|
5697
|
-
if (isMismatch(item) !== key) continue;
|
|
5698
|
-
for (const el of titleElsOf(item)) writeTitle(el, want);
|
|
5699
|
-
wrote = true;
|
|
5700
|
-
}
|
|
5701
|
-
if (wrote) setTimeout(() => {
|
|
5702
|
-
void enforceKey(key);
|
|
5703
|
-
}, REVERIFY_MS);
|
|
5704
|
-
})();
|
|
5705
|
-
}, RECHECK_DELAY_MS);
|
|
6803
|
+
function schedulePeek(ws, delay) {
|
|
6804
|
+
clearTimeout(peekTimers.get(ws));
|
|
6805
|
+
peekTimers.set(ws, setTimeout(() => {
|
|
6806
|
+
peekTimers.delete(ws);
|
|
6807
|
+
void peek(ws);
|
|
6808
|
+
}, delay));
|
|
5706
6809
|
}
|
|
5707
|
-
|
|
5708
|
-
const
|
|
5709
|
-
if (
|
|
5710
|
-
|
|
5711
|
-
|
|
5712
|
-
for (const item of findRows(key)) {
|
|
5713
|
-
if (isMismatch(item) !== key) continue;
|
|
5714
|
-
for (const el of titleElsOf(item)) writeTitle(el, want);
|
|
6810
|
+
function clearPeek(ws) {
|
|
6811
|
+
const t2 = peekTimers.get(ws);
|
|
6812
|
+
if (t2) {
|
|
6813
|
+
clearTimeout(t2);
|
|
6814
|
+
peekTimers.delete(ws);
|
|
5715
6815
|
}
|
|
5716
6816
|
}
|
|
5717
|
-
function
|
|
5718
|
-
|
|
5719
|
-
|
|
5720
|
-
|
|
5721
|
-
|
|
6817
|
+
function syncPeeks() {
|
|
6818
|
+
for (const [ws, set] of runningByWs) {
|
|
6819
|
+
if (!enabled2 || !set.size) {
|
|
6820
|
+
clearPeek(ws);
|
|
6821
|
+
continue;
|
|
6822
|
+
}
|
|
6823
|
+
const row = findWsRow(ws);
|
|
6824
|
+
const head = row && wsHead(row);
|
|
6825
|
+
if (!row || !head || head.getAttribute("aria-expanded") !== "false" || wsWithRows.has(ws)) {
|
|
6826
|
+
clearPeek(ws);
|
|
6827
|
+
continue;
|
|
6828
|
+
}
|
|
6829
|
+
if (!peekTimers.has(ws) && !activePeeks.has(ws)) schedulePeek(ws, peekedWs.has(ws) ? PEEK_REPEAT_MS : PEEK_FIRST_MS);
|
|
5722
6830
|
}
|
|
5723
6831
|
}
|
|
5724
|
-
var
|
|
5725
|
-
function
|
|
5726
|
-
|
|
5727
|
-
|
|
5728
|
-
|
|
5729
|
-
|
|
5730
|
-
|
|
5731
|
-
|
|
5732
|
-
|
|
5733
|
-
|
|
5734
|
-
|
|
5735
|
-
|
|
6832
|
+
var peekChain = Promise.resolve();
|
|
6833
|
+
async function peek(ws, opts) {
|
|
6834
|
+
if (!opts?.manual) {
|
|
6835
|
+
const auth = await authoritativeIdle(ws);
|
|
6836
|
+
if (auth !== null) {
|
|
6837
|
+
if (auth) {
|
|
6838
|
+
runningByWs.delete(ws);
|
|
6839
|
+
} else {
|
|
6840
|
+
let set = runningByWs.get(ws);
|
|
6841
|
+
if (!set) {
|
|
6842
|
+
set = /* @__PURE__ */ new Set();
|
|
6843
|
+
runningByWs.set(ws, set);
|
|
6844
|
+
}
|
|
6845
|
+
set.add(ws + ":active");
|
|
6846
|
+
schedulePeek(ws, PEEK_REPEAT_MS);
|
|
5736
6847
|
}
|
|
6848
|
+
apply();
|
|
6849
|
+
return true;
|
|
5737
6850
|
}
|
|
5738
6851
|
}
|
|
5739
|
-
|
|
5740
|
-
|
|
5741
|
-
|
|
5742
|
-
|
|
5743
|
-
|
|
5744
|
-
scanDebounce2 = setTimeout(() => {
|
|
5745
|
-
scanDebounce2 = 0;
|
|
5746
|
-
scan2();
|
|
5747
|
-
}, SCAN_DEBOUNCE_MS2);
|
|
5748
|
-
}
|
|
5749
|
-
var mapRefreshTimer = 0;
|
|
5750
|
-
function refreshMapSoon() {
|
|
5751
|
-
if (mapRefreshTimer) return;
|
|
5752
|
-
const tick2 = () => {
|
|
5753
|
-
if (document.hidden) {
|
|
5754
|
-
mapRefreshTimer = setTimeout(tick2, 1e4);
|
|
5755
|
-
return;
|
|
5756
|
-
}
|
|
5757
|
-
mapRefreshTimer = 0;
|
|
5758
|
-
if (enabled2 && resolved) void fetchPinned().then((m) => {
|
|
5759
|
-
if (m) scan2();
|
|
5760
|
-
});
|
|
5761
|
-
};
|
|
5762
|
-
mapRefreshTimer = setTimeout(tick2, MAP_REFRESH_MS);
|
|
5763
|
-
}
|
|
5764
|
-
var editingKey = null;
|
|
5765
|
-
var bootDelay = 0;
|
|
5766
|
-
function scheduleBootRetry() {
|
|
5767
|
-
bootDelay = bootDelay ? Math.min(bootDelay * 2, MAP_REFRESH_MS) : BOOT_RETRY_MS;
|
|
5768
|
-
setTimeout(() => {
|
|
5769
|
-
if (resolved) return;
|
|
5770
|
-
if (!document.hidden) void bootstrap();
|
|
5771
|
-
scheduleBootRetry();
|
|
5772
|
-
}, bootDelay);
|
|
5773
|
-
}
|
|
5774
|
-
async function bootstrap() {
|
|
5775
|
-
const map = await fetchPinned();
|
|
5776
|
-
if (map) scan2();
|
|
6852
|
+
const run = () => peekInner(ws, opts);
|
|
6853
|
+
const p = peekChain.then(run, run);
|
|
6854
|
+
peekChain = p.catch(() => {
|
|
6855
|
+
});
|
|
6856
|
+
return p;
|
|
5777
6857
|
}
|
|
5778
|
-
function
|
|
5779
|
-
|
|
5780
|
-
|
|
6858
|
+
async function peekInner(ws, opts) {
|
|
6859
|
+
if (!opts?.manual && !enabled2 || document.hidden || activePeeks.has(ws)) return false;
|
|
6860
|
+
const row = findWsRow(ws);
|
|
6861
|
+
const head = row && wsHead(row);
|
|
6862
|
+
if (!row || !head || head.getAttribute("aria-expanded") !== "false") return false;
|
|
6863
|
+
if (!currentTaskRow()) {
|
|
6864
|
+
schedulePeek(ws, PEEK_REPEAT_MS);
|
|
6865
|
+
return false;
|
|
6866
|
+
}
|
|
6867
|
+
activePeeks.add(ws);
|
|
6868
|
+
peekedWs.add(ws);
|
|
6869
|
+
const rect = row.getBoundingClientRect();
|
|
6870
|
+
const frozen = row.cloneNode(true);
|
|
6871
|
+
frozen.classList.add("zcodepro-ws-frozen");
|
|
6872
|
+
frozen.style.left = rect.left + "px";
|
|
6873
|
+
frozen.style.top = rect.top + "px";
|
|
6874
|
+
frozen.style.width = rect.width + "px";
|
|
6875
|
+
frozen.style.height = rect.height + "px";
|
|
6876
|
+
document.body.append(frozen);
|
|
6877
|
+
row.style.visibility = "hidden";
|
|
6878
|
+
const hider = installPeekHider(ws);
|
|
6879
|
+
let readOk = false;
|
|
6880
|
+
try {
|
|
6881
|
+
toggleNavSafe(head);
|
|
6882
|
+
readOk = await settleAndRead(ws);
|
|
6883
|
+
const rowNow = findWsRow(ws) || row;
|
|
6884
|
+
const headNow = wsHead(rowNow);
|
|
6885
|
+
if (headNow && headNow.getAttribute("aria-expanded") === "true" && !userTouched(rowNow)) {
|
|
6886
|
+
toggleNavSafe(headNow);
|
|
6887
|
+
await waitForRowsGone(ws);
|
|
6888
|
+
}
|
|
6889
|
+
} finally {
|
|
6890
|
+
removePeekHider(hider);
|
|
6891
|
+
row.style.visibility = "";
|
|
6892
|
+
frozen.remove();
|
|
6893
|
+
activePeeks.delete(ws);
|
|
5781
6894
|
}
|
|
6895
|
+
apply();
|
|
6896
|
+
const set = runningByWs.get(ws);
|
|
6897
|
+
if (set && set.size && enabled2) schedulePeek(ws, PEEK_REPEAT_MS);
|
|
6898
|
+
return readOk;
|
|
5782
6899
|
}
|
|
5783
|
-
function
|
|
5784
|
-
|
|
5785
|
-
|
|
5786
|
-
|
|
6900
|
+
function wsRunningSnapshot() {
|
|
6901
|
+
const curKey = currentTaskRow()?.getAttribute("data-task-item-key") || "";
|
|
6902
|
+
return {
|
|
6903
|
+
running: [...runningByWs.entries()].filter(([, set]) => set.size > 0).map(([ws]) => ws),
|
|
6904
|
+
current: curKey ? workspaceOf(curKey) || null : null
|
|
6905
|
+
};
|
|
5787
6906
|
}
|
|
5788
|
-
|
|
5789
|
-
|
|
5790
|
-
|
|
5791
|
-
|
|
5792
|
-
if (el instanceof HTMLInputElement || el instanceof HTMLTextAreaElement) {
|
|
5793
|
-
Object.getOwnPropertyDescriptor(el.constructor.prototype, "value").set.call(el, text);
|
|
5794
|
-
} else {
|
|
5795
|
-
el.textContent = text;
|
|
5796
|
-
}
|
|
5797
|
-
el.dispatchEvent(new Event("input", { bubbles: true }));
|
|
6907
|
+
function wsRunningKeys() {
|
|
6908
|
+
const keys = /* @__PURE__ */ new Set();
|
|
6909
|
+
for (const set of runningByWs.values()) for (const k of set) keys.add(k);
|
|
6910
|
+
return keys;
|
|
5798
6911
|
}
|
|
5799
|
-
function
|
|
5800
|
-
if (!
|
|
5801
|
-
|
|
5802
|
-
|
|
6912
|
+
async function verifyWorkspaceNotRunning(ws) {
|
|
6913
|
+
if (!ws || document.hidden) return false;
|
|
6914
|
+
const row = findWsRow(ws);
|
|
6915
|
+
const head = row && wsHead(row);
|
|
6916
|
+
if (!row || !head) return false;
|
|
6917
|
+
if (head.getAttribute("aria-expanded") !== "false") {
|
|
6918
|
+
let run = false;
|
|
6919
|
+
for (const el of domRowsOf(ws)) if (isRunningRow(el)) run = true;
|
|
6920
|
+
return !run;
|
|
5803
6921
|
}
|
|
5804
|
-
|
|
5805
|
-
|
|
5806
|
-
|
|
5807
|
-
|
|
5808
|
-
if (renamePrefilled.has(el) || !el.getClientRects().length) continue;
|
|
5809
|
-
if (el.closest(TASK_SEL) || el.closest(".zcodepro-overlay")) continue;
|
|
5810
|
-
const cur = String(el.value ?? el.textContent ?? "").trim();
|
|
5811
|
-
if (!cur) continue;
|
|
5812
|
-
renamePrefilled.add(el);
|
|
5813
|
-
if (cur !== String(want).trim()) setNativeValue(el, String(want));
|
|
5814
|
-
renameCtx = null;
|
|
5815
|
-
return;
|
|
6922
|
+
let verified = false;
|
|
6923
|
+
try {
|
|
6924
|
+
verified = await peek(ws, { manual: true }) === true;
|
|
6925
|
+
} catch {
|
|
5816
6926
|
}
|
|
6927
|
+
if (!verified) return false;
|
|
6928
|
+
const set = runningByWs.get(ws);
|
|
6929
|
+
return !(set && set.size);
|
|
5817
6930
|
}
|
|
5818
|
-
function
|
|
5819
|
-
|
|
5820
|
-
|
|
5821
|
-
|
|
5822
|
-
|
|
5823
|
-
|
|
5824
|
-
|
|
5825
|
-
|
|
5826
|
-
|
|
5827
|
-
|
|
5828
|
-
|
|
5829
|
-
|
|
5830
|
-
|
|
5831
|
-
|
|
5832
|
-
|
|
5833
|
-
|
|
5834
|
-
|
|
5835
|
-
|
|
5836
|
-
|
|
5837
|
-
|
|
5838
|
-
|
|
5839
|
-
|
|
5840
|
-
|
|
5841
|
-
|
|
5842
|
-
|
|
5843
|
-
|
|
5844
|
-
|
|
5845
|
-
|
|
5846
|
-
|
|
5847
|
-
|
|
5848
|
-
|
|
5849
|
-
|
|
5850
|
-
document.addEventListener("focusin", (e) => {
|
|
5851
|
-
const el = e.target;
|
|
5852
|
-
if (!(el instanceof Element)) return;
|
|
5853
|
-
if (!el.matches('input, textarea, [contenteditable="true"]')) return;
|
|
5854
|
-
const row = el.closest(TASK_SEL);
|
|
5855
|
-
editingKey = row ? row.getAttribute("data-task-item-key") || "" : null;
|
|
5856
|
-
});
|
|
5857
|
-
document.addEventListener("focusout", () => {
|
|
5858
|
-
if (editingKey === null) return;
|
|
5859
|
-
editingKey = null;
|
|
5860
|
-
void fetchPinned().then((m) => {
|
|
5861
|
-
if (m) scan2();
|
|
5862
|
-
});
|
|
6931
|
+
function settleAndRead(ws) {
|
|
6932
|
+
return new Promise((resolve) => {
|
|
6933
|
+
const t0 = Date.now();
|
|
6934
|
+
let lastCount = -1;
|
|
6935
|
+
let stableAt = 0;
|
|
6936
|
+
let zeroRows = false;
|
|
6937
|
+
const timer = setInterval(() => {
|
|
6938
|
+
const rows = domRowsOf(ws);
|
|
6939
|
+
const elapsed = Date.now() - t0;
|
|
6940
|
+
if (rows.length !== lastCount) {
|
|
6941
|
+
lastCount = rows.length;
|
|
6942
|
+
stableAt = Date.now();
|
|
6943
|
+
}
|
|
6944
|
+
const settled = rows.length > 0 && rows.length === lastCount && Date.now() - stableAt >= PEEK_SETTLE_MS;
|
|
6945
|
+
if (!settled && elapsed < PEEK_MAX_MS) return;
|
|
6946
|
+
clearInterval(timer);
|
|
6947
|
+
if (lastCount === 0) {
|
|
6948
|
+
zeroRows = true;
|
|
6949
|
+
} else {
|
|
6950
|
+
let set = runningByWs.get(ws);
|
|
6951
|
+
if (!set) {
|
|
6952
|
+
set = /* @__PURE__ */ new Set();
|
|
6953
|
+
runningByWs.set(ws, set);
|
|
6954
|
+
}
|
|
6955
|
+
for (const el of rows) {
|
|
6956
|
+
const key = el.getAttribute("data-task-item-key") || "";
|
|
6957
|
+
if (isRunningRow(el)) set.add(key);
|
|
6958
|
+
else set.delete(key);
|
|
6959
|
+
}
|
|
6960
|
+
}
|
|
6961
|
+
resolve(!zeroRows);
|
|
6962
|
+
}, 80);
|
|
5863
6963
|
});
|
|
5864
6964
|
}
|
|
5865
|
-
|
|
5866
|
-
|
|
5867
|
-
|
|
5868
|
-
|
|
5869
|
-
|
|
5870
|
-
|
|
5871
|
-
|
|
5872
|
-
|
|
5873
|
-
|
|
5874
|
-
var COLLECT_MAX_MS = 6e5;
|
|
5875
|
-
var installed3 = false;
|
|
5876
|
-
var knownKeys = /* @__PURE__ */ new Set();
|
|
5877
|
-
var attempted = /* @__PURE__ */ new Set();
|
|
5878
|
-
var sleep = (ms) => new Promise((r) => setTimeout(r, ms));
|
|
5879
|
-
function sessIdOf2(key) {
|
|
5880
|
-
const i = key.indexOf(":sess_");
|
|
5881
|
-
return i > 0 ? key.slice(i + 1) : "";
|
|
6965
|
+
var PEEK_EXEMPT_CLASS = "zcodepro-peek-exempt";
|
|
6966
|
+
var cssAttr = (v) => String(v).replace(/\\/g, "\\\\").replace(/"/g, '\\"');
|
|
6967
|
+
function installPeekHider(ws) {
|
|
6968
|
+
const rowSel3 = `${TASK_SEL}[data-task-item-key^="${cssAttr(ws + ":")}"]`;
|
|
6969
|
+
for (const r of document.querySelectorAll(rowSel3)) r.classList.add(PEEK_EXEMPT_CLASS);
|
|
6970
|
+
const style = document.createElement("style");
|
|
6971
|
+
style.textContent = `${rowSel3}:not(.${PEEK_EXEMPT_CLASS}){display:none!important}`;
|
|
6972
|
+
document.head.append(style);
|
|
6973
|
+
return { style, sel: rowSel3 };
|
|
5882
6974
|
}
|
|
5883
|
-
function
|
|
5884
|
-
|
|
5885
|
-
|
|
5886
|
-
}
|
|
5887
|
-
return "";
|
|
6975
|
+
function removePeekHider(hider) {
|
|
6976
|
+
hider.style.remove();
|
|
6977
|
+
for (const r of document.querySelectorAll("." + PEEK_EXEMPT_CLASS)) r.classList.remove(PEEK_EXEMPT_CLASS);
|
|
5888
6978
|
}
|
|
5889
|
-
function
|
|
5890
|
-
|
|
5891
|
-
|
|
5892
|
-
|
|
5893
|
-
|
|
6979
|
+
function waitForRowsGone(ws) {
|
|
6980
|
+
const sel = `${TASK_SEL}[data-task-item-key^="${cssAttr(ws + ":")}"]:not(.${PEEK_EXEMPT_CLASS})`;
|
|
6981
|
+
return new Promise((resolve) => {
|
|
6982
|
+
const t0 = Date.now();
|
|
6983
|
+
const timer = setInterval(() => {
|
|
6984
|
+
if (!document.querySelector(sel) || Date.now() - t0 >= PEEK_UNMOUNT_WAIT_MS) {
|
|
6985
|
+
clearInterval(timer);
|
|
6986
|
+
resolve();
|
|
6987
|
+
}
|
|
6988
|
+
}, 40);
|
|
6989
|
+
});
|
|
5894
6990
|
}
|
|
5895
|
-
var
|
|
5896
|
-
|
|
5897
|
-
|
|
5898
|
-
const
|
|
5899
|
-
|
|
5900
|
-
const text = (last.innerText || "").replace(URL_RE, "").trim();
|
|
5901
|
-
return text.slice(0, 600);
|
|
6991
|
+
var TOUCH_WINDOW_MS = 800;
|
|
6992
|
+
var wsTouchAt = /* @__PURE__ */ new WeakMap();
|
|
6993
|
+
function userTouched(row) {
|
|
6994
|
+
const at = wsTouchAt.get(row);
|
|
6995
|
+
return !!at && Date.now() - at < TOUCH_WINDOW_MS;
|
|
5902
6996
|
}
|
|
5903
|
-
function
|
|
5904
|
-
|
|
5905
|
-
if (!raw) return true;
|
|
5906
|
-
const stripped = raw.replace(URL_RE, "");
|
|
5907
|
-
return stripped.length < raw.length / 3;
|
|
6997
|
+
function inSel(node, sel) {
|
|
6998
|
+
return !!(node instanceof Element && node.closest && node.closest(sel));
|
|
5908
6999
|
}
|
|
5909
|
-
|
|
5910
|
-
const
|
|
5911
|
-
|
|
5912
|
-
|
|
5913
|
-
|
|
5914
|
-
|
|
5915
|
-
|
|
5916
|
-
|
|
5917
|
-
|
|
5918
|
-
|
|
5919
|
-
|
|
5920
|
-
|
|
5921
|
-
|
|
5922
|
-
|
|
5923
|
-
await sleep(400);
|
|
5924
|
-
}
|
|
5925
|
-
if (!texts.length) return;
|
|
5926
|
-
let assistantSeen = false;
|
|
5927
|
-
const convObserver = new MutationObserver((muts) => {
|
|
5928
|
-
if (currentKey() !== key) return;
|
|
5929
|
-
for (const m of muts) {
|
|
5930
|
-
const t2 = m.type === "characterData" ? m.target.parentElement : m.target;
|
|
5931
|
-
if (t2 instanceof Element && t2.closest(USER_ROW)) continue;
|
|
5932
|
-
for (const n of [t2, ...m.addedNodes]) {
|
|
5933
|
-
if (n instanceof Element && n.closest && n.closest(CONV2)) {
|
|
5934
|
-
assistantSeen = true;
|
|
5935
|
-
return;
|
|
5936
|
-
}
|
|
5937
|
-
}
|
|
5938
|
-
}
|
|
5939
|
-
});
|
|
5940
|
-
convObserver.observe(document.body, { childList: true, subtree: true, characterData: true });
|
|
5941
|
-
const startAt = Date.now();
|
|
5942
|
-
let lastCount = texts.length;
|
|
5943
|
-
let lastChange = Date.now();
|
|
7000
|
+
function relevant(muts) {
|
|
7001
|
+
for (const m of muts) {
|
|
7002
|
+
if (inSel(m.target, TASK_SEL) || inSel(m.target, WS_SEL())) return true;
|
|
7003
|
+
for (const n of m.addedNodes) {
|
|
7004
|
+
if (n instanceof Element && (n.matches(TASK_SEL) || n.matches(WS_SEL()) || n.querySelector(TASK_SEL) || n.querySelector(WS_SEL()))) return true;
|
|
7005
|
+
}
|
|
7006
|
+
for (const n of m.removedNodes) {
|
|
7007
|
+
if (n instanceof Element && (n.matches(TASK_SEL) || n.matches(WS_SEL()) || n.querySelector(TASK_SEL))) return true;
|
|
7008
|
+
}
|
|
7009
|
+
}
|
|
7010
|
+
return false;
|
|
7011
|
+
}
|
|
7012
|
+
var pollMs = CONFIG_POLL_MIN_MS;
|
|
7013
|
+
async function refreshConfig() {
|
|
5944
7014
|
try {
|
|
5945
|
-
|
|
5946
|
-
|
|
5947
|
-
|
|
5948
|
-
|
|
5949
|
-
|
|
5950
|
-
|
|
5951
|
-
|
|
5952
|
-
|
|
5953
|
-
|
|
5954
|
-
|
|
7015
|
+
const res = await rpc("/config");
|
|
7016
|
+
if (res && res.ok && res.config && res.config.features) {
|
|
7017
|
+
const next = res.config.features.wsRunningSpin !== false;
|
|
7018
|
+
if (next !== enabled2) {
|
|
7019
|
+
enabled2 = next;
|
|
7020
|
+
if (!next) {
|
|
7021
|
+
for (const ws of [...peekTimers.keys()]) clearPeek(ws);
|
|
7022
|
+
apply();
|
|
7023
|
+
}
|
|
7024
|
+
return true;
|
|
5955
7025
|
}
|
|
5956
|
-
if (assistantSeen) break;
|
|
5957
|
-
if (Date.now() - lastChange >= QUIET_FALLBACK_MS) break;
|
|
5958
7026
|
}
|
|
5959
|
-
}
|
|
5960
|
-
convObserver.disconnect();
|
|
7027
|
+
} catch {
|
|
5961
7028
|
}
|
|
5962
|
-
|
|
5963
|
-
|
|
5964
|
-
|
|
5965
|
-
|
|
5966
|
-
|
|
5967
|
-
|
|
5968
|
-
|
|
5969
|
-
|
|
5970
|
-
|
|
5971
|
-
|
|
7029
|
+
return false;
|
|
7030
|
+
}
|
|
7031
|
+
function pollConfig() {
|
|
7032
|
+
setTimeout(async () => {
|
|
7033
|
+
if (document.hidden) pollMs = CONFIG_POLL_MAX_MS;
|
|
7034
|
+
else pollMs = await refreshConfig() ? CONFIG_POLL_MIN_MS : Math.min(Math.round(pollMs * 1.5), CONFIG_POLL_MAX_MS);
|
|
7035
|
+
pollConfig();
|
|
7036
|
+
}, pollMs);
|
|
7037
|
+
}
|
|
7038
|
+
var scanDebounce = 0;
|
|
7039
|
+
function startWsRunningSpin() {
|
|
7040
|
+
if (installed2 || typeof document === "undefined") return;
|
|
7041
|
+
installed2 = true;
|
|
7042
|
+
void refreshConfig();
|
|
7043
|
+
pollConfig();
|
|
7044
|
+
const observer2 = new MutationObserver((muts) => {
|
|
7045
|
+
if (!relevant(muts)) return;
|
|
7046
|
+
handleRemovals(muts);
|
|
7047
|
+
if (!scanDebounce) {
|
|
7048
|
+
scanDebounce = setTimeout(() => {
|
|
7049
|
+
scanDebounce = 0;
|
|
7050
|
+
scan();
|
|
7051
|
+
}, SCAN_DEBOUNCE_MS);
|
|
7052
|
+
}
|
|
7053
|
+
});
|
|
7054
|
+
observer2.observe(document.body, { childList: true, subtree: true });
|
|
7055
|
+
scan();
|
|
7056
|
+
setInterval(() => {
|
|
7057
|
+
if (!document.hidden && enabled2) scan();
|
|
7058
|
+
}, SCAN_FALLBACK_MS);
|
|
7059
|
+
document.addEventListener("visibilitychange", () => {
|
|
7060
|
+
if (!document.hidden) scan();
|
|
7061
|
+
});
|
|
7062
|
+
document.addEventListener("click", (e) => {
|
|
7063
|
+
if (!e.isTrusted) return;
|
|
7064
|
+
const row = e.target instanceof Element && e.target.closest(WS_SEL());
|
|
7065
|
+
if (row) wsTouchAt.set(row, Date.now());
|
|
7066
|
+
}, true);
|
|
7067
|
+
}
|
|
7068
|
+
|
|
7069
|
+
// src/inject/features/session-switch.js
|
|
7070
|
+
var MRU_LIMIT = 50;
|
|
7071
|
+
var SCAN_DEBOUNCE_MS2 = 150;
|
|
7072
|
+
var SCAN_FALLBACK_MS2 = 5e3;
|
|
7073
|
+
var INITIAL_COUNT = 10;
|
|
7074
|
+
var PAGE_SIZE = 5;
|
|
7075
|
+
var UNSEEN_LIMIT = 50;
|
|
7076
|
+
var mru = [];
|
|
7077
|
+
var current = null;
|
|
7078
|
+
var titles = /* @__PURE__ */ new Map();
|
|
7079
|
+
var popupEl = null;
|
|
7080
|
+
var aliasesCache = {};
|
|
7081
|
+
var highlight = 0;
|
|
7082
|
+
var scanDebounce2 = 0;
|
|
7083
|
+
var popupMode = "mru";
|
|
7084
|
+
var visibleCount = INITIAL_COUNT;
|
|
7085
|
+
var unseen = /* @__PURE__ */ new Set();
|
|
7086
|
+
var lastRunKeys = null;
|
|
7087
|
+
var movedSinceOpen = false;
|
|
7088
|
+
var hotkeys = { ...DEFAULT_SHORTCUTS };
|
|
7089
|
+
function loadHotkeys() {
|
|
7090
|
+
return getConfig(true).then((cfg) => {
|
|
7091
|
+
const sc = cfg && cfg.shortcuts;
|
|
7092
|
+
if (sc && typeof sc === "object") {
|
|
7093
|
+
for (const k of Object.keys(DEFAULT_SHORTCUTS)) {
|
|
7094
|
+
if (typeof sc[k] === "string" && /^[a-z0-9]$/.test(sc[k])) hotkeys[k] = sc[k];
|
|
5972
7095
|
}
|
|
5973
7096
|
}
|
|
7097
|
+
}).catch(() => {
|
|
7098
|
+
});
|
|
7099
|
+
}
|
|
7100
|
+
function firstLineOf(item) {
|
|
7101
|
+
const tEl = item.querySelector('[class*="truncate"]');
|
|
7102
|
+
return (tEl ? tEl.textContent : (item.innerText || "").split("\n")[0])?.trim() || "";
|
|
7103
|
+
}
|
|
7104
|
+
function workspaceOf2(key) {
|
|
7105
|
+
const i = key.indexOf(":sess_");
|
|
7106
|
+
return i > 0 ? key.slice(0, i) : key;
|
|
7107
|
+
}
|
|
7108
|
+
function findCurrent() {
|
|
7109
|
+
for (const el of document.querySelectorAll("[data-task-item-key]")) {
|
|
7110
|
+
if ((el.className + "").includes("bg-selected")) return el;
|
|
5974
7111
|
}
|
|
5975
|
-
|
|
5976
|
-
|
|
5977
|
-
|
|
5978
|
-
|
|
5979
|
-
|
|
5980
|
-
|
|
5981
|
-
|
|
5982
|
-
|
|
5983
|
-
|
|
5984
|
-
void refreshPinnedTitles();
|
|
7112
|
+
return null;
|
|
7113
|
+
}
|
|
7114
|
+
function record(key) {
|
|
7115
|
+
if (key) unseen.delete(key);
|
|
7116
|
+
if (key && key !== current) {
|
|
7117
|
+
current = key;
|
|
7118
|
+
mru = mru.filter((k) => k !== key);
|
|
7119
|
+
mru.unshift(key);
|
|
7120
|
+
if (mru.length > MRU_LIMIT) mru.length = MRU_LIMIT;
|
|
5985
7121
|
}
|
|
5986
7122
|
}
|
|
5987
|
-
function
|
|
7123
|
+
function scan2() {
|
|
7124
|
+
const cur = findCurrent();
|
|
7125
|
+
if (cur) record(cur.getAttribute("data-task-item-key"));
|
|
5988
7126
|
for (const el of document.querySelectorAll("[data-task-item-key]")) {
|
|
5989
|
-
|
|
5990
|
-
if (!key || knownKeys.has(key)) continue;
|
|
5991
|
-
knownKeys.add(key);
|
|
5992
|
-
void onNewTaskRow(key);
|
|
7127
|
+
titles.set(el.getAttribute("data-task-item-key"), firstLineOf(el));
|
|
5993
7128
|
}
|
|
5994
7129
|
}
|
|
5995
|
-
var
|
|
5996
|
-
var
|
|
5997
|
-
function
|
|
7130
|
+
var rowSel2 = "[data-task-item-key]";
|
|
7131
|
+
var inTaskRow = (node) => node instanceof Element && !!node.closest && !!node.closest(rowSel2);
|
|
7132
|
+
function taskRowMutations(muts) {
|
|
5998
7133
|
for (const m of muts) {
|
|
5999
7134
|
if (m.type === "attributes") {
|
|
6000
|
-
if (
|
|
7135
|
+
if (inTaskRow(m.target)) return true;
|
|
6001
7136
|
} else if (m.type === "characterData") {
|
|
6002
|
-
if (m.target.parentElement &&
|
|
6003
|
-
} else if (
|
|
7137
|
+
if (m.target.parentElement && inTaskRow(m.target.parentElement)) return true;
|
|
7138
|
+
} else if (inTaskRow(m.target)) {
|
|
6004
7139
|
return true;
|
|
6005
7140
|
} else {
|
|
6006
7141
|
for (const n of m.addedNodes) {
|
|
6007
|
-
if (n instanceof Element && (n.matches(
|
|
7142
|
+
if (n instanceof Element && (n.matches(rowSel2) || !!n.querySelector(rowSel2))) return true;
|
|
6008
7143
|
}
|
|
6009
7144
|
}
|
|
6010
7145
|
}
|
|
6011
7146
|
return false;
|
|
6012
7147
|
}
|
|
6013
|
-
|
|
6014
|
-
|
|
6015
|
-
|
|
6016
|
-
|
|
6017
|
-
|
|
6018
|
-
|
|
6019
|
-
}, SCAN_DEBOUNCE_MS3);
|
|
7148
|
+
function scheduleScan() {
|
|
7149
|
+
if (scanDebounce2) return;
|
|
7150
|
+
scanDebounce2 = setTimeout(() => {
|
|
7151
|
+
scanDebounce2 = 0;
|
|
7152
|
+
scan2();
|
|
7153
|
+
}, SCAN_DEBOUNCE_MS2);
|
|
6020
7154
|
}
|
|
6021
|
-
function
|
|
6022
|
-
|
|
6023
|
-
|
|
6024
|
-
|
|
7155
|
+
async function switchTo(key) {
|
|
7156
|
+
const find = () => document.querySelector(`[data-task-item-key="${CSS.escape(key)}"]`);
|
|
7157
|
+
let item = find();
|
|
7158
|
+
if (!item) {
|
|
7159
|
+
const ws = workspaceOf2(key);
|
|
7160
|
+
const header = findProjectRow(ws);
|
|
7161
|
+
const expander = header && header.querySelector("[aria-expanded]");
|
|
7162
|
+
if (expander && expander.getAttribute("aria-expanded") === "false") {
|
|
7163
|
+
expander.dispatchEvent(new MouseEvent("click", { bubbles: true, cancelable: true }));
|
|
7164
|
+
for (let i = 0; i < 20 && !(item = find()); i++) await new Promise((r) => setTimeout(r, 100));
|
|
7165
|
+
}
|
|
7166
|
+
}
|
|
7167
|
+
if (!item) return false;
|
|
7168
|
+
item.scrollIntoView({ block: "nearest" });
|
|
7169
|
+
item.dispatchEvent(new MouseEvent("click", { bubbles: true, cancelable: true }));
|
|
7170
|
+
return true;
|
|
7171
|
+
}
|
|
7172
|
+
function attentionList() {
|
|
7173
|
+
const run = wsRunningKeys();
|
|
7174
|
+
const listed = /* @__PURE__ */ new Set();
|
|
7175
|
+
const head = [];
|
|
7176
|
+
for (const k of mru) {
|
|
7177
|
+
if (run.has(k) || unseen.has(k)) {
|
|
7178
|
+
head.push(k);
|
|
7179
|
+
listed.add(k);
|
|
7180
|
+
}
|
|
7181
|
+
}
|
|
7182
|
+
const tail = [];
|
|
7183
|
+
for (const k of run) if (!listed.has(k)) {
|
|
7184
|
+
tail.push(k);
|
|
7185
|
+
listed.add(k);
|
|
7186
|
+
}
|
|
7187
|
+
for (const k of unseen) if (!listed.has(k)) {
|
|
7188
|
+
tail.push(k);
|
|
7189
|
+
listed.add(k);
|
|
7190
|
+
}
|
|
7191
|
+
return [...head, ...tail];
|
|
7192
|
+
}
|
|
7193
|
+
function activeList() {
|
|
7194
|
+
return popupMode === "attention" ? attentionList() : mru;
|
|
7195
|
+
}
|
|
7196
|
+
function closePopup(commit) {
|
|
7197
|
+
if (!popupEl) return;
|
|
7198
|
+
const idx = highlight;
|
|
7199
|
+
const list = activeList();
|
|
7200
|
+
popupEl.remove();
|
|
7201
|
+
popupEl = null;
|
|
7202
|
+
if (commit && list[idx] && list[idx] !== current) {
|
|
7203
|
+
void switchTo(list[idx]).then((ok) => {
|
|
7204
|
+
if (!ok) showToast(t().switcherFailed, "error");
|
|
7205
|
+
});
|
|
7206
|
+
}
|
|
7207
|
+
}
|
|
7208
|
+
function findTitle(key) {
|
|
7209
|
+
const item = document.querySelector(`[data-task-item-key="${CSS.escape(key)}"]`);
|
|
7210
|
+
if (item) titles.set(key, firstLineOf(item));
|
|
7211
|
+
const id = key.slice(key.indexOf(":sess_") + 1);
|
|
7212
|
+
return titles.get(key) || `sess ${id.slice(0, 8)}`;
|
|
7213
|
+
}
|
|
7214
|
+
function projLabelOf(key, aliases2) {
|
|
7215
|
+
const ws = workspaceOf2(key);
|
|
7216
|
+
if (!ws) return "";
|
|
7217
|
+
return aliases2[ws] || ws.replace(/[\\/]+$/, "").split(/[\\/]/).pop();
|
|
7218
|
+
}
|
|
7219
|
+
function renderPopup() {
|
|
7220
|
+
if (!popupEl) return;
|
|
7221
|
+
const L = t();
|
|
7222
|
+
const list = popupEl.querySelector("[data-zcodepro-switcher-list]");
|
|
7223
|
+
const full = activeList();
|
|
7224
|
+
const shown = full.slice(0, visibleCount);
|
|
7225
|
+
const run = popupMode === "attention" ? wsRunningKeys() : null;
|
|
7226
|
+
list.replaceChildren(...shown.map((key) => {
|
|
7227
|
+
const proj = projLabelOf(key, aliasesCache);
|
|
7228
|
+
return h(
|
|
7229
|
+
"div",
|
|
7230
|
+
{
|
|
7231
|
+
class: "zcodepro-switcher-row",
|
|
7232
|
+
"data-active": full[highlight] === key ? "" : void 0,
|
|
7233
|
+
onClick: () => {
|
|
7234
|
+
highlight = full.indexOf(key);
|
|
7235
|
+
closePopup(true);
|
|
7236
|
+
}
|
|
7237
|
+
},
|
|
7238
|
+
// 标题文本包 span:截断省略作用在文本节点上(flex 容器自身 ellipsis 无效)
|
|
7239
|
+
h(
|
|
7240
|
+
"div",
|
|
7241
|
+
{ class: "zcodepro-switcher-title" },
|
|
7242
|
+
key === current ? h("span", { class: "zcodepro-switcher-tag" }, L.switcherCurrent) : null,
|
|
7243
|
+
run && run.has(key) ? h("span", { class: "zcodepro-switcher-tag zcodepro-switcher-tag-run" }, L.switcherRunning) : null,
|
|
7244
|
+
run && !run.has(key) ? h("span", { class: "zcodepro-switcher-tag zcodepro-switcher-tag-new" }, L.switcherUnseen) : null,
|
|
7245
|
+
h("span", null, findTitle(key))
|
|
7246
|
+
),
|
|
7247
|
+
// 无项目归属(如置顶)时不渲染空行
|
|
7248
|
+
proj ? h("div", { class: "zcodepro-switcher-ws" }, proj) : null
|
|
7249
|
+
);
|
|
7250
|
+
}));
|
|
7251
|
+
if (full.length > shown.length) {
|
|
7252
|
+
list.append(h(
|
|
7253
|
+
"div",
|
|
7254
|
+
{ class: "zcodepro-switcher-more" },
|
|
7255
|
+
L.switcherMore.replaceAll("{n}", String(full.length - shown.length))
|
|
7256
|
+
));
|
|
7257
|
+
}
|
|
7258
|
+
}
|
|
7259
|
+
async function openPopup(mode = "mru") {
|
|
7260
|
+
if (popupEl) return;
|
|
7261
|
+
popupMode = mode;
|
|
7262
|
+
visibleCount = INITIAL_COUNT;
|
|
7263
|
+
highlight = 0;
|
|
7264
|
+
movedSinceOpen = false;
|
|
7265
|
+
const cfg = await getConfig().catch(() => null);
|
|
7266
|
+
aliasesCache = cfg && cfg.aliases && typeof cfg.aliases === "object" ? cfg.aliases : {};
|
|
7267
|
+
ensureStyle();
|
|
7268
|
+
const L = t();
|
|
7269
|
+
popupEl = h(
|
|
7270
|
+
"div",
|
|
7271
|
+
{
|
|
7272
|
+
class: "zcodepro-switcher-overlay",
|
|
7273
|
+
// 点弹窗外 = 取消(不切)
|
|
7274
|
+
onMousedown: (e) => {
|
|
7275
|
+
if (e.target === popupEl) closePopup(false);
|
|
7276
|
+
}
|
|
7277
|
+
},
|
|
7278
|
+
h(
|
|
7279
|
+
"div",
|
|
7280
|
+
{ class: "zcodepro-switcher" },
|
|
7281
|
+
// 提示行键位跟随当前配置(改键后新开的弹窗即用新键位)
|
|
7282
|
+
h(
|
|
7283
|
+
"div",
|
|
7284
|
+
{ class: "zcodepro-switcher-hint" },
|
|
7285
|
+
(mode === "attention" ? L.switcherAttentionHint : L.switcherHint).replaceAll("{prev}", hotkeys.switchPrev).replaceAll("{next}", hotkeys.switchNext)
|
|
7286
|
+
),
|
|
7287
|
+
h("div", { "data-zcodepro-switcher-list": "1", class: "zcodepro-switcher-list" })
|
|
7288
|
+
)
|
|
7289
|
+
);
|
|
7290
|
+
document.body.append(popupEl);
|
|
7291
|
+
renderPopup();
|
|
7292
|
+
}
|
|
7293
|
+
function scrollHighlight() {
|
|
7294
|
+
const row = popupEl && popupEl.querySelector("[data-active]");
|
|
7295
|
+
if (row) row.scrollIntoView({ block: "nearest" });
|
|
7296
|
+
}
|
|
7297
|
+
function moveUp() {
|
|
7298
|
+
const len = Math.min(activeList().length, visibleCount);
|
|
7299
|
+
if (len < 2) return;
|
|
7300
|
+
highlight = highlight > 0 ? highlight - 1 : len - 1;
|
|
7301
|
+
movedSinceOpen = true;
|
|
7302
|
+
renderPopup();
|
|
7303
|
+
scrollHighlight();
|
|
7304
|
+
}
|
|
7305
|
+
function moveDown() {
|
|
7306
|
+
const full = activeList();
|
|
7307
|
+
const len = Math.min(full.length, visibleCount);
|
|
7308
|
+
if (len < 2) return;
|
|
7309
|
+
if (highlight < len - 1) {
|
|
7310
|
+
highlight += 1;
|
|
7311
|
+
} else if (visibleCount < full.length) {
|
|
7312
|
+
visibleCount = Math.min(visibleCount + PAGE_SIZE, full.length);
|
|
7313
|
+
highlight = len;
|
|
7314
|
+
} else {
|
|
7315
|
+
highlight = 0;
|
|
7316
|
+
}
|
|
7317
|
+
movedSinceOpen = true;
|
|
7318
|
+
renderPopup();
|
|
7319
|
+
scrollHighlight();
|
|
7320
|
+
}
|
|
7321
|
+
function startSessionSwitch() {
|
|
7322
|
+
scan2();
|
|
7323
|
+
void loadHotkeys();
|
|
7324
|
+
window.addEventListener("zcodepro:config-changed", () => {
|
|
7325
|
+
void loadHotkeys();
|
|
7326
|
+
});
|
|
6025
7327
|
new MutationObserver((muts) => {
|
|
6026
|
-
if (
|
|
6027
|
-
}).observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ["class"]
|
|
7328
|
+
if (taskRowMutations(muts)) scheduleScan();
|
|
7329
|
+
}).observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ["class"] });
|
|
6028
7330
|
setInterval(() => {
|
|
6029
|
-
if (!document.hidden)
|
|
6030
|
-
},
|
|
7331
|
+
if (!document.hidden) scan2();
|
|
7332
|
+
}, SCAN_FALLBACK_MS2);
|
|
6031
7333
|
document.addEventListener("visibilitychange", () => {
|
|
6032
|
-
if (!document.hidden)
|
|
7334
|
+
if (!document.hidden) scan2();
|
|
6033
7335
|
});
|
|
6034
|
-
|
|
6035
|
-
|
|
6036
|
-
|
|
6037
|
-
|
|
6038
|
-
|
|
6039
|
-
|
|
6040
|
-
var CONFIG_POLL_MAX_MS = 6e4;
|
|
6041
|
-
var pollMs = CONFIG_POLL_MIN_MS;
|
|
6042
|
-
async function refreshConfig() {
|
|
6043
|
-
try {
|
|
6044
|
-
const res = await rpc("/config");
|
|
6045
|
-
if (res && res.ok && res.config && res.config.features) {
|
|
6046
|
-
const next = res.config.features.pinnedKeepCollapsed !== false;
|
|
6047
|
-
if (next !== keepCollapsed) {
|
|
6048
|
-
keepCollapsed = next;
|
|
6049
|
-
return true;
|
|
7336
|
+
setInterval(() => {
|
|
7337
|
+
if (document.hidden) return;
|
|
7338
|
+
const now = wsRunningKeys();
|
|
7339
|
+
if (lastRunKeys) {
|
|
7340
|
+
for (const k of lastRunKeys) {
|
|
7341
|
+
if (!now.has(k) && k !== current) unseen.add(k);
|
|
6050
7342
|
}
|
|
6051
7343
|
}
|
|
6052
|
-
|
|
6053
|
-
|
|
6054
|
-
|
|
6055
|
-
}
|
|
6056
|
-
function pollConfig() {
|
|
6057
|
-
setTimeout(async () => {
|
|
6058
|
-
if (document.hidden) pollMs = CONFIG_POLL_MAX_MS;
|
|
6059
|
-
else pollMs = await refreshConfig() ? CONFIG_POLL_MIN_MS : Math.min(Math.round(pollMs * 1.5), CONFIG_POLL_MAX_MS);
|
|
6060
|
-
pollConfig();
|
|
6061
|
-
}, pollMs);
|
|
6062
|
-
}
|
|
6063
|
-
function startPinnedExpandSuppression() {
|
|
6064
|
-
if (installed4 || typeof document === "undefined") return;
|
|
6065
|
-
installed4 = true;
|
|
6066
|
-
void refreshConfig();
|
|
6067
|
-
pollConfig();
|
|
6068
|
-
document.addEventListener("visibilitychange", () => {
|
|
6069
|
-
if (!document.hidden) void refreshConfig();
|
|
6070
|
-
});
|
|
6071
|
-
document.addEventListener("click", (e) => {
|
|
6072
|
-
if (!keepCollapsed) return;
|
|
6073
|
-
const taskRow = e.target.closest && e.target.closest('[data-testid^="task-item-"]');
|
|
6074
|
-
if (!taskRow) return;
|
|
6075
|
-
const key = taskRow.getAttribute("data-task-item-key") || "";
|
|
6076
|
-
const sep = key.lastIndexOf(":");
|
|
6077
|
-
if (sep <= 0) return;
|
|
6078
|
-
const wsKey = key.slice(0, sep);
|
|
6079
|
-
const wsRow = document.querySelector(`[data-testid="workspace-item-${cssEscape(wsKey)}"]`);
|
|
6080
|
-
if (!wsRow || wsRow.getAttribute("aria-expanded") !== "false") return;
|
|
6081
|
-
const head = wsRow.matches("[aria-expanded]") ? wsRow : wsRow.querySelector("[aria-expanded]");
|
|
6082
|
-
if (!head) return;
|
|
6083
|
-
collapseAfterContentLoaded(wsRow);
|
|
6084
|
-
}, true);
|
|
7344
|
+
lastRunKeys = now;
|
|
7345
|
+
if (unseen.size > UNSEEN_LIMIT) unseen = new Set([...unseen].slice(-UNSEEN_LIMIT));
|
|
7346
|
+
}, 1e4);
|
|
6085
7347
|
document.addEventListener("click", (e) => {
|
|
6086
|
-
const
|
|
6087
|
-
if (
|
|
7348
|
+
const item = e.target instanceof Element && e.target.closest("[data-task-item-key]");
|
|
7349
|
+
if (item) record(item.getAttribute("data-task-item-key"));
|
|
6088
7350
|
}, true);
|
|
6089
|
-
|
|
6090
|
-
|
|
6091
|
-
|
|
6092
|
-
|
|
6093
|
-
|
|
6094
|
-
|
|
6095
|
-
}
|
|
6096
|
-
function collapseNavSafe(head) {
|
|
6097
|
-
const cur = currentTaskRow();
|
|
6098
|
-
const backKey = cur ? cur.getAttribute("data-task-item-key") : "";
|
|
6099
|
-
head.dispatchEvent(new MouseEvent("click", { bubbles: true, cancelable: true }));
|
|
6100
|
-
if (!backKey) return;
|
|
6101
|
-
const back = cur && cur.isConnected ? cur : document.querySelector(`[data-task-item-key="${cssEscape(backKey)}"]`);
|
|
6102
|
-
if (back) back.dispatchEvent(new MouseEvent("click", { bubbles: true, cancelable: true }));
|
|
6103
|
-
}
|
|
6104
|
-
function collapseAfterContentLoaded(wsRow) {
|
|
6105
|
-
const deadline = Date.now() + 25e3;
|
|
6106
|
-
let lastLen = (document.querySelector("main") || document.body).innerText.length;
|
|
6107
|
-
let grewAt = 0;
|
|
6108
|
-
let settledAt = 0;
|
|
6109
|
-
const headOf = () => {
|
|
6110
|
-
const h2 = wsRow.matches("[aria-expanded]") ? wsRow : wsRow.querySelector("[aria-expanded]");
|
|
6111
|
-
return h2 || null;
|
|
6112
|
-
};
|
|
6113
|
-
const userTouched2 = () => wsRow.__zcodeproUserTouched && Date.now() - wsRow.__zcodeproUserTouched < 800;
|
|
6114
|
-
const tick2 = () => {
|
|
6115
|
-
if (!keepCollapsed || Date.now() > deadline || !wsRow.isConnected) return done();
|
|
6116
|
-
const len = (document.querySelector("main") || document.body).innerText.length;
|
|
6117
|
-
if (len > lastLen) grewAt = Date.now();
|
|
6118
|
-
if (grewAt && Date.now() - grewAt >= 1e3) settledAt = settledAt || Date.now();
|
|
6119
|
-
lastLen = len;
|
|
6120
|
-
const head = headOf();
|
|
6121
|
-
if (head && head.getAttribute("aria-expanded") === "true" && !userTouched2()) {
|
|
6122
|
-
collapseNavSafe(head);
|
|
7351
|
+
document.addEventListener("keydown", (e) => {
|
|
7352
|
+
if (e.key === "Escape" && popupEl) {
|
|
7353
|
+
e.preventDefault();
|
|
7354
|
+
e.stopImmediatePropagation();
|
|
7355
|
+
closePopup(false);
|
|
7356
|
+
return;
|
|
6123
7357
|
}
|
|
6124
|
-
if (
|
|
6125
|
-
|
|
6126
|
-
|
|
6127
|
-
|
|
6128
|
-
|
|
6129
|
-
|
|
7358
|
+
if (popupEl && (e.key === "ArrowUp" || e.key === "ArrowDown" || e.key === "Enter")) {
|
|
7359
|
+
e.preventDefault();
|
|
7360
|
+
e.stopImmediatePropagation();
|
|
7361
|
+
if (e.key === "ArrowUp") moveUp();
|
|
7362
|
+
else if (e.key === "ArrowDown") moveDown();
|
|
7363
|
+
else if (!e.repeat) closePopup(true);
|
|
7364
|
+
return;
|
|
6130
7365
|
}
|
|
6131
|
-
|
|
6132
|
-
|
|
6133
|
-
|
|
6134
|
-
|
|
6135
|
-
|
|
6136
|
-
|
|
6137
|
-
|
|
6138
|
-
|
|
6139
|
-
|
|
6140
|
-
|
|
7366
|
+
if (!e.altKey || e.ctrlKey || e.metaKey || e.isComposing) return;
|
|
7367
|
+
if (document.querySelector(".zcodepro-overlay")) return;
|
|
7368
|
+
const k = e.key.toLowerCase();
|
|
7369
|
+
const isHot = k === hotkeys.switchLast || k === hotkeys.switchPrev || k === hotkeys.switchNext || k === hotkeys.switchRecent || k === hotkeys.switchAttention;
|
|
7370
|
+
if (!isHot) return;
|
|
7371
|
+
e.preventDefault();
|
|
7372
|
+
e.stopImmediatePropagation();
|
|
7373
|
+
void (async () => {
|
|
7374
|
+
const cfg = await getConfig();
|
|
7375
|
+
if (cfg.features && cfg.features.sessionSwitch === false) return;
|
|
7376
|
+
if (k === hotkeys.switchLast) {
|
|
7377
|
+
if (e.repeat) return;
|
|
7378
|
+
closePopup(false);
|
|
7379
|
+
const live = findCurrent();
|
|
7380
|
+
if (live) record(live.getAttribute("data-task-item-key"));
|
|
7381
|
+
const target = live ? mru[0] === current ? mru[1] : mru.find((mk) => mk !== current) : mru[0];
|
|
7382
|
+
if (!target) {
|
|
7383
|
+
showToast(t().switcherEmpty);
|
|
7384
|
+
return;
|
|
7385
|
+
}
|
|
7386
|
+
void switchTo(target).then((ok) => {
|
|
7387
|
+
if (!ok) showToast(t().switcherFailed, "error");
|
|
7388
|
+
});
|
|
7389
|
+
return;
|
|
7390
|
+
}
|
|
7391
|
+
if (k === hotkeys.switchAttention) {
|
|
7392
|
+
if (e.repeat) return;
|
|
7393
|
+
closePopup(false);
|
|
7394
|
+
if (!attentionList().length) {
|
|
7395
|
+
showToast(t().switcherAttentionEmpty);
|
|
7396
|
+
return;
|
|
7397
|
+
}
|
|
7398
|
+
await openPopup("attention");
|
|
7399
|
+
return;
|
|
7400
|
+
}
|
|
7401
|
+
if (mru.length < 2) {
|
|
7402
|
+
showToast(t().switcherEmpty);
|
|
7403
|
+
return;
|
|
7404
|
+
}
|
|
7405
|
+
if (k === hotkeys.switchRecent) {
|
|
7406
|
+
if (!e.repeat && !popupEl) await openPopup("mru");
|
|
7407
|
+
return;
|
|
7408
|
+
}
|
|
7409
|
+
if (!popupEl) await openPopup("mru");
|
|
7410
|
+
if (k === hotkeys.switchPrev) moveUp();
|
|
7411
|
+
else moveDown();
|
|
7412
|
+
})();
|
|
7413
|
+
}, true);
|
|
7414
|
+
document.addEventListener("keyup", (e) => {
|
|
7415
|
+
if (e.key === "Alt" && popupEl && movedSinceOpen) closePopup(true);
|
|
7416
|
+
}, true);
|
|
7417
|
+
window.addEventListener("blur", () => closePopup(false));
|
|
6141
7418
|
}
|
|
6142
7419
|
|
|
6143
|
-
// src/inject/features/
|
|
6144
|
-
var
|
|
7420
|
+
// src/inject/features/title-lock.js
|
|
7421
|
+
var TASK_SEL2 = "[data-task-item-key]";
|
|
7422
|
+
var SCAN_DEBOUNCE_MS3 = 150;
|
|
7423
|
+
var SCAN_FALLBACK_MS3 = 5e3;
|
|
7424
|
+
var BOOT_RETRY_MS = 5e3;
|
|
7425
|
+
var RECHECK_DELAY_MS = 1e3;
|
|
7426
|
+
var REVERIFY_MS = 3e3;
|
|
7427
|
+
var MAP_REFRESH_MS = 6e4;
|
|
7428
|
+
var installed3 = false;
|
|
7429
|
+
var seenRows = /* @__PURE__ */ new WeakSet();
|
|
6145
7430
|
var enabled3 = true;
|
|
6146
|
-
var
|
|
6147
|
-
var
|
|
6148
|
-
var
|
|
6149
|
-
var
|
|
6150
|
-
|
|
6151
|
-
var PEEK_MAX_MS = 1500;
|
|
6152
|
-
var PEEK_UNMOUNT_WAIT_MS = 800;
|
|
6153
|
-
var CONFIG_POLL_MIN_MS2 = 5e3;
|
|
6154
|
-
var CONFIG_POLL_MAX_MS2 = 6e4;
|
|
6155
|
-
var TASK_SEL3 = "[data-task-item-key]";
|
|
6156
|
-
var WS_SEL = '[data-testid^="workspace-item-"]';
|
|
6157
|
-
var runningByWs = /* @__PURE__ */ new Map();
|
|
6158
|
-
var peekTimers = /* @__PURE__ */ new Map();
|
|
6159
|
-
var activePeeks = /* @__PURE__ */ new Set();
|
|
6160
|
-
var peekedWs = /* @__PURE__ */ new Set();
|
|
6161
|
-
var wsWithRows = /* @__PURE__ */ new Set();
|
|
6162
|
-
function workspaceOf2(key) {
|
|
7431
|
+
var pinned = null;
|
|
7432
|
+
var resolved = false;
|
|
7433
|
+
var fetching = null;
|
|
7434
|
+
var pendingKeys = /* @__PURE__ */ new Set();
|
|
7435
|
+
function sessIdOf(key) {
|
|
6163
7436
|
const i = key.indexOf(":sess_");
|
|
6164
|
-
return i > 0 ? key.slice(
|
|
6165
|
-
}
|
|
6166
|
-
function findWsRow(ws) {
|
|
6167
|
-
return document.querySelector(`[data-testid="workspace-item-${CSS.escape(ws)}"]`);
|
|
6168
|
-
}
|
|
6169
|
-
function wsHead(row) {
|
|
6170
|
-
return row.matches("[aria-expanded]") ? row : row.querySelector("[aria-expanded]");
|
|
6171
|
-
}
|
|
6172
|
-
function isRunningRow(el) {
|
|
6173
|
-
const holder = el.firstElementChild && el.firstElementChild.querySelector(":scope > span");
|
|
6174
|
-
if (!holder) return false;
|
|
6175
|
-
return [...holder.children].some((c) => c.tagName === "svg" && (c.getAttribute("class") || "").includes("lucide-loader"));
|
|
7437
|
+
return i > 0 ? key.slice(i + 1) : key;
|
|
6176
7438
|
}
|
|
6177
|
-
function
|
|
6178
|
-
|
|
7439
|
+
function titleElsOf(item) {
|
|
7440
|
+
const copies = item.querySelectorAll("[data-task-title-copy]");
|
|
7441
|
+
if (copies.length) return [...copies];
|
|
7442
|
+
const t2 = item.querySelector('[class*="truncate"]');
|
|
7443
|
+
return t2 ? [t2] : [];
|
|
6179
7444
|
}
|
|
6180
|
-
function
|
|
6181
|
-
|
|
6182
|
-
if ((el.className + "").includes("bg-selected")) return el;
|
|
6183
|
-
}
|
|
6184
|
-
return null;
|
|
7445
|
+
function findRows(key) {
|
|
7446
|
+
return [...document.querySelectorAll(`${TASK_SEL2}[data-task-item-key="${CSS.escape(key)}"]`)];
|
|
6185
7447
|
}
|
|
6186
|
-
|
|
7448
|
+
async function fetchPinned() {
|
|
7449
|
+
if (fetching) return fetching;
|
|
7450
|
+
const p = (async () => {
|
|
7451
|
+
const res = await rpc("/pinned-titles");
|
|
7452
|
+
if (!res || !res.ok) return null;
|
|
7453
|
+
resolved = true;
|
|
7454
|
+
enabled3 = res.enabled !== false;
|
|
7455
|
+
if (!enabled3) {
|
|
7456
|
+
pinned = null;
|
|
7457
|
+
return null;
|
|
7458
|
+
}
|
|
7459
|
+
pinned = new Map(Object.entries(res.titles || {}));
|
|
7460
|
+
return pinned;
|
|
7461
|
+
})();
|
|
7462
|
+
fetching = p;
|
|
6187
7463
|
try {
|
|
6188
|
-
|
|
6189
|
-
}
|
|
7464
|
+
return await p;
|
|
7465
|
+
} finally {
|
|
7466
|
+
if (fetching === p) fetching = null;
|
|
6190
7467
|
}
|
|
6191
|
-
};
|
|
6192
|
-
function toggleNavSafe(head) {
|
|
6193
|
-
const cur = currentTaskRow2();
|
|
6194
|
-
const backKey = cur ? cur.getAttribute("data-task-item-key") : "";
|
|
6195
|
-
synthClick(head);
|
|
6196
|
-
if (!backKey) return;
|
|
6197
|
-
const back = cur && cur.isConnected ? cur : document.querySelector(`${TASK_SEL3}[data-task-item-key="${CSS.escape(backKey)}"]`);
|
|
6198
|
-
if (back) synthClick(back);
|
|
6199
7468
|
}
|
|
6200
|
-
function
|
|
6201
|
-
|
|
6202
|
-
|
|
6203
|
-
|
|
6204
|
-
|
|
6205
|
-
|
|
6206
|
-
|
|
6207
|
-
|
|
6208
|
-
|
|
6209
|
-
|
|
6210
|
-
if (!set) {
|
|
6211
|
-
set = /* @__PURE__ */ new Set();
|
|
6212
|
-
runningByWs.set(ws, set);
|
|
6213
|
-
}
|
|
6214
|
-
set.add(key);
|
|
6215
|
-
} else if (set) {
|
|
6216
|
-
set.delete(key);
|
|
6217
|
-
}
|
|
6218
|
-
}
|
|
6219
|
-
syncPeeks();
|
|
6220
|
-
apply();
|
|
7469
|
+
function isMismatch(item) {
|
|
7470
|
+
if (!enabled3 || !pinned) return null;
|
|
7471
|
+
const key = item.getAttribute("data-task-item-key") || "";
|
|
7472
|
+
const want = pinned.get(sessIdOf(key));
|
|
7473
|
+
if (want === void 0) return null;
|
|
7474
|
+
const els = titleElsOf(item);
|
|
7475
|
+
if (!els.length) return null;
|
|
7476
|
+
if ((els[0].textContent || "").trim() === String(want).trim()) return null;
|
|
7477
|
+
if (item.querySelector('input, textarea, [contenteditable="true"]')) return null;
|
|
7478
|
+
return key;
|
|
6221
7479
|
}
|
|
6222
|
-
function
|
|
6223
|
-
const
|
|
6224
|
-
|
|
6225
|
-
|
|
6226
|
-
|
|
6227
|
-
|
|
6228
|
-
|
|
6229
|
-
|
|
7480
|
+
function writeTitle(el, text) {
|
|
7481
|
+
const walker = document.createTreeWalker(el, NodeFilter.SHOW_TEXT);
|
|
7482
|
+
const first = walker.nextNode();
|
|
7483
|
+
if (first && !walker.nextNode()) first.nodeValue = text;
|
|
7484
|
+
else el.textContent = text;
|
|
7485
|
+
}
|
|
7486
|
+
function scheduleEnforce(key, { immediate = false } = {}) {
|
|
7487
|
+
if (immediate) {
|
|
7488
|
+
if (enabled3 && pinned) {
|
|
7489
|
+
const want = pinned.get(sessIdOf(key));
|
|
7490
|
+
if (want !== void 0) {
|
|
7491
|
+
for (const item of findRows(key)) {
|
|
7492
|
+
for (const el of titleElsOf(item)) writeTitle(el, want);
|
|
7493
|
+
}
|
|
7494
|
+
}
|
|
6230
7495
|
}
|
|
6231
7496
|
}
|
|
6232
|
-
if (
|
|
6233
|
-
|
|
6234
|
-
const key = el.getAttribute("data-task-item-key") || "";
|
|
6235
|
-
const ws = workspaceOf2(key);
|
|
6236
|
-
return key && ws ? { key, ws, run: isRunningRow(el) } : null;
|
|
6237
|
-
}).filter(Boolean);
|
|
6238
|
-
if (!infos.length) return;
|
|
7497
|
+
if (pendingKeys.has(key)) return;
|
|
7498
|
+
pendingKeys.add(key);
|
|
6239
7499
|
setTimeout(() => {
|
|
6240
|
-
|
|
6241
|
-
|
|
6242
|
-
const
|
|
6243
|
-
|
|
6244
|
-
|
|
6245
|
-
if (
|
|
6246
|
-
|
|
6247
|
-
|
|
6248
|
-
|
|
6249
|
-
|
|
6250
|
-
|
|
6251
|
-
} else if (set) {
|
|
6252
|
-
set.delete(info.key);
|
|
7500
|
+
pendingKeys.delete(key);
|
|
7501
|
+
void (async () => {
|
|
7502
|
+
const map = await fetchPinned();
|
|
7503
|
+
if (!map) return;
|
|
7504
|
+
const want = map.get(sessIdOf(key));
|
|
7505
|
+
if (want === void 0) return;
|
|
7506
|
+
let wrote = false;
|
|
7507
|
+
for (const item of findRows(key)) {
|
|
7508
|
+
if (isMismatch(item) !== key) continue;
|
|
7509
|
+
for (const el of titleElsOf(item)) writeTitle(el, want);
|
|
7510
|
+
wrote = true;
|
|
6253
7511
|
}
|
|
6254
|
-
|
|
6255
|
-
|
|
6256
|
-
|
|
6257
|
-
|
|
6258
|
-
|
|
6259
|
-
function apply() {
|
|
6260
|
-
const seen = /* @__PURE__ */ new Set();
|
|
6261
|
-
for (const row of document.querySelectorAll(WS_SEL)) {
|
|
6262
|
-
const path = row.getAttribute("data-testid").slice("workspace-item-".length);
|
|
6263
|
-
seen.add(path);
|
|
6264
|
-
const head = wsHead(row);
|
|
6265
|
-
const collapsed = !head || head.getAttribute("aria-expanded") === "false";
|
|
6266
|
-
const running = !!(enabled3 && collapsed && runningByWs.get(path) && runningByWs.get(path).size);
|
|
6267
|
-
const icon = row.firstElementChild && row.firstElementChild.querySelector(":scope > span");
|
|
6268
|
-
if (icon) icon.classList.toggle("zcodepro-ws-running", running);
|
|
6269
|
-
}
|
|
6270
|
-
for (const ws of [...runningByWs.keys()]) if (!seen.has(ws)) runningByWs.delete(ws);
|
|
6271
|
-
}
|
|
6272
|
-
function schedulePeek(ws, delay) {
|
|
6273
|
-
clearTimeout(peekTimers.get(ws));
|
|
6274
|
-
peekTimers.set(ws, setTimeout(() => {
|
|
6275
|
-
peekTimers.delete(ws);
|
|
6276
|
-
void peek(ws);
|
|
6277
|
-
}, delay));
|
|
7512
|
+
if (wrote) setTimeout(() => {
|
|
7513
|
+
void enforceKey(key);
|
|
7514
|
+
}, REVERIFY_MS);
|
|
7515
|
+
})();
|
|
7516
|
+
}, RECHECK_DELAY_MS);
|
|
6278
7517
|
}
|
|
6279
|
-
function
|
|
6280
|
-
const
|
|
6281
|
-
if (
|
|
6282
|
-
|
|
6283
|
-
|
|
7518
|
+
async function enforceKey(key) {
|
|
7519
|
+
const map = await fetchPinned();
|
|
7520
|
+
if (!map) return;
|
|
7521
|
+
const want = map.get(sessIdOf(key));
|
|
7522
|
+
if (want === void 0) return;
|
|
7523
|
+
for (const item of findRows(key)) {
|
|
7524
|
+
if (isMismatch(item) !== key) continue;
|
|
7525
|
+
for (const el of titleElsOf(item)) writeTitle(el, want);
|
|
6284
7526
|
}
|
|
6285
7527
|
}
|
|
6286
|
-
function
|
|
6287
|
-
|
|
6288
|
-
|
|
6289
|
-
|
|
7528
|
+
function scan3() {
|
|
7529
|
+
if (!enabled3 || !pinned || pinned.size === 0) return;
|
|
7530
|
+
for (const item of document.querySelectorAll(TASK_SEL2)) {
|
|
7531
|
+
const key = isMismatch(item);
|
|
7532
|
+
if (!key) {
|
|
7533
|
+
seenRows.add(item);
|
|
6290
7534
|
continue;
|
|
6291
7535
|
}
|
|
6292
|
-
const
|
|
6293
|
-
|
|
6294
|
-
|
|
6295
|
-
|
|
6296
|
-
|
|
7536
|
+
const fresh = !seenRows.has(item);
|
|
7537
|
+
seenRows.add(item);
|
|
7538
|
+
scheduleEnforce(key, { immediate: fresh });
|
|
7539
|
+
}
|
|
7540
|
+
}
|
|
7541
|
+
var inTaskRow2 = (node) => !!(node instanceof Element && node.closest && node.closest(TASK_SEL2));
|
|
7542
|
+
function taskRowMutations2(muts) {
|
|
7543
|
+
for (const m of muts) {
|
|
7544
|
+
if (m.type === "attributes") {
|
|
7545
|
+
if (inTaskRow2(m.target)) return true;
|
|
7546
|
+
} else if (m.type === "characterData") {
|
|
7547
|
+
if (m.target.parentElement && inTaskRow2(m.target.parentElement)) return true;
|
|
7548
|
+
} else if (inTaskRow2(m.target)) {
|
|
7549
|
+
return true;
|
|
7550
|
+
} else {
|
|
7551
|
+
for (const n of m.addedNodes) {
|
|
7552
|
+
if (n instanceof Element && (n.matches(TASK_SEL2) || !!n.querySelector(TASK_SEL2))) return true;
|
|
7553
|
+
}
|
|
6297
7554
|
}
|
|
6298
|
-
if (!peekTimers.has(ws) && !activePeeks.has(ws)) schedulePeek(ws, peekedWs.has(ws) ? PEEK_REPEAT_MS : PEEK_FIRST_MS);
|
|
6299
7555
|
}
|
|
7556
|
+
return false;
|
|
6300
7557
|
}
|
|
6301
|
-
var
|
|
6302
|
-
|
|
6303
|
-
|
|
6304
|
-
|
|
6305
|
-
|
|
6306
|
-
|
|
6307
|
-
|
|
7558
|
+
var scanDebounce3 = 0;
|
|
7559
|
+
function scheduleScan2() {
|
|
7560
|
+
if (scanDebounce3) return;
|
|
7561
|
+
scanDebounce3 = setTimeout(() => {
|
|
7562
|
+
scanDebounce3 = 0;
|
|
7563
|
+
scan3();
|
|
7564
|
+
}, SCAN_DEBOUNCE_MS3);
|
|
6308
7565
|
}
|
|
6309
|
-
|
|
6310
|
-
|
|
6311
|
-
|
|
6312
|
-
const
|
|
6313
|
-
|
|
6314
|
-
|
|
6315
|
-
|
|
6316
|
-
return false;
|
|
6317
|
-
}
|
|
6318
|
-
activePeeks.add(ws);
|
|
6319
|
-
peekedWs.add(ws);
|
|
6320
|
-
const rect = row.getBoundingClientRect();
|
|
6321
|
-
const frozen = row.cloneNode(true);
|
|
6322
|
-
frozen.classList.add("zcodepro-ws-frozen");
|
|
6323
|
-
frozen.style.left = rect.left + "px";
|
|
6324
|
-
frozen.style.top = rect.top + "px";
|
|
6325
|
-
frozen.style.width = rect.width + "px";
|
|
6326
|
-
frozen.style.height = rect.height + "px";
|
|
6327
|
-
document.body.append(frozen);
|
|
6328
|
-
row.style.visibility = "hidden";
|
|
6329
|
-
const hider = installPeekHider(ws);
|
|
6330
|
-
try {
|
|
6331
|
-
toggleNavSafe(head);
|
|
6332
|
-
await settleAndRead(ws);
|
|
6333
|
-
const rowNow = findWsRow(ws) || row;
|
|
6334
|
-
const headNow = wsHead(rowNow);
|
|
6335
|
-
if (headNow && headNow.getAttribute("aria-expanded") === "true" && !userTouched(rowNow)) {
|
|
6336
|
-
toggleNavSafe(headNow);
|
|
6337
|
-
await waitForRowsGone(ws);
|
|
7566
|
+
var mapRefreshTimer = 0;
|
|
7567
|
+
function refreshMapSoon() {
|
|
7568
|
+
if (mapRefreshTimer) return;
|
|
7569
|
+
const tick2 = () => {
|
|
7570
|
+
if (document.hidden) {
|
|
7571
|
+
mapRefreshTimer = setTimeout(tick2, 1e4);
|
|
7572
|
+
return;
|
|
6338
7573
|
}
|
|
6339
|
-
|
|
6340
|
-
|
|
6341
|
-
|
|
6342
|
-
|
|
6343
|
-
|
|
7574
|
+
mapRefreshTimer = 0;
|
|
7575
|
+
if (enabled3 && resolved) void fetchPinned().then((m) => {
|
|
7576
|
+
if (m) scan3();
|
|
7577
|
+
});
|
|
7578
|
+
};
|
|
7579
|
+
mapRefreshTimer = setTimeout(tick2, MAP_REFRESH_MS);
|
|
7580
|
+
}
|
|
7581
|
+
var editingKey = null;
|
|
7582
|
+
var bootDelay = 0;
|
|
7583
|
+
function scheduleBootRetry() {
|
|
7584
|
+
bootDelay = bootDelay ? Math.min(bootDelay * 2, MAP_REFRESH_MS) : BOOT_RETRY_MS;
|
|
7585
|
+
setTimeout(() => {
|
|
7586
|
+
if (resolved) return;
|
|
7587
|
+
if (!document.hidden) void bootstrap();
|
|
7588
|
+
scheduleBootRetry();
|
|
7589
|
+
}, bootDelay);
|
|
7590
|
+
}
|
|
7591
|
+
async function bootstrap() {
|
|
7592
|
+
const map = await fetchPinned();
|
|
7593
|
+
if (map) scan3();
|
|
7594
|
+
}
|
|
7595
|
+
function setRowTitle(key, text) {
|
|
7596
|
+
for (const item of findRows(key)) {
|
|
7597
|
+
for (const el of titleElsOf(item)) writeTitle(el, text);
|
|
6344
7598
|
}
|
|
6345
|
-
apply();
|
|
6346
|
-
const set = runningByWs.get(ws);
|
|
6347
|
-
if (set && set.size && enabled3) schedulePeek(ws, PEEK_REPEAT_MS);
|
|
6348
|
-
return true;
|
|
6349
7599
|
}
|
|
6350
|
-
function
|
|
6351
|
-
|
|
6352
|
-
|
|
6353
|
-
|
|
6354
|
-
current: curKey ? workspaceOf2(curKey) || null : null
|
|
6355
|
-
};
|
|
7600
|
+
function refreshPinnedTitles() {
|
|
7601
|
+
return fetchPinned().then((m) => {
|
|
7602
|
+
if (m) scan3();
|
|
7603
|
+
});
|
|
6356
7604
|
}
|
|
6357
|
-
|
|
6358
|
-
|
|
6359
|
-
|
|
6360
|
-
|
|
6361
|
-
if (
|
|
6362
|
-
|
|
6363
|
-
|
|
6364
|
-
|
|
6365
|
-
return !run;
|
|
7605
|
+
var RENAME_CTX_VALID_MS = 15e3;
|
|
7606
|
+
var renameCtx = null;
|
|
7607
|
+
var renamePrefilled = /* @__PURE__ */ new WeakSet();
|
|
7608
|
+
function setNativeValue(el, text) {
|
|
7609
|
+
if (el instanceof HTMLInputElement || el instanceof HTMLTextAreaElement) {
|
|
7610
|
+
Object.getOwnPropertyDescriptor(el.constructor.prototype, "value").set.call(el, text);
|
|
7611
|
+
} else {
|
|
7612
|
+
el.textContent = text;
|
|
6366
7613
|
}
|
|
6367
|
-
|
|
6368
|
-
|
|
6369
|
-
|
|
6370
|
-
|
|
7614
|
+
el.dispatchEvent(new Event("input", { bubbles: true }));
|
|
7615
|
+
}
|
|
7616
|
+
function prefillRenameDialog() {
|
|
7617
|
+
if (!renameCtx || !renameCtx.armed || Date.now() - renameCtx.at > RENAME_CTX_VALID_MS) {
|
|
7618
|
+
renameCtx = null;
|
|
7619
|
+
return;
|
|
7620
|
+
}
|
|
7621
|
+
if (!enabled3 || !pinned) return;
|
|
7622
|
+
const want = pinned.get(sessIdOf(renameCtx.key));
|
|
7623
|
+
if (want === void 0) return;
|
|
7624
|
+
for (const el of document.querySelectorAll('[role="dialog"] input, [role="dialog"] textarea, [role="dialog"] [contenteditable="true"]')) {
|
|
7625
|
+
if (renamePrefilled.has(el) || !el.getClientRects().length) continue;
|
|
7626
|
+
if (el.closest(TASK_SEL2) || el.closest(".zcodepro-overlay")) continue;
|
|
7627
|
+
const cur = String(el.value ?? el.textContent ?? "").trim();
|
|
7628
|
+
if (!cur) continue;
|
|
7629
|
+
renamePrefilled.add(el);
|
|
7630
|
+
if (cur !== String(want).trim()) setNativeValue(el, String(want));
|
|
7631
|
+
renameCtx = null;
|
|
7632
|
+
return;
|
|
6371
7633
|
}
|
|
6372
|
-
if (!verified) return false;
|
|
6373
|
-
const set = runningByWs.get(ws);
|
|
6374
|
-
return !(set && set.size);
|
|
6375
7634
|
}
|
|
6376
|
-
function
|
|
6377
|
-
|
|
6378
|
-
|
|
6379
|
-
|
|
6380
|
-
|
|
6381
|
-
|
|
6382
|
-
|
|
6383
|
-
|
|
6384
|
-
|
|
6385
|
-
|
|
6386
|
-
|
|
6387
|
-
|
|
6388
|
-
|
|
6389
|
-
|
|
6390
|
-
|
|
6391
|
-
|
|
6392
|
-
|
|
6393
|
-
|
|
6394
|
-
|
|
6395
|
-
|
|
6396
|
-
|
|
6397
|
-
|
|
6398
|
-
|
|
6399
|
-
|
|
6400
|
-
|
|
6401
|
-
|
|
6402
|
-
|
|
6403
|
-
|
|
6404
|
-
|
|
6405
|
-
|
|
6406
|
-
|
|
7635
|
+
function startTitleLock() {
|
|
7636
|
+
if (installed3 || typeof document === "undefined") return;
|
|
7637
|
+
installed3 = true;
|
|
7638
|
+
void bootstrap();
|
|
7639
|
+
new MutationObserver((muts) => {
|
|
7640
|
+
if (renameCtx) prefillRenameDialog();
|
|
7641
|
+
if (!taskRowMutations2(muts)) return;
|
|
7642
|
+
refreshMapSoon();
|
|
7643
|
+
scheduleScan2();
|
|
7644
|
+
}).observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ["class"], characterData: true });
|
|
7645
|
+
document.addEventListener("contextmenu", (e) => {
|
|
7646
|
+
const row = e.target instanceof Element && e.target.closest(TASK_SEL2);
|
|
7647
|
+
renameCtx = row ? { key: row.getAttribute("data-task-item-key") || "", at: 0, armed: false } : null;
|
|
7648
|
+
}, true);
|
|
7649
|
+
document.addEventListener("click", (e) => {
|
|
7650
|
+
if (!renameCtx || renameCtx.armed) return;
|
|
7651
|
+
const item = e.target instanceof Element && e.target.closest('[role="menuitem"], [data-radix-collection-item]');
|
|
7652
|
+
if (item && /重命名|rename/i.test(item.textContent || "")) {
|
|
7653
|
+
renameCtx.armed = true;
|
|
7654
|
+
renameCtx.at = Date.now();
|
|
7655
|
+
}
|
|
7656
|
+
}, true);
|
|
7657
|
+
scheduleBootRetry();
|
|
7658
|
+
setInterval(() => {
|
|
7659
|
+
if (!document.hidden) scan3();
|
|
7660
|
+
}, SCAN_FALLBACK_MS3);
|
|
7661
|
+
document.addEventListener("visibilitychange", () => {
|
|
7662
|
+
if (!document.hidden) scan3();
|
|
7663
|
+
});
|
|
7664
|
+
window.addEventListener("zcodepro:config-changed", () => {
|
|
7665
|
+
void bootstrap();
|
|
7666
|
+
});
|
|
7667
|
+
document.addEventListener("focusin", (e) => {
|
|
7668
|
+
const el = e.target;
|
|
7669
|
+
if (!(el instanceof Element)) return;
|
|
7670
|
+
if (!el.matches('input, textarea, [contenteditable="true"]')) return;
|
|
7671
|
+
const row = el.closest(TASK_SEL2);
|
|
7672
|
+
editingKey = row ? row.getAttribute("data-task-item-key") || "" : null;
|
|
7673
|
+
});
|
|
7674
|
+
document.addEventListener("focusout", () => {
|
|
7675
|
+
if (editingKey === null) return;
|
|
7676
|
+
editingKey = null;
|
|
7677
|
+
void fetchPinned().then((m) => {
|
|
7678
|
+
if (m) scan3();
|
|
7679
|
+
});
|
|
6407
7680
|
});
|
|
6408
7681
|
}
|
|
6409
|
-
|
|
6410
|
-
|
|
6411
|
-
|
|
6412
|
-
|
|
6413
|
-
|
|
6414
|
-
|
|
6415
|
-
|
|
6416
|
-
|
|
6417
|
-
|
|
7682
|
+
|
|
7683
|
+
// src/inject/features/title-gen.js
|
|
7684
|
+
var CONV2 = '[class*="@md/conversation"]';
|
|
7685
|
+
var USER_ROW = '[class*="user-row"]';
|
|
7686
|
+
var SCAN_DEBOUNCE_MS4 = 300;
|
|
7687
|
+
var SCAN_FALLBACK_MS4 = 5e3;
|
|
7688
|
+
var SELECT_WAIT_MS = 2e3;
|
|
7689
|
+
var MSG_WAIT_MS = 1e4;
|
|
7690
|
+
var QUIET_FALLBACK_MS = 12e4;
|
|
7691
|
+
var COLLECT_MAX_MS = 6e5;
|
|
7692
|
+
var installed4 = false;
|
|
7693
|
+
var knownKeys = /* @__PURE__ */ new Set();
|
|
7694
|
+
var attempted = /* @__PURE__ */ new Set();
|
|
7695
|
+
var sleep2 = (ms) => new Promise((r) => setTimeout(r, ms));
|
|
7696
|
+
function sessIdOf2(key) {
|
|
7697
|
+
const i = key.indexOf(":sess_");
|
|
7698
|
+
return i > 0 ? key.slice(i + 1) : "";
|
|
6418
7699
|
}
|
|
6419
|
-
function
|
|
6420
|
-
|
|
6421
|
-
|
|
7700
|
+
function currentKey() {
|
|
7701
|
+
for (const el of document.querySelectorAll("[data-task-item-key]")) {
|
|
7702
|
+
if ((el.className + "").includes("bg-selected")) return el.getAttribute("data-task-item-key") || "";
|
|
7703
|
+
}
|
|
7704
|
+
return "";
|
|
6422
7705
|
}
|
|
6423
|
-
function
|
|
6424
|
-
|
|
6425
|
-
|
|
6426
|
-
|
|
6427
|
-
|
|
6428
|
-
if (!document.querySelector(sel) || Date.now() - t0 >= PEEK_UNMOUNT_WAIT_MS) {
|
|
6429
|
-
clearInterval(timer);
|
|
6430
|
-
resolve();
|
|
6431
|
-
}
|
|
6432
|
-
}, 40);
|
|
6433
|
-
});
|
|
7706
|
+
function userTexts() {
|
|
7707
|
+
return [...document.querySelectorAll(`${CONV2} ${USER_ROW}`)].map((r) => {
|
|
7708
|
+
const el = r.querySelector(".whitespace-pre-wrap");
|
|
7709
|
+
return ((el ? el.textContent : r.innerText) || "").trim();
|
|
7710
|
+
}).filter(Boolean);
|
|
6434
7711
|
}
|
|
6435
|
-
var
|
|
6436
|
-
|
|
6437
|
-
|
|
6438
|
-
const
|
|
6439
|
-
|
|
7712
|
+
var URL_RE = /https?:\/\/[^\s\u4e00-\u9fff\u3000-\u303f\uff00-\uffef]+/g;
|
|
7713
|
+
function assistantText() {
|
|
7714
|
+
const els = [...document.querySelectorAll('[class*="@md/conversation"] [class*="assistant-row"]')].filter((e) => !e.querySelector("[data-is-streaming]"));
|
|
7715
|
+
const last = els[els.length - 1];
|
|
7716
|
+
if (!last) return "";
|
|
7717
|
+
const text = (last.innerText || "").replace(URL_RE, "").trim();
|
|
7718
|
+
return text.slice(0, 600);
|
|
6440
7719
|
}
|
|
6441
|
-
function
|
|
6442
|
-
|
|
7720
|
+
function linkDominant(t2) {
|
|
7721
|
+
const raw = t2.replace(/\s+/g, "");
|
|
7722
|
+
if (!raw) return true;
|
|
7723
|
+
const stripped = raw.replace(URL_RE, "");
|
|
7724
|
+
return stripped.length < raw.length / 3;
|
|
6443
7725
|
}
|
|
6444
|
-
function
|
|
6445
|
-
|
|
6446
|
-
|
|
6447
|
-
|
|
6448
|
-
|
|
7726
|
+
async function onNewTaskRow(key) {
|
|
7727
|
+
const selDeadline = Date.now() + SELECT_WAIT_MS;
|
|
7728
|
+
while (currentKey() !== key && Date.now() < selDeadline) await sleep2(200);
|
|
7729
|
+
if (currentKey() !== key) return;
|
|
7730
|
+
const cfg = await getConfig().catch(() => null);
|
|
7731
|
+
if (!cfg || !cfg.titleGen || cfg.titleGen.enabled !== true) return;
|
|
7732
|
+
const sessId = sessIdOf2(key);
|
|
7733
|
+
if (!sessId || attempted.has(sessId)) return;
|
|
7734
|
+
attempted.add(sessId);
|
|
7735
|
+
let texts = [];
|
|
7736
|
+
const msgDeadline = Date.now() + MSG_WAIT_MS;
|
|
7737
|
+
while (Date.now() < msgDeadline) {
|
|
7738
|
+
texts = userTexts();
|
|
7739
|
+
if (texts.length) break;
|
|
7740
|
+
await sleep2(400);
|
|
7741
|
+
}
|
|
7742
|
+
if (!texts.length) return;
|
|
7743
|
+
let assistantSeen = false;
|
|
7744
|
+
const convObserver = new MutationObserver((muts) => {
|
|
7745
|
+
if (currentKey() !== key) return;
|
|
7746
|
+
for (const m of muts) {
|
|
7747
|
+
const t2 = m.type === "characterData" ? m.target.parentElement : m.target;
|
|
7748
|
+
if (t2 instanceof Element && t2.closest(USER_ROW)) continue;
|
|
7749
|
+
for (const n of [t2, ...m.addedNodes]) {
|
|
7750
|
+
if (n instanceof Element && n.closest && n.closest(CONV2)) {
|
|
7751
|
+
assistantSeen = true;
|
|
7752
|
+
return;
|
|
7753
|
+
}
|
|
7754
|
+
}
|
|
6449
7755
|
}
|
|
6450
|
-
|
|
6451
|
-
|
|
7756
|
+
});
|
|
7757
|
+
convObserver.observe(document.body, { childList: true, subtree: true, characterData: true });
|
|
7758
|
+
const startAt = Date.now();
|
|
7759
|
+
let lastCount = texts.length;
|
|
7760
|
+
let lastChange = Date.now();
|
|
7761
|
+
try {
|
|
7762
|
+
while (Date.now() - startAt < COLLECT_MAX_MS) {
|
|
7763
|
+
await sleep2(500);
|
|
7764
|
+
if (currentKey() !== key) {
|
|
7765
|
+
lastChange = Date.now();
|
|
7766
|
+
continue;
|
|
7767
|
+
}
|
|
7768
|
+
texts = userTexts();
|
|
7769
|
+
if (texts.length !== lastCount) {
|
|
7770
|
+
lastCount = texts.length;
|
|
7771
|
+
lastChange = Date.now();
|
|
7772
|
+
}
|
|
7773
|
+
if (assistantSeen) break;
|
|
7774
|
+
if (Date.now() - lastChange >= QUIET_FALLBACK_MS) break;
|
|
6452
7775
|
}
|
|
7776
|
+
} finally {
|
|
7777
|
+
convObserver.disconnect();
|
|
7778
|
+
}
|
|
7779
|
+
if (!texts.length) return;
|
|
7780
|
+
if (linkDominant(texts.join("\n"))) {
|
|
7781
|
+
const deadline = Date.now() + 6e4;
|
|
7782
|
+
while (Date.now() < deadline) {
|
|
7783
|
+
await sleep2(2e3);
|
|
7784
|
+
if (currentKey() !== key) continue;
|
|
7785
|
+
const a = assistantText();
|
|
7786
|
+
if (a && a.length > 80) {
|
|
7787
|
+
texts.push(`\uFF08\u9996\u8F6E\u56DE\u7B54\u6458\u8981\uFF09${a}`);
|
|
7788
|
+
break;
|
|
7789
|
+
}
|
|
7790
|
+
}
|
|
7791
|
+
}
|
|
7792
|
+
const callTitleGen = () => rpc("/title-gen/run", { method: "POST", body: { sessId, text: texts.join("\n") } }).catch(() => null);
|
|
7793
|
+
let res = await callTitleGen();
|
|
7794
|
+
for (const delay of [5e3, 2e4]) {
|
|
7795
|
+
if (res && res.ok) break;
|
|
7796
|
+
await sleep2(delay);
|
|
7797
|
+
res = await callTitleGen();
|
|
7798
|
+
}
|
|
7799
|
+
if (res && res.ok && res.written && res.title) {
|
|
7800
|
+
setRowTitle(key, res.title);
|
|
7801
|
+
void refreshPinnedTitles();
|
|
6453
7802
|
}
|
|
6454
|
-
return false;
|
|
6455
7803
|
}
|
|
6456
|
-
|
|
6457
|
-
|
|
6458
|
-
|
|
6459
|
-
|
|
6460
|
-
|
|
6461
|
-
|
|
6462
|
-
|
|
6463
|
-
|
|
6464
|
-
|
|
6465
|
-
|
|
6466
|
-
|
|
6467
|
-
|
|
6468
|
-
|
|
7804
|
+
function scanForNewRows() {
|
|
7805
|
+
for (const el of document.querySelectorAll("[data-task-item-key]")) {
|
|
7806
|
+
const key = el.getAttribute("data-task-item-key") || "";
|
|
7807
|
+
if (!key || knownKeys.has(key)) continue;
|
|
7808
|
+
knownKeys.add(key);
|
|
7809
|
+
void onNewTaskRow(key);
|
|
7810
|
+
}
|
|
7811
|
+
}
|
|
7812
|
+
var TASK_SEL3 = "[data-task-item-key]";
|
|
7813
|
+
var inTaskRow3 = (node) => !!(node instanceof Element && node.closest && node.closest(TASK_SEL3));
|
|
7814
|
+
function taskRowMutations3(muts) {
|
|
7815
|
+
for (const m of muts) {
|
|
7816
|
+
if (m.type === "attributes") {
|
|
7817
|
+
if (inTaskRow3(m.target)) return true;
|
|
7818
|
+
} else if (m.type === "characterData") {
|
|
7819
|
+
if (m.target.parentElement && inTaskRow3(m.target.parentElement)) return true;
|
|
7820
|
+
} else if (inTaskRow3(m.target)) {
|
|
7821
|
+
return true;
|
|
7822
|
+
} else {
|
|
7823
|
+
for (const n of m.addedNodes) {
|
|
7824
|
+
if (n instanceof Element && (n.matches(TASK_SEL3) || !!n.querySelector(TASK_SEL3))) return true;
|
|
6469
7825
|
}
|
|
6470
7826
|
}
|
|
6471
|
-
} catch {
|
|
6472
7827
|
}
|
|
6473
7828
|
return false;
|
|
6474
7829
|
}
|
|
6475
|
-
function pollConfig2() {
|
|
6476
|
-
setTimeout(async () => {
|
|
6477
|
-
if (document.hidden) pollMs2 = CONFIG_POLL_MAX_MS2;
|
|
6478
|
-
else pollMs2 = await refreshConfig2() ? CONFIG_POLL_MIN_MS2 : Math.min(Math.round(pollMs2 * 1.5), CONFIG_POLL_MAX_MS2);
|
|
6479
|
-
pollConfig2();
|
|
6480
|
-
}, pollMs2);
|
|
6481
|
-
}
|
|
6482
7830
|
var scanDebounce4 = 0;
|
|
6483
|
-
function
|
|
6484
|
-
if (
|
|
6485
|
-
|
|
6486
|
-
|
|
6487
|
-
|
|
6488
|
-
|
|
6489
|
-
|
|
6490
|
-
|
|
6491
|
-
|
|
6492
|
-
|
|
6493
|
-
|
|
6494
|
-
|
|
6495
|
-
|
|
6496
|
-
|
|
6497
|
-
});
|
|
6498
|
-
observer2.observe(document.body, { childList: true, subtree: true });
|
|
6499
|
-
scan3();
|
|
7831
|
+
function scheduleScan3() {
|
|
7832
|
+
if (scanDebounce4) return;
|
|
7833
|
+
scanDebounce4 = setTimeout(() => {
|
|
7834
|
+
scanDebounce4 = 0;
|
|
7835
|
+
scanForNewRows();
|
|
7836
|
+
}, SCAN_DEBOUNCE_MS4);
|
|
7837
|
+
}
|
|
7838
|
+
function startTitleGen() {
|
|
7839
|
+
if (installed4 || typeof document === "undefined") return;
|
|
7840
|
+
installed4 = true;
|
|
7841
|
+
scanForNewRows();
|
|
7842
|
+
new MutationObserver((muts) => {
|
|
7843
|
+
if (taskRowMutations3(muts)) scheduleScan3();
|
|
7844
|
+
}).observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ["class"], characterData: true });
|
|
6500
7845
|
setInterval(() => {
|
|
6501
|
-
if (!document.hidden
|
|
7846
|
+
if (!document.hidden) scanForNewRows();
|
|
6502
7847
|
}, SCAN_FALLBACK_MS4);
|
|
6503
7848
|
document.addEventListener("visibilitychange", () => {
|
|
6504
|
-
if (!document.hidden)
|
|
7849
|
+
if (!document.hidden) scanForNewRows();
|
|
6505
7850
|
});
|
|
6506
|
-
document.addEventListener("click", (e) => {
|
|
6507
|
-
if (!e.isTrusted) return;
|
|
6508
|
-
const row = e.target instanceof Element && e.target.closest(WS_SEL);
|
|
6509
|
-
if (row) wsTouchAt.set(row, Date.now());
|
|
6510
|
-
}, true);
|
|
6511
7851
|
}
|
|
6512
7852
|
|
|
6513
7853
|
// src/inject/features/idle-reclaim.js
|
|
6514
7854
|
var CHECK_MS = 3e4;
|
|
6515
|
-
var WS_SEL2 = '[data-testid^="workspace-item-"]';
|
|
6516
7855
|
var MIN_MINUTES = 1;
|
|
6517
7856
|
var MAX_MINUTES = 1440;
|
|
6518
7857
|
var idleSince = /* @__PURE__ */ new Map();
|
|
@@ -6520,46 +7859,16 @@
|
|
|
6520
7859
|
var scanDisabledLogged = false;
|
|
6521
7860
|
var bootAt = Date.now();
|
|
6522
7861
|
var startupSweepDone = false;
|
|
6523
|
-
|
|
6524
|
-
function findServices() {
|
|
6525
|
-
if (servicesRef) return servicesRef;
|
|
6526
|
-
try {
|
|
6527
|
-
const rootEl = document.getElementById("root");
|
|
6528
|
-
const containerKey = rootEl && Object.keys(rootEl).find((k) => k.startsWith("__reactContainer$"));
|
|
6529
|
-
if (!containerKey) return null;
|
|
6530
|
-
const seen = /* @__PURE__ */ new Set();
|
|
6531
|
-
let found = null;
|
|
6532
|
-
const scanObj = (o) => {
|
|
6533
|
-
if (!o || typeof o !== "object" || seen.has(o) || found) return;
|
|
6534
|
-
seen.add(o);
|
|
6535
|
-
const ts = o.zcodeTaskService;
|
|
6536
|
-
if (ts && typeof ts === "object" && typeof ts.releaseWorkspacePreparation === "function") found = o;
|
|
6537
|
-
};
|
|
6538
|
-
let visited = 0;
|
|
6539
|
-
const visit = (f) => {
|
|
6540
|
-
if (!f || found || visited > 6e4) return;
|
|
6541
|
-
visited++;
|
|
6542
|
-
for (const holder of [f.memoizedProps, f.memoizedState]) {
|
|
6543
|
-
if (!holder || typeof holder !== "object") continue;
|
|
6544
|
-
scanObj(holder);
|
|
6545
|
-
for (const v of Object.values(holder)) {
|
|
6546
|
-
if (v && typeof v === "object") scanObj(v);
|
|
6547
|
-
}
|
|
6548
|
-
}
|
|
6549
|
-
visit(f.child);
|
|
6550
|
-
visit(f.sibling);
|
|
6551
|
-
};
|
|
6552
|
-
visit(rootEl[containerKey]);
|
|
6553
|
-
if (found) servicesRef = found;
|
|
6554
|
-
return found;
|
|
6555
|
-
} catch {
|
|
6556
|
-
return null;
|
|
6557
|
-
}
|
|
6558
|
-
}
|
|
6559
|
-
function sidebarWorkspaces() {
|
|
7862
|
+
async function sidebarWorkspaces() {
|
|
6560
7863
|
const out = /* @__PURE__ */ new Set();
|
|
6561
|
-
|
|
6562
|
-
|
|
7864
|
+
const res = await rpc("/projects-v2").catch(() => null);
|
|
7865
|
+
if (res && res.ok && res.available) {
|
|
7866
|
+
for (const proj of res.projects || []) {
|
|
7867
|
+
for (const r of proj.roots || []) {
|
|
7868
|
+
const p = String(r.path || "").replace(/[\/]+$/, "");
|
|
7869
|
+
if (p) out.add(p);
|
|
7870
|
+
}
|
|
7871
|
+
}
|
|
6563
7872
|
}
|
|
6564
7873
|
return out;
|
|
6565
7874
|
}
|
|
@@ -6578,8 +7887,14 @@
|
|
|
6578
7887
|
}
|
|
6579
7888
|
}
|
|
6580
7889
|
async function tryReclaim(ws, cooldownMs) {
|
|
6581
|
-
const
|
|
6582
|
-
if (
|
|
7890
|
+
const auth = await authoritativeIdle(ws);
|
|
7891
|
+
if (auth === null) {
|
|
7892
|
+
const verifiedIdle = await verifyWorkspaceNotRunning(ws);
|
|
7893
|
+
if (!verifiedIdle) {
|
|
7894
|
+
blockUntil.set(ws, Date.now() + cooldownMs);
|
|
7895
|
+
return;
|
|
7896
|
+
}
|
|
7897
|
+
} else if (!auth) {
|
|
6583
7898
|
blockUntil.set(ws, Date.now() + cooldownMs);
|
|
6584
7899
|
return;
|
|
6585
7900
|
}
|
|
@@ -6609,7 +7924,7 @@
|
|
|
6609
7924
|
}
|
|
6610
7925
|
const busy = new Set(snap.running);
|
|
6611
7926
|
busy.add(snap.current);
|
|
6612
|
-
const workspaces = sidebarWorkspaces();
|
|
7927
|
+
const workspaces = await sidebarWorkspaces();
|
|
6613
7928
|
for (const ws of [...idleSince.keys(), ...blockUntil.keys()]) {
|
|
6614
7929
|
if (!workspaces.has(ws)) {
|
|
6615
7930
|
idleSince.delete(ws);
|
|
@@ -6665,24 +7980,34 @@
|
|
|
6665
7980
|
var SYNC_DEBOUNCE_MS = 150;
|
|
6666
7981
|
var SCAN_FALLBACK_MS5 = 5e3;
|
|
6667
7982
|
var ROW_SEL = "[data-task-item-key]";
|
|
6668
|
-
var MENU_SEL = '[data-testid="task-new-button"], [data-testid="automations-open"], [data-testid="plugin-store-sidebar-open"], [data-slot="command"], [data-testid="desktop-top-nav-back"]';
|
|
7983
|
+
var MENU_SEL = '[data-testid="task-new-button"], [data-testid="automations-open"], [data-testid="plugin-store-sidebar-open"], [data-testid="sidebar-search-open"], [data-slot="command"], [data-testid="desktop-top-nav-back"]';
|
|
6669
7984
|
var enabled4 = true;
|
|
6670
7985
|
var rowEl = null;
|
|
6671
7986
|
var origs = null;
|
|
6672
7987
|
var syncTimer = 0;
|
|
6673
7988
|
var widthObserver = null;
|
|
6674
7989
|
var widthObserved = null;
|
|
6675
|
-
function
|
|
6676
|
-
const
|
|
6677
|
-
|
|
6678
|
-
|
|
6679
|
-
|
|
6680
|
-
|
|
6681
|
-
|
|
6682
|
-
|
|
6683
|
-
|
|
6684
|
-
|
|
6685
|
-
|
|
7990
|
+
function findParts() {
|
|
7991
|
+
const newTask = document.querySelector('[data-testid="task-new-button"]');
|
|
7992
|
+
if (!newTask) return null;
|
|
7993
|
+
if (!isNewProjectSidebar()) {
|
|
7994
|
+
const menu = newTask.parentElement;
|
|
7995
|
+
if (!menu || !menu.querySelector('[data-testid="automations-open"]')) return null;
|
|
7996
|
+
const search2 = menu.querySelector('button [class*="lucide-search"]')?.closest("button");
|
|
7997
|
+
const auto2 = menu.querySelector('[data-testid="automations-open"]');
|
|
7998
|
+
const plugin2 = menu.querySelector('[data-testid="plugin-store-sidebar-open"]');
|
|
7999
|
+
return search2 && auto2 && plugin2 ? { newTask, search: search2, auto: auto2, plugin: plugin2, hideEls: [menu] } : null;
|
|
8000
|
+
}
|
|
8001
|
+
const search = document.querySelector('[data-testid="sidebar-search-open"]');
|
|
8002
|
+
const auto = document.querySelector('[data-testid="automations-open"]');
|
|
8003
|
+
const plugin = document.querySelector('[data-testid="plugin-store-sidebar-open"]');
|
|
8004
|
+
if (!search || !auto || !plugin) return null;
|
|
8005
|
+
const hideEls = [.../* @__PURE__ */ new Set([
|
|
8006
|
+
newTask.closest('[data-testid="sidebar-primary-navigation"]'),
|
|
8007
|
+
auto.closest('[data-testid="sidebar-primary-navigation"]'),
|
|
8008
|
+
search.closest('[data-testid="sidebar-search-toolbar"]')
|
|
8009
|
+
])].filter(Boolean);
|
|
8010
|
+
return hideEls.length ? { newTask, search, auto, plugin, hideEls } : null;
|
|
6686
8011
|
}
|
|
6687
8012
|
function nameOf(orig, nameSel, fallback) {
|
|
6688
8013
|
let name = nameSel && (orig.querySelector(nameSel)?.textContent || "").trim();
|
|
@@ -6708,6 +8033,7 @@
|
|
|
6708
8033
|
else btn.removeAttribute("data-active");
|
|
6709
8034
|
if (kind === "auto" || kind === "plugin") btn.setAttribute("aria-pressed", on ? "true" : "false");
|
|
6710
8035
|
}
|
|
8036
|
+
var lastSelectedKey = "";
|
|
6711
8037
|
function syncActive() {
|
|
6712
8038
|
if (!origs || !rowEl) return;
|
|
6713
8039
|
const auto = origs.auto.getAttribute("aria-pressed") === "true";
|
|
@@ -6717,23 +8043,37 @@
|
|
|
6717
8043
|
for (const el of document.querySelectorAll(ROW_SEL)) {
|
|
6718
8044
|
if ((el.className + "").includes("bg-selected")) {
|
|
6719
8045
|
selected = true;
|
|
8046
|
+
lastSelectedKey = el.getAttribute("data-task-item-key") || lastSelectedKey;
|
|
6720
8047
|
break;
|
|
6721
8048
|
}
|
|
6722
8049
|
}
|
|
6723
|
-
|
|
8050
|
+
let newTaskOn = false;
|
|
8051
|
+
if (!selected && lastSelectedKey) {
|
|
8052
|
+
const stillMounted = document.querySelector(`${ROW_SEL}[data-task-item-key="${CSS.escape(lastSelectedKey)}"]`);
|
|
8053
|
+
if (stillMounted) {
|
|
8054
|
+
newTaskOn = !auto && !plugin;
|
|
8055
|
+
lastSelectedKey = "";
|
|
8056
|
+
} else {
|
|
8057
|
+
const btn = rowEl?.querySelector('[data-kind="newTask"]');
|
|
8058
|
+
newTaskOn = btn ? btn.getAttribute("data-active") === "1" : false;
|
|
8059
|
+
}
|
|
8060
|
+
} else if (!selected) {
|
|
8061
|
+
newTaskOn = !auto && !plugin;
|
|
8062
|
+
}
|
|
8063
|
+
setActive("newTask", newTaskOn);
|
|
6724
8064
|
setActive("search", palette);
|
|
6725
8065
|
setActive("auto", auto);
|
|
6726
8066
|
setActive("plugin", plugin);
|
|
6727
8067
|
}
|
|
6728
8068
|
function rebuild() {
|
|
6729
|
-
const
|
|
6730
|
-
if (!menu) return false;
|
|
6731
|
-
const next = originalsOf(menu);
|
|
8069
|
+
const parts = findParts();
|
|
6732
8070
|
const navRow = document.querySelector('[data-testid="desktop-top-nav-back"]')?.parentElement;
|
|
6733
|
-
if (!
|
|
6734
|
-
if (origs && origs.
|
|
6735
|
-
|
|
6736
|
-
|
|
8071
|
+
if (!parts || !navRow) return false;
|
|
8072
|
+
if (origs && origs.hideEls[0] !== parts.hideEls[0]) {
|
|
8073
|
+
for (const el of origs.hideEls) el.classList.remove(HIDE_CLASS);
|
|
8074
|
+
}
|
|
8075
|
+
for (const el of parts.hideEls) el.classList.add(HIDE_CLASS);
|
|
8076
|
+
origs = parts;
|
|
6737
8077
|
rowEl?.remove();
|
|
6738
8078
|
navRow.classList.add("zcodepro-tb-hidden-native");
|
|
6739
8079
|
const L = t();
|
|
@@ -6748,17 +8088,17 @@
|
|
|
6748
8088
|
setTimeout(syncActive, 150);
|
|
6749
8089
|
}
|
|
6750
8090
|
});
|
|
6751
|
-
const newBtn = mk("newTask",
|
|
6752
|
-
const icon = iconOf(
|
|
8091
|
+
const newBtn = mk("newTask", parts.newTask, "span.truncate", L.tbNewTask);
|
|
8092
|
+
const icon = iconOf(parts.newTask);
|
|
6753
8093
|
if (icon) newBtn.append(icon);
|
|
6754
|
-
const searchBtn = mk("search",
|
|
6755
|
-
const sIcon = iconOf(
|
|
8094
|
+
const searchBtn = mk("search", parts.search, "span.truncate", L.tbSearch);
|
|
8095
|
+
const sIcon = iconOf(parts.search);
|
|
6756
8096
|
if (sIcon) searchBtn.append(sIcon);
|
|
6757
|
-
const autoBtn = mk("auto",
|
|
6758
|
-
const aIcon = iconOf(
|
|
8097
|
+
const autoBtn = mk("auto", parts.auto, null, L.tbAutomations);
|
|
8098
|
+
const aIcon = iconOf(parts.auto);
|
|
6759
8099
|
if (aIcon) autoBtn.append(aIcon);
|
|
6760
|
-
const pluginBtn = mk("plugin",
|
|
6761
|
-
const pIcon = iconOf(
|
|
8100
|
+
const pluginBtn = mk("plugin", parts.plugin, null, L.tbPluginStore);
|
|
8101
|
+
const pIcon = iconOf(parts.plugin);
|
|
6762
8102
|
if (pIcon) pluginBtn.append(pIcon);
|
|
6763
8103
|
rowEl = h("div", { class: "zcodepro-tb-row" }, newBtn, searchBtn, autoBtn, pluginBtn);
|
|
6764
8104
|
const updBtn = [...navRow.querySelectorAll("button")].find((b) => /bg-(success|emerald)/.test(b.className || ""));
|
|
@@ -6773,7 +8113,7 @@
|
|
|
6773
8113
|
}
|
|
6774
8114
|
var NARROW_SIDEBAR_PX = 260;
|
|
6775
8115
|
function sidebarTooNarrow() {
|
|
6776
|
-
const scroll = document.querySelector(".flex.flex-1.min-h-0.flex-col.gap-3.overflow-y-auto");
|
|
8116
|
+
const scroll = document.querySelector(".flex.flex-1.min-h-0.flex-col.gap-3.overflow-y-auto") || document.querySelector("aside .min-h-0.flex-1.overflow-y-auto");
|
|
6777
8117
|
if (!scroll) return false;
|
|
6778
8118
|
if (!widthObserver) widthObserver = new ResizeObserver(() => scheduleSync());
|
|
6779
8119
|
if (widthObserved !== scroll) {
|
|
@@ -6785,18 +8125,18 @@
|
|
|
6785
8125
|
}
|
|
6786
8126
|
function sync() {
|
|
6787
8127
|
if (!enabled4) return;
|
|
6788
|
-
const
|
|
6789
|
-
if (!
|
|
8128
|
+
const parts = findParts();
|
|
8129
|
+
if (!parts) {
|
|
6790
8130
|
if (rowEl) rowEl.style.display = "none";
|
|
6791
8131
|
return;
|
|
6792
8132
|
}
|
|
6793
8133
|
if (sidebarCollapsed() || sidebarTooNarrow()) {
|
|
6794
8134
|
if (rowEl) rowEl.style.display = "none";
|
|
6795
|
-
|
|
8135
|
+
for (const el of parts.hideEls) el.classList.remove(HIDE_CLASS);
|
|
6796
8136
|
document.querySelectorAll(".zcodepro-tb-hidden-native").forEach((el) => el.classList.remove("zcodepro-tb-hidden-native"));
|
|
6797
8137
|
return;
|
|
6798
8138
|
}
|
|
6799
|
-
const alive = origs && origs.
|
|
8139
|
+
const alive = origs && origs.hideEls[0] === parts.hideEls[0] && origs.newTask.isConnected && origs.search.isConnected && origs.auto.isConnected && origs.plugin.isConnected && rowEl && rowEl.isConnected;
|
|
6800
8140
|
if (!alive && !rebuild()) {
|
|
6801
8141
|
if (rowEl) rowEl.style.display = "none";
|
|
6802
8142
|
setTimeout(scheduleSync, 400);
|
|
@@ -6805,7 +8145,7 @@
|
|
|
6805
8145
|
}
|
|
6806
8146
|
const navRow = document.querySelector('[data-testid="desktop-top-nav-back"]')?.parentElement;
|
|
6807
8147
|
if (navRow) navRow.classList.add("zcodepro-tb-hidden-native");
|
|
6808
|
-
|
|
8148
|
+
for (const el of parts.hideEls) el.classList.add(HIDE_CLASS);
|
|
6809
8149
|
if (rowEl) rowEl.style.display = "";
|
|
6810
8150
|
syncActive();
|
|
6811
8151
|
}
|
|
@@ -6839,12 +8179,12 @@
|
|
|
6839
8179
|
rowEl?.remove();
|
|
6840
8180
|
rowEl = null;
|
|
6841
8181
|
if (origs) {
|
|
6842
|
-
origs.
|
|
8182
|
+
for (const el of origs.hideEls) el.classList.remove(HIDE_CLASS);
|
|
6843
8183
|
document.querySelectorAll(".zcodepro-tb-hidden-native").forEach((el) => el.classList.remove("zcodepro-tb-hidden-native"));
|
|
6844
8184
|
origs = null;
|
|
6845
8185
|
}
|
|
6846
8186
|
}
|
|
6847
|
-
async function
|
|
8187
|
+
async function refreshConfig2() {
|
|
6848
8188
|
const cfg = await getConfig(true).catch(() => null);
|
|
6849
8189
|
enabled4 = !cfg || !cfg.features || cfg.features.toolbarIcons !== false;
|
|
6850
8190
|
if (enabled4) sync();
|
|
@@ -6853,9 +8193,9 @@
|
|
|
6853
8193
|
function startToolbarIcons() {
|
|
6854
8194
|
ensureStyle();
|
|
6855
8195
|
window.addEventListener("zcodepro:config-changed", () => {
|
|
6856
|
-
void
|
|
8196
|
+
void refreshConfig2();
|
|
6857
8197
|
});
|
|
6858
|
-
void
|
|
8198
|
+
void refreshConfig2();
|
|
6859
8199
|
new MutationObserver((muts) => {
|
|
6860
8200
|
if (relevantMutations(muts)) scheduleSync();
|
|
6861
8201
|
}).observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ["class", "aria-pressed"] });
|
|
@@ -6877,8 +8217,8 @@
|
|
|
6877
8217
|
var syncTimer2 = 0;
|
|
6878
8218
|
function findPinnedHeader() {
|
|
6879
8219
|
for (const h3 of document.querySelectorAll("h3")) {
|
|
6880
|
-
const
|
|
6881
|
-
if (
|
|
8220
|
+
const list = h3.nextElementSibling;
|
|
8221
|
+
if (list && list.querySelector("li[data-task-item-key]")) return h3;
|
|
6882
8222
|
}
|
|
6883
8223
|
return null;
|
|
6884
8224
|
}
|
|
@@ -6974,7 +8314,7 @@
|
|
|
6974
8314
|
h3.parentElement?.classList.remove(COLLAPSED_CLASS);
|
|
6975
8315
|
}
|
|
6976
8316
|
}
|
|
6977
|
-
async function
|
|
8317
|
+
async function refreshConfig3() {
|
|
6978
8318
|
const cfg = await getConfig(true).catch(() => null);
|
|
6979
8319
|
enabled5 = !cfg || !cfg.features || cfg.features.pinnedCollapse !== false;
|
|
6980
8320
|
if (enabled5) sync2();
|
|
@@ -6983,9 +8323,9 @@
|
|
|
6983
8323
|
function startPinnedCollapse() {
|
|
6984
8324
|
ensureStyle();
|
|
6985
8325
|
window.addEventListener("zcodepro:config-changed", () => {
|
|
6986
|
-
void
|
|
8326
|
+
void refreshConfig3();
|
|
6987
8327
|
});
|
|
6988
|
-
void
|
|
8328
|
+
void refreshConfig3();
|
|
6989
8329
|
new MutationObserver((muts) => {
|
|
6990
8330
|
if (relevantMutations2(muts)) scheduleSync2();
|
|
6991
8331
|
}).observe(document.body, { childList: true, subtree: true });
|
|
@@ -7060,6 +8400,10 @@
|
|
|
7060
8400
|
void startAliasWatcher();
|
|
7061
8401
|
} catch {
|
|
7062
8402
|
}
|
|
8403
|
+
try {
|
|
8404
|
+
startAliasMigrationWatcher();
|
|
8405
|
+
} catch {
|
|
8406
|
+
}
|
|
7063
8407
|
try {
|
|
7064
8408
|
startTaskOrderWatcher();
|
|
7065
8409
|
} catch {
|
|
@@ -7080,10 +8424,6 @@
|
|
|
7080
8424
|
startImageMenu();
|
|
7081
8425
|
} catch {
|
|
7082
8426
|
}
|
|
7083
|
-
try {
|
|
7084
|
-
startPinnedExpandSuppression();
|
|
7085
|
-
} catch {
|
|
7086
|
-
}
|
|
7087
8427
|
try {
|
|
7088
8428
|
startWsRunningSpin();
|
|
7089
8429
|
} catch {
|