zcode-pro 0.20.3 → 1.0.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 +8 -5
- package/README.md +7 -4
- package/dist/inject.js +1413 -440
- package/package.json +1 -1
- package/src/host/helper.mjs +147 -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 +101 -18
- 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/session-switch.js +6 -2
- package/src/inject/features/settings-dialog.js +88 -59
- 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 +384 -27
- package/src/inject/index.js +3 -2
- package/src/inject/ui.js +20 -11
- package/src/inject/features/pinned-expand.js +0 -142
package/dist/inject.js
CHANGED
|
@@ -30,6 +30,35 @@
|
|
|
30
30
|
function clearConfigCache() {
|
|
31
31
|
configCache = { value: null, at: 0 };
|
|
32
32
|
}
|
|
33
|
+
function zcodeAppVersion() {
|
|
34
|
+
const v = liveBoot().zcodeVersion;
|
|
35
|
+
return typeof v === "string" && v ? v : "";
|
|
36
|
+
}
|
|
37
|
+
function zcodeVersionGte(version, major, minor, patch = 0) {
|
|
38
|
+
const m = String(version || "").match(/^(\d+)\.(\d+)\.(\d+)/);
|
|
39
|
+
if (!m) return false;
|
|
40
|
+
const a = Number(m[1]), b = Number(m[2]), c = Number(m[3]);
|
|
41
|
+
return a > major || a === major && (b > minor || b === minor && c >= patch);
|
|
42
|
+
}
|
|
43
|
+
function officialRenameSupported() {
|
|
44
|
+
return zcodeVersionGte(zcodeAppVersion(), 3, 16, 1);
|
|
45
|
+
}
|
|
46
|
+
var newSidebarCached = false;
|
|
47
|
+
function isNewProjectSidebar() {
|
|
48
|
+
if (newSidebarCached) return true;
|
|
49
|
+
if (officialRenameSupported()) {
|
|
50
|
+
newSidebarCached = true;
|
|
51
|
+
return true;
|
|
52
|
+
}
|
|
53
|
+
try {
|
|
54
|
+
if (document.querySelector("section[data-project-id]")) {
|
|
55
|
+
newSidebarCached = true;
|
|
56
|
+
return true;
|
|
57
|
+
}
|
|
58
|
+
} catch {
|
|
59
|
+
}
|
|
60
|
+
return false;
|
|
61
|
+
}
|
|
33
62
|
var zh = {
|
|
34
63
|
settingsTitle: "ZCode Pro",
|
|
35
64
|
tabFeatures: "\u529F\u80FD",
|
|
@@ -76,7 +105,7 @@
|
|
|
76
105
|
syncRecLink: "\u575A\u679C\u4E91 WebDAV",
|
|
77
106
|
syncRecSuffix: "\uFF1A\u767B\u5F55\u4E0E\u5BC6\u7801\u586B\u201C\u5E94\u7528\u5BC6\u7801\u201D\uFF0C\u4E0D\u662F\u8D26\u53F7\u5BC6\u7801\u3002",
|
|
78
107
|
syncIncludeZcp: "ZCode Pro \u8BBE\u7F6E",
|
|
79
|
-
syncIncludeZcpDesc: "\u529F\u80FD\u5F00\u5173\u3001\u6837\u5F0F\u8C03\u6574\
|
|
108
|
+
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
109
|
syncIncludeModel: "\u6A21\u578B\u8BBE\u7F6E",
|
|
81
110
|
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
111
|
syncUpload: "\u4E0A\u4F20\u5230\u4E91\u7AEF",
|
|
@@ -176,8 +205,8 @@
|
|
|
176
205
|
titleGenTesting: "\u751F\u6210\u4E2D\u2026",
|
|
177
206
|
titleGenTestOk: "\u751F\u6210\u7ED3\u679C\uFF1A",
|
|
178
207
|
titleGenTestFailed: "\u751F\u6210\u5931\u8D25",
|
|
179
|
-
featureWsRunning: "\u6298\u53E0\
|
|
180
|
-
featureWsRunningDesc: "\
|
|
208
|
+
featureWsRunning: "\u6298\u53E0\u65F6\u4EFB\u52A1\u8FD0\u884C\u4E2D\u63D0\u793A",
|
|
209
|
+
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\uFF1B3.16.1 \u4E4B\u524D\u6BCF 60 \u79D2\u4F1A\u5728\u540E\u53F0\u77ED\u6682\u5C55\u5F00\u9879\u76EE\u590D\u6838\u518D\u6536\u8D77\u3002",
|
|
181
210
|
tabPerformance: "\u6027\u80FD",
|
|
182
211
|
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
212
|
featureIdleReclaim: "\u7A7A\u95F2\u9879\u76EE\u5185\u5B58\u56DE\u6536",
|
|
@@ -217,17 +246,16 @@
|
|
|
217
246
|
imageCopied: "\u56FE\u7247\u5DF2\u590D\u5236\u5230\u526A\u8D34\u677F",
|
|
218
247
|
imageCopyFailed: "\u590D\u5236\u56FE\u7247\u5931\u8D25",
|
|
219
248
|
openFolderItem: "\u6253\u5F00\u6587\u4EF6\u5939",
|
|
249
|
+
openFolderPrimary: "\u4E3B\u76EE\u5F55",
|
|
220
250
|
copyPathItem: "\u590D\u5236\u8DEF\u5F84",
|
|
221
251
|
pathCopied: "\u8DEF\u5F84\u5DF2\u590D\u5236\u5230\u526A\u8D34\u677F",
|
|
222
252
|
pathCopyFailed: "\u590D\u5236\u8DEF\u5F84\u5931\u8D25",
|
|
223
253
|
fileOpenDefault: "\u9ED8\u8BA4\u5E94\u7528\u6253\u5F00",
|
|
224
254
|
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",
|
|
255
|
+
featureAutoUpdatePlugins: "\u81EA\u52A8\u66F4\u65B0",
|
|
256
|
+
featureAutoUpdatePluginsRepo: "duanluan/zcode-plugins",
|
|
257
|
+
featureAutoUpdatePluginsDesc: "",
|
|
258
|
+
pluginsCheckNow: "\u68C0\u67E5\u66F4\u65B0",
|
|
231
259
|
pluginsUpdating: "\u6B63\u5728\u66F4\u65B0\u63D2\u4EF6\u2026",
|
|
232
260
|
pluginsUpToDate: "\u63D2\u4EF6\u5DF2\u662F\u6700\u65B0",
|
|
233
261
|
pluginsUpdatesFound: "{n} \u4E2A\u63D2\u4EF6\u53EF\u66F4\u65B0",
|
|
@@ -305,6 +333,8 @@
|
|
|
305
333
|
hrUsageNone: "\u5F53\u524D\u6CA1\u6709\u8D70 headroom \u7684\u4F9B\u5E94\u5546\uFF0C\u672A\u5207\u6362",
|
|
306
334
|
headroomLoadFailed: "\u8BFB\u53D6 Headroom \u914D\u7F6E\u5931\u8D25",
|
|
307
335
|
headroomStatusTitle: "\u8FD0\u884C\u72B6\u6001",
|
|
336
|
+
hrInstRunning: "\u8FD0\u884C\u4E2D",
|
|
337
|
+
hrInstStopped: "\u672A\u8FD0\u884C",
|
|
308
338
|
headroomStatusLoadFailed: "\u8BFB\u53D6\u8FD0\u884C\u72B6\u6001\u5931\u8D25",
|
|
309
339
|
headroomProxyUp: "\u4EE3\u7406\u8FD0\u884C\u4E2D",
|
|
310
340
|
headroomProxyDown: "\u4EE3\u7406\u672A\u8FD0\u884C",
|
|
@@ -370,6 +400,30 @@
|
|
|
370
400
|
aliasSaved: "\u522B\u540D\u5DF2\u66F4\u65B0",
|
|
371
401
|
aliasCleared: "\u5DF2\u6062\u590D\u771F\u5B9E\u540D\u79F0",
|
|
372
402
|
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",
|
|
403
|
+
featureProjectMenuDescNew: "\u9879\u76EE\u201C\u66F4\u591A\u201D\u83DC\u5355\u4E2D\u7684\u5207\u6362\u6587\u4EF6\u5939\u3001\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",
|
|
404
|
+
aliasMigrateTitle: "\u8FC1\u79FB\u9879\u76EE\u522B\u540D",
|
|
405
|
+
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",
|
|
406
|
+
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",
|
|
407
|
+
aliasMigrateStateDone: "\u5DF2\u8FC1\u79FB",
|
|
408
|
+
aliasMigrateStateMerged: "\u5DF2\u5E76\u5165\u300C{name}\u300D",
|
|
409
|
+
aliasMigrateStateDeleted: "\u9879\u76EE\u5DF2\u5220\u9664",
|
|
410
|
+
aliasMigrateStateMissing: "\u672C\u673A\u4E0D\u5B58\u5728",
|
|
411
|
+
aliasMigrateStateRenamed: "\u9879\u76EE\u5DF2\u91CD\u547D\u540D",
|
|
412
|
+
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",
|
|
413
|
+
aliasMigrateClearDead: "\u6E05\u9664\u5931\u6548\u6761\u76EE",
|
|
414
|
+
aliasMigrateDeadCleared: "\u5DF2\u6E05\u9664 {n} \u6761\u5931\u6548\u522B\u540D",
|
|
415
|
+
aliasMigrateDeadClearFailed: "\u90E8\u5206\u5931\u6548\u522B\u540D\u672A\u80FD\u6E05\u9664\uFF0C\u8BF7\u91CD\u8BD5",
|
|
416
|
+
aliasMigrateGo: "\u8FC1\u79FB\u6240\u9009",
|
|
417
|
+
aliasMigrateRunning: "\u8FC1\u79FB\u4E2D\u2026",
|
|
418
|
+
aliasMigrateProgress: "\u6B63\u5728\u8FC1\u79FB {i}/{n}\uFF1A{name}",
|
|
419
|
+
aliasMigrateStateFailed: "\u5931\u8D25",
|
|
420
|
+
aliasMigrateSkip: "\u6682\u4E0D\u8FC1\u79FB",
|
|
421
|
+
aliasMigrateDone: "\u5DF2\u8FC1\u79FB {n} \u4E2A\u522B\u540D",
|
|
422
|
+
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",
|
|
423
|
+
aliasMigrateAllFailed: "\u522B\u540D\u8FC1\u79FB\u672A\u6210\u529F\uFF0C\u53EF\u7A0D\u540E\u5728 ZCode Pro \u8BBE\u7F6E\u4E2D\u91CD\u8BD5",
|
|
424
|
+
aliasMigrateCardName: "\u522B\u540D\u8FC1\u79FB",
|
|
425
|
+
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",
|
|
426
|
+
aliasMigrateRun: "\u8FC1\u79FB",
|
|
373
427
|
taskOrderSaved: "\u987A\u5E8F\u5DF2\u66F4\u65B0",
|
|
374
428
|
qqGroupTitle: "QQ \u7FA4\uFF1A428403354",
|
|
375
429
|
qqGroupDesc: "\u95EE\u9898\u53CD\u9988\u4E0E\u4EA4\u6D41",
|
|
@@ -441,7 +495,7 @@
|
|
|
441
495
|
syncRecLink: "Jianguoyun WebDAV",
|
|
442
496
|
syncRecSuffix: " \u2014 use the app password, not your account password.",
|
|
443
497
|
syncIncludeZcp: "ZCode Pro settings",
|
|
444
|
-
syncIncludeZcpDesc: "Feature toggles, style adjustments
|
|
498
|
+
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
499
|
syncIncludeModel: "Model settings",
|
|
446
500
|
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
501
|
syncUpload: "Upload",
|
|
@@ -541,8 +595,8 @@
|
|
|
541
595
|
titleGenTesting: "Generating\u2026",
|
|
542
596
|
titleGenTestOk: "Result: ",
|
|
543
597
|
titleGenTestFailed: "Generation failed",
|
|
544
|
-
featureWsRunning: "Running indicator
|
|
545
|
-
featureWsRunningDesc: "
|
|
598
|
+
featureWsRunning: "Running indicator when collapsed",
|
|
599
|
+
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. Before ZCode 3.16.1 the project is briefly re-expanded in the background every 60 s to re-check.",
|
|
546
600
|
tabPerformance: "Performance",
|
|
547
601
|
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
602
|
featureIdleReclaim: "Idle project memory reclaim",
|
|
@@ -582,17 +636,16 @@
|
|
|
582
636
|
imageCopied: "Image copied to the clipboard.",
|
|
583
637
|
imageCopyFailed: "Failed to copy the image.",
|
|
584
638
|
openFolderItem: "Open folder",
|
|
639
|
+
openFolderPrimary: "primary",
|
|
585
640
|
copyPathItem: "Copy path",
|
|
586
641
|
pathCopied: "Path copied to the clipboard.",
|
|
587
642
|
pathCopyFailed: "Failed to copy the path.",
|
|
588
643
|
fileOpenDefault: "Open with default app",
|
|
589
644
|
fileReveal: "Reveal in file manager",
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
pluginsUpdateTitle: "Plugin updates \xB7 zcode-plugins",
|
|
595
|
-
pluginsCheckNow: "Check & update",
|
|
645
|
+
featureAutoUpdatePlugins: "Auto-update",
|
|
646
|
+
featureAutoUpdatePluginsRepo: "duanluan/zcode-plugins",
|
|
647
|
+
featureAutoUpdatePluginsDesc: "",
|
|
648
|
+
pluginsCheckNow: "Check for updates",
|
|
596
649
|
pluginsUpdating: "Updating plugins\u2026",
|
|
597
650
|
pluginsUpToDate: "Plugins are up to date",
|
|
598
651
|
pluginsUpdatesFound: "{n} plugin(s) can be updated",
|
|
@@ -670,6 +723,8 @@
|
|
|
670
723
|
hrUsageNone: "No providers route through headroom; nothing changed",
|
|
671
724
|
headroomLoadFailed: "Failed to load the Headroom config",
|
|
672
725
|
headroomStatusTitle: "Status",
|
|
726
|
+
hrInstRunning: "running",
|
|
727
|
+
hrInstStopped: "down",
|
|
673
728
|
headroomStatusLoadFailed: "Failed to load the status",
|
|
674
729
|
headroomProxyUp: "Proxy running",
|
|
675
730
|
headroomProxyDown: "Proxy down",
|
|
@@ -735,6 +790,30 @@
|
|
|
735
790
|
aliasSaved: "Alias updated.",
|
|
736
791
|
aliasCleared: "Real name restored.",
|
|
737
792
|
aliasHint: "The directory name on disk is unchanged: terminals, file managers and other path-based UI still show the real name.",
|
|
793
|
+
featureProjectMenuDescNew: 'Switch folder, 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.',
|
|
794
|
+
aliasMigrateTitle: "Migrate project aliases",
|
|
795
|
+
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.',
|
|
796
|
+
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.',
|
|
797
|
+
aliasMigrateStateDone: "Migrated",
|
|
798
|
+
aliasMigrateStateMerged: 'Merged into "{name}"',
|
|
799
|
+
aliasMigrateStateDeleted: "Project deleted",
|
|
800
|
+
aliasMigrateStateMissing: "Not on this machine",
|
|
801
|
+
aliasMigrateStateRenamed: "Project renamed",
|
|
802
|
+
aliasMigrateDeadSummary: "{n} stale entries (not on this machine / project deleted \u2014 usually old-machine paths from settings sync)",
|
|
803
|
+
aliasMigrateClearDead: "Clear stale entries",
|
|
804
|
+
aliasMigrateDeadCleared: "Removed {n} stale alias(es)",
|
|
805
|
+
aliasMigrateDeadClearFailed: "Some stale aliases could not be removed; please retry",
|
|
806
|
+
aliasMigrateGo: "Migrate selected",
|
|
807
|
+
aliasMigrateRunning: "Migrating\u2026",
|
|
808
|
+
aliasMigrateProgress: "Migrating {i}/{n}: {name}",
|
|
809
|
+
aliasMigrateStateFailed: "Failed",
|
|
810
|
+
aliasMigrateSkip: "Not now",
|
|
811
|
+
aliasMigrateDone: "Migrated {n} alias(es)",
|
|
812
|
+
aliasMigratePartial: "{n} migrated, {m} failed; retry the rest later in ZCode Pro settings",
|
|
813
|
+
aliasMigrateAllFailed: "Alias migration failed; retry later in ZCode Pro settings",
|
|
814
|
+
aliasMigrateCardName: "Alias migration",
|
|
815
|
+
aliasMigrateCardDesc: "Project renaming is built in now; {n} custom alias(es) are not migrated yet.",
|
|
816
|
+
aliasMigrateRun: "Migrate",
|
|
738
817
|
taskOrderSaved: "Order updated.",
|
|
739
818
|
qqGroupTitle: "QQ group: 428403354",
|
|
740
819
|
qqGroupDesc: "Feedback & discussion",
|
|
@@ -918,7 +997,7 @@
|
|
|
918
997
|
var overlayClassBare = "fixed inset-0 isolate z-50 flex items-center justify-center duration-100 p-4 platform-linux-desktop:top-12";
|
|
919
998
|
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
999
|
var dialogStack = [];
|
|
921
|
-
function openDialog({ title, description, onMount, onClose, width = "sm:max-w-md", overlay = "dim", draggable = false, posKey = "", dismissOnOutside = true, bodyClass = "" }) {
|
|
1000
|
+
function openDialog({ title, description, onMount, onClose, width = "sm:max-w-md", overlay = "dim", draggable = false, posKey = "", dismissOnOutside = true, bodyClass = "", closable = false }) {
|
|
922
1001
|
const L = t();
|
|
923
1002
|
const prevActive = document.activeElement;
|
|
924
1003
|
let cleanupDrag = null;
|
|
@@ -958,8 +1037,25 @@
|
|
|
958
1037
|
content.style.pointerEvents = "auto";
|
|
959
1038
|
}
|
|
960
1039
|
const titleEl = h("h2", { class: "text-lg font-semibold leading-none tracking-tight text-foreground" }, title);
|
|
961
|
-
|
|
1040
|
+
const titleRow = closable ? h(
|
|
1041
|
+
"div",
|
|
1042
|
+
{ class: "flex items-start justify-between gap-2" },
|
|
962
1043
|
titleEl,
|
|
1044
|
+
h("button", {
|
|
1045
|
+
type: "button",
|
|
1046
|
+
class: "zcodepro-close",
|
|
1047
|
+
title: L.close,
|
|
1048
|
+
"aria-label": L.close,
|
|
1049
|
+
onMousedown: (e) => {
|
|
1050
|
+
e.stopPropagation();
|
|
1051
|
+
},
|
|
1052
|
+
onClick: () => {
|
|
1053
|
+
close();
|
|
1054
|
+
}
|
|
1055
|
+
}, "\u2715")
|
|
1056
|
+
) : titleEl;
|
|
1057
|
+
content.append(
|
|
1058
|
+
titleRow,
|
|
963
1059
|
...description ? [h("p", { class: "mt-2 text-ui-sm/relaxed text-foreground-subtle" }, description)] : []
|
|
964
1060
|
);
|
|
965
1061
|
const body = h("div", { class: "zcodepro-dialog-body " + (bodyClass || "mt-4") });
|
|
@@ -1154,13 +1250,13 @@
|
|
|
1154
1250
|
}
|
|
1155
1251
|
function unitField({ value = null, fallback = { value: 100, unit: "%" }, step = { px: 10, "%": 1 }, onCommit }) {
|
|
1156
1252
|
const RANGES = { px: [320, 3840], "%": [20, 100] };
|
|
1157
|
-
const
|
|
1253
|
+
const norm3 = (v) => {
|
|
1158
1254
|
if (!v || !RANGES[v.unit]) return null;
|
|
1159
1255
|
const [min, max] = RANGES[v.unit];
|
|
1160
1256
|
const n = v.unit === "px" ? Math.round(v.value) : Math.round(v.value * 10) / 10;
|
|
1161
1257
|
return Number.isFinite(n) ? { value: Math.min(max, Math.max(min, n)), unit: v.unit } : null;
|
|
1162
1258
|
};
|
|
1163
|
-
let current2 =
|
|
1259
|
+
let current2 = norm3(value) || norm3(fallback) || { value: 100, unit: "%" };
|
|
1164
1260
|
const input = h("input", {
|
|
1165
1261
|
type: "text",
|
|
1166
1262
|
inputmode: "decimal",
|
|
@@ -1171,7 +1267,7 @@
|
|
|
1171
1267
|
input.value = `${current2.value}${current2.unit}`;
|
|
1172
1268
|
};
|
|
1173
1269
|
const commit = (v) => {
|
|
1174
|
-
const next =
|
|
1270
|
+
const next = norm3(v);
|
|
1175
1271
|
if (!next || next.value === current2.value && next.unit === current2.unit) {
|
|
1176
1272
|
display();
|
|
1177
1273
|
return;
|
|
@@ -1208,7 +1304,7 @@
|
|
|
1208
1304
|
return {
|
|
1209
1305
|
el: input,
|
|
1210
1306
|
reset() {
|
|
1211
|
-
current2 =
|
|
1307
|
+
current2 = norm3(fallback) || current2;
|
|
1212
1308
|
display();
|
|
1213
1309
|
},
|
|
1214
1310
|
get() {
|
|
@@ -1247,7 +1343,7 @@
|
|
|
1247
1343
|
"div",
|
|
1248
1344
|
{ class: "min-w-0 flex-1" },
|
|
1249
1345
|
h("div", { class: "text-ui-sm font-medium text-foreground" }, name),
|
|
1250
|
-
|
|
1346
|
+
h("div", { class: "mt-0.5 text-ui-xs/relaxed text-foreground-subtle", "data-zcodepro-row-desc": "" }, desc ?? "")
|
|
1251
1347
|
),
|
|
1252
1348
|
...extraEl ? [extraEl] : [],
|
|
1253
1349
|
h("button", {
|
|
@@ -1525,13 +1621,9 @@
|
|
|
1525
1621
|
.zcodepro-imgmenu-item:hover {
|
|
1526
1622
|
background-color: var(--color-accent, color-mix(in oklab, var(--color-foreground, #888) 10%, transparent));
|
|
1527
1623
|
}
|
|
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
|
-
}
|
|
1624
|
+
/* \u6298\u53E0\u9879\u76EE\u8FD0\u884C\u63D0\u793A\uFF1Afolder \u56FE\u6807\u8BA9\u4F4D\u7ED9 loader\uFF08loader \u7531\u811A\u672C\u63D2\u5165\uFF0C
|
|
1625
|
+
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 */
|
|
1626
|
+
span.zcodepro-ws-running svg:not(.zcodepro-ws-loader) { display: none !important; }
|
|
1535
1627
|
/* \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
1628
|
.zcodepro-ws-frozen {
|
|
1537
1629
|
position: fixed;
|
|
@@ -1645,12 +1737,82 @@
|
|
|
1645
1737
|
}
|
|
1646
1738
|
.zcodepro-pin-head:hover .zcodepro-pin-chevron svg { opacity: 1; }
|
|
1647
1739
|
.zcodepro-pin-collapsed .zcodepro-pin-chevron svg { transform: rotate(-90deg); }
|
|
1648
|
-
.zcodepro-pin-collapsed > ul { display: none !important; }
|
|
1740
|
+
.zcodepro-pin-collapsed > :is(ul, div):has(li[data-task-item-key]) { display: none !important; }
|
|
1649
1741
|
/* \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
1742
|
.zcodepro-pin-collapsed .zcodepro-pin-head { padding-bottom: 0; }
|
|
1651
1743
|
`));
|
|
1652
1744
|
}
|
|
1653
1745
|
|
|
1746
|
+
// src/inject/features/copy-path.js
|
|
1747
|
+
async function appendCopyPathItem(menu, anchorItem, project) {
|
|
1748
|
+
if (menu.querySelector('[data-zcodepro-item="copy-path"]')) return;
|
|
1749
|
+
const L = t();
|
|
1750
|
+
const item = anchorItem.cloneNode(true);
|
|
1751
|
+
item.removeAttribute("data-testid");
|
|
1752
|
+
item.removeAttribute("data-highlighted");
|
|
1753
|
+
item.setAttribute("data-zcodepro-item", "copy-path");
|
|
1754
|
+
for (const child of [...item.childNodes]) child.remove();
|
|
1755
|
+
const origIcon = anchorItem.querySelector("svg");
|
|
1756
|
+
const iconClass = origIcon ? origIcon.getAttribute("class") : "h-3.5 w-3.5";
|
|
1757
|
+
item.append(hCopyIcon(iconClass), document.createTextNode(L.copyPathItem));
|
|
1758
|
+
item.addEventListener("mouseenter", () => {
|
|
1759
|
+
for (const el of menu.querySelectorAll('[role="menuitem"]')) el.removeAttribute("data-highlighted");
|
|
1760
|
+
item.setAttribute("data-highlighted", "");
|
|
1761
|
+
});
|
|
1762
|
+
item.addEventListener("mouseleave", () => item.removeAttribute("data-highlighted"));
|
|
1763
|
+
item.addEventListener("click", () => {
|
|
1764
|
+
closeRadixMenu(menu);
|
|
1765
|
+
void copyText(project.path);
|
|
1766
|
+
});
|
|
1767
|
+
anchorItem.before(item);
|
|
1768
|
+
}
|
|
1769
|
+
async function copyText(text) {
|
|
1770
|
+
const L = t();
|
|
1771
|
+
if (await copyToClipboard(text)) showToast(L.pathCopied);
|
|
1772
|
+
else showToast(L.pathCopyFailed, "error");
|
|
1773
|
+
}
|
|
1774
|
+
async function copyToClipboard(text) {
|
|
1775
|
+
try {
|
|
1776
|
+
await navigator.clipboard.writeText(text);
|
|
1777
|
+
return true;
|
|
1778
|
+
} catch {
|
|
1779
|
+
return copyViaHiddenInput(text);
|
|
1780
|
+
}
|
|
1781
|
+
}
|
|
1782
|
+
function copyViaHiddenInput(text) {
|
|
1783
|
+
try {
|
|
1784
|
+
const input = h("input", { type: "text", style: "position:fixed;left:-9999px;top:0;opacity:0" });
|
|
1785
|
+
input.value = text;
|
|
1786
|
+
document.body.append(input);
|
|
1787
|
+
input.select();
|
|
1788
|
+
const ok = document.execCommand("copy");
|
|
1789
|
+
input.remove();
|
|
1790
|
+
return ok;
|
|
1791
|
+
} catch {
|
|
1792
|
+
return false;
|
|
1793
|
+
}
|
|
1794
|
+
}
|
|
1795
|
+
function hCopyIcon(cls) {
|
|
1796
|
+
const ns = "http://www.w3.org/2000/svg";
|
|
1797
|
+
const svg = document.createElementNS(ns, "svg");
|
|
1798
|
+
svg.setAttribute("viewBox", "0 0 24 24");
|
|
1799
|
+
svg.setAttribute("fill", "none");
|
|
1800
|
+
svg.setAttribute("stroke", "currentColor");
|
|
1801
|
+
svg.setAttribute("stroke-width", "2");
|
|
1802
|
+
svg.setAttribute("stroke-linecap", "round");
|
|
1803
|
+
svg.setAttribute("stroke-linejoin", "round");
|
|
1804
|
+
svg.setAttribute("class", cls);
|
|
1805
|
+
for (const d of [
|
|
1806
|
+
"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",
|
|
1807
|
+
"M4 16c-1.1 0-2-.9-2-2V4a2 2 0 0 1 2-2h12a2 2 0 0 1 2 2"
|
|
1808
|
+
]) {
|
|
1809
|
+
const p = document.createElementNS(ns, "path");
|
|
1810
|
+
p.setAttribute("d", d);
|
|
1811
|
+
svg.append(p);
|
|
1812
|
+
}
|
|
1813
|
+
return svg;
|
|
1814
|
+
}
|
|
1815
|
+
|
|
1654
1816
|
// src/inject/features/alias.js
|
|
1655
1817
|
var norm = (p) => String(p || "").replace(/[\\/]+$/, "");
|
|
1656
1818
|
var basenameOf = (p) => norm(p).split(/[\\/]/).pop() || "";
|
|
@@ -1679,6 +1841,7 @@
|
|
|
1679
1841
|
return false;
|
|
1680
1842
|
}
|
|
1681
1843
|
async function startAliasWatcher() {
|
|
1844
|
+
if (isNewProjectSidebar()) return;
|
|
1682
1845
|
await syncFromConfig();
|
|
1683
1846
|
if (observer) return;
|
|
1684
1847
|
observer = new MutationObserver((muts) => {
|
|
@@ -2053,76 +2216,6 @@
|
|
|
2053
2216
|
return svg;
|
|
2054
2217
|
}
|
|
2055
2218
|
|
|
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
2219
|
// src/inject/features/project-menu.js
|
|
2127
2220
|
var REMOVE_TEXTS = ["\u79FB\u9664", "Remove"];
|
|
2128
2221
|
function extractPathFromTestId2(testid) {
|
|
@@ -2131,37 +2224,213 @@
|
|
|
2131
2224
|
m = testid.match(/[-:=,|]([A-Za-z]:\\.*)$/);
|
|
2132
2225
|
return m ? m[1] : null;
|
|
2133
2226
|
}
|
|
2134
|
-
function
|
|
2135
|
-
|
|
2227
|
+
function openMenuProjectRow() {
|
|
2228
|
+
const trigger = document.querySelector(
|
|
2229
|
+
'[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"]'
|
|
2230
|
+
);
|
|
2231
|
+
const row = trigger ? trigger.closest("section[data-project-id]") : null;
|
|
2232
|
+
if (!row) return null;
|
|
2233
|
+
const host = row.getAttribute("data-project-host");
|
|
2234
|
+
return host === null || host === "local" ? row : null;
|
|
2136
2235
|
}
|
|
2137
2236
|
async function resolveProjectPath(removeItem) {
|
|
2138
|
-
const
|
|
2139
|
-
const extracted = extractPathFromTestId2(testid);
|
|
2237
|
+
const extracted = extractPathFromTestId2(removeItem.getAttribute("data-testid") || "");
|
|
2140
2238
|
if (!extracted) return null;
|
|
2141
2239
|
const res = await rpc("/projects");
|
|
2142
2240
|
if (res.ok && Array.isArray(res.projects)) {
|
|
2143
|
-
const
|
|
2144
|
-
const hit = res.projects.find((p) =>
|
|
2241
|
+
const norm3 = (p) => String(p).replace(/[\\/]+$/, "");
|
|
2242
|
+
const hit = res.projects.find((p) => norm3(p.path) === norm3(extracted));
|
|
2145
2243
|
if (hit) return hit;
|
|
2146
2244
|
}
|
|
2147
|
-
return { path: extracted, name:
|
|
2245
|
+
return { path: extracted, name: String(extracted).replace(/[\\/]+$/, "").split(/[\\/]/).pop() || "" };
|
|
2246
|
+
}
|
|
2247
|
+
function cloneMenuItem(anchor, testid, label) {
|
|
2248
|
+
const item = anchor.cloneNode(true);
|
|
2249
|
+
item.removeAttribute("data-testid");
|
|
2250
|
+
item.removeAttribute("data-highlighted");
|
|
2251
|
+
item.removeAttribute("id");
|
|
2252
|
+
item.setAttribute("data-zcodepro-item", testid);
|
|
2253
|
+
for (const child of [...item.childNodes]) child.remove();
|
|
2254
|
+
const origIcon = anchor.querySelector("svg");
|
|
2255
|
+
const iconClass = origIcon ? origIcon.getAttribute("class") : "h-3.5 w-3.5";
|
|
2256
|
+
const ns = "http://www.w3.org/2000/svg";
|
|
2257
|
+
const svg = document.createElementNS(ns, "svg");
|
|
2258
|
+
svg.setAttribute("viewBox", "0 0 24 24");
|
|
2259
|
+
svg.setAttribute("fill", "none");
|
|
2260
|
+
svg.setAttribute("stroke", "currentColor");
|
|
2261
|
+
svg.setAttribute("stroke-width", "2");
|
|
2262
|
+
svg.setAttribute("stroke-linecap", "round");
|
|
2263
|
+
svg.setAttribute("stroke-linejoin", "round");
|
|
2264
|
+
svg.setAttribute("class", iconClass);
|
|
2265
|
+
const p = document.createElementNS(ns, "path");
|
|
2266
|
+
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");
|
|
2267
|
+
svg.append(p);
|
|
2268
|
+
item.append(svg, document.createTextNode(label));
|
|
2269
|
+
return item;
|
|
2270
|
+
}
|
|
2271
|
+
function wireHighlight(menu, item) {
|
|
2272
|
+
item.addEventListener("mouseenter", () => {
|
|
2273
|
+
for (const el of menu.querySelectorAll('[role="menuitem"]')) el.removeAttribute("data-highlighted");
|
|
2274
|
+
item.setAttribute("data-highlighted", "");
|
|
2275
|
+
});
|
|
2276
|
+
item.addEventListener("mouseleave", () => item.removeAttribute("data-highlighted"));
|
|
2277
|
+
}
|
|
2278
|
+
function attachFolderHover(menu, item, roots) {
|
|
2279
|
+
const L = t();
|
|
2280
|
+
let sub = null;
|
|
2281
|
+
let subHovered = false;
|
|
2282
|
+
let hideTimer = 0;
|
|
2283
|
+
let aliveTimer = 0;
|
|
2284
|
+
const removeSub = () => {
|
|
2285
|
+
clearTimeout(hideTimer);
|
|
2286
|
+
clearInterval(aliveTimer);
|
|
2287
|
+
sub?.remove();
|
|
2288
|
+
sub = null;
|
|
2289
|
+
subHovered = false;
|
|
2290
|
+
};
|
|
2291
|
+
const position = () => {
|
|
2292
|
+
const rect = item.getBoundingClientRect();
|
|
2293
|
+
sub.style.left = rect.right + "px";
|
|
2294
|
+
sub.style.top = rect.top + "px";
|
|
2295
|
+
const r = sub.getBoundingClientRect();
|
|
2296
|
+
if (r.right > window.innerWidth - 8) {
|
|
2297
|
+
sub.style.left = "";
|
|
2298
|
+
sub.style.right = window.innerWidth - rect.left + "px";
|
|
2299
|
+
}
|
|
2300
|
+
};
|
|
2301
|
+
const ensureSub = () => {
|
|
2302
|
+
if (sub) {
|
|
2303
|
+
position();
|
|
2304
|
+
return;
|
|
2305
|
+
}
|
|
2306
|
+
sub = document.createElement("div");
|
|
2307
|
+
sub.setAttribute("role", "menu");
|
|
2308
|
+
sub.setAttribute("data-zcodepro-item", "open-folder-sub");
|
|
2309
|
+
sub.className = "zcodepro-card flex flex-col gap-0.5 rounded-lg border border-border bg-menu p-1 text-ui-sm shadow-lg";
|
|
2310
|
+
sub.style.cssText = "position:fixed;z-index:60;min-width:14rem;";
|
|
2311
|
+
for (const root of roots) {
|
|
2312
|
+
const base = String(root.path).replace(/[\\/]+$/, "").split(/[\\/]/).pop() || root.path;
|
|
2313
|
+
const row = document.createElement("div");
|
|
2314
|
+
row.setAttribute("role", "menuitem");
|
|
2315
|
+
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";
|
|
2316
|
+
row.title = root.path;
|
|
2317
|
+
row.append(document.createTextNode(base + (root.primary ? ` \xB7 ${L.openFolderPrimary}` : "")));
|
|
2318
|
+
row.addEventListener("click", () => {
|
|
2319
|
+
try {
|
|
2320
|
+
menu.dispatchEvent(new KeyboardEvent("keydown", { key: "Escape", code: "Escape", bubbles: true, cancelable: true }));
|
|
2321
|
+
} catch {
|
|
2322
|
+
}
|
|
2323
|
+
removeSub();
|
|
2324
|
+
void rpc("/open-folder", { method: "POST", body: { path: root.path } });
|
|
2325
|
+
});
|
|
2326
|
+
sub.append(row);
|
|
2327
|
+
}
|
|
2328
|
+
sub.addEventListener("mouseenter", () => {
|
|
2329
|
+
subHovered = true;
|
|
2330
|
+
clearTimeout(hideTimer);
|
|
2331
|
+
});
|
|
2332
|
+
sub.addEventListener("mouseleave", () => {
|
|
2333
|
+
subHovered = false;
|
|
2334
|
+
scheduleHide();
|
|
2335
|
+
});
|
|
2336
|
+
document.body.append(sub);
|
|
2337
|
+
position();
|
|
2338
|
+
aliveTimer = setInterval(() => {
|
|
2339
|
+
if (!menu.isConnected) removeSub();
|
|
2340
|
+
}, 400);
|
|
2341
|
+
};
|
|
2342
|
+
const scheduleHide = () => {
|
|
2343
|
+
clearTimeout(hideTimer);
|
|
2344
|
+
hideTimer = setTimeout(() => {
|
|
2345
|
+
if (!subHovered) removeSub();
|
|
2346
|
+
}, 300);
|
|
2347
|
+
};
|
|
2348
|
+
item.addEventListener("mouseenter", () => {
|
|
2349
|
+
clearTimeout(hideTimer);
|
|
2350
|
+
ensureSub();
|
|
2351
|
+
});
|
|
2352
|
+
item.addEventListener("mouseleave", scheduleHide);
|
|
2353
|
+
item.addEventListener("click", () => {
|
|
2354
|
+
clearTimeout(hideTimer);
|
|
2355
|
+
ensureSub();
|
|
2356
|
+
});
|
|
2357
|
+
}
|
|
2358
|
+
async function injectNewMenuItems(content, menuRow) {
|
|
2359
|
+
const L = t();
|
|
2360
|
+
const projectId = menuRow.getAttribute("data-project-id");
|
|
2361
|
+
const editItem = content.querySelector('[data-testid="virtual-project-edit"]');
|
|
2362
|
+
if (!editItem || !projectId) return;
|
|
2363
|
+
if (content.querySelector("[data-zcodepro-item]")) return;
|
|
2364
|
+
const config = await getConfig();
|
|
2365
|
+
if (config.features && config.features.projectMenu === false) return;
|
|
2366
|
+
const res = await rpc("/projects-v2");
|
|
2367
|
+
if (!res.ok || !res.available) return;
|
|
2368
|
+
const proj = (res.projects || []).find((p) => p.id === projectId);
|
|
2369
|
+
if (!proj) return;
|
|
2370
|
+
const roots = (proj.roots || []).slice().sort((a, b) => (b.primary ? 1 : 0) - (a.primary ? 1 : 0));
|
|
2371
|
+
if (!roots.length) return;
|
|
2372
|
+
const primary = roots.find((r) => r.primary) || roots[0];
|
|
2373
|
+
const openItem = cloneMenuItem(editItem, "open-folder", L.openFolderItem);
|
|
2374
|
+
wireHighlight(content, openItem);
|
|
2375
|
+
if (roots.length === 1) {
|
|
2376
|
+
openItem.addEventListener("click", () => {
|
|
2377
|
+
try {
|
|
2378
|
+
content.dispatchEvent(new KeyboardEvent("keydown", { key: "Escape", code: "Escape", bubbles: true, cancelable: true }));
|
|
2379
|
+
} catch {
|
|
2380
|
+
}
|
|
2381
|
+
void rpc("/open-folder", { method: "POST", body: { path: primary.path } });
|
|
2382
|
+
});
|
|
2383
|
+
} else {
|
|
2384
|
+
const ns = "http://www.w3.org/2000/svg";
|
|
2385
|
+
const chev = document.createElementNS(ns, "svg");
|
|
2386
|
+
chev.setAttribute("viewBox", "0 0 24 24");
|
|
2387
|
+
chev.setAttribute("fill", "none");
|
|
2388
|
+
chev.setAttribute("stroke", "currentColor");
|
|
2389
|
+
chev.setAttribute("stroke-width", "2");
|
|
2390
|
+
chev.setAttribute("stroke-linecap", "round");
|
|
2391
|
+
chev.setAttribute("stroke-linejoin", "round");
|
|
2392
|
+
chev.setAttribute("class", "ml-auto size-3.5 shrink-0 text-foreground-subtle");
|
|
2393
|
+
const chevPath = document.createElementNS(ns, "path");
|
|
2394
|
+
chevPath.setAttribute("d", "m9 18 6-6-6-6");
|
|
2395
|
+
chev.append(chevPath);
|
|
2396
|
+
openItem.append(chev);
|
|
2397
|
+
attachFolderHover(content, openItem, roots);
|
|
2398
|
+
}
|
|
2399
|
+
editItem.after(openItem);
|
|
2400
|
+
const copyItem = cloneMenuItem(editItem, "copy-path", L.copyPathItem);
|
|
2401
|
+
wireHighlight(content, copyItem);
|
|
2402
|
+
copyItem.addEventListener("click", () => {
|
|
2403
|
+
try {
|
|
2404
|
+
content.dispatchEvent(new KeyboardEvent("keydown", { key: "Escape", code: "Escape", bubbles: true, cancelable: true }));
|
|
2405
|
+
} catch {
|
|
2406
|
+
}
|
|
2407
|
+
void copyToClipboard(primary.path).then((ok) => showToast(ok ? L.pathCopied : L.pathCopyFailed, ok ? void 0 : "error"));
|
|
2408
|
+
});
|
|
2409
|
+
openItem.after(copyItem);
|
|
2148
2410
|
}
|
|
2149
2411
|
function handleProjectMenu(content) {
|
|
2150
|
-
if (content.querySelector(
|
|
2412
|
+
if (content.querySelector("[data-zcodepro-item]")) return;
|
|
2151
2413
|
const items = itemsOf(content);
|
|
2152
|
-
const
|
|
2414
|
+
const newUi = isNewProjectSidebar();
|
|
2415
|
+
const menuRow = newUi ? openMenuProjectRow() : null;
|
|
2416
|
+
const anchor = newUi ? items.find((el) => el.getAttribute("data-testid") === "virtual-project-edit") : items.find(
|
|
2153
2417
|
(el) => el.hasAttribute("data-testid") && REMOVE_TEXTS.some((x) => itemText(el).startsWith(x))
|
|
2154
2418
|
);
|
|
2155
|
-
if (!
|
|
2419
|
+
if (!anchor) return;
|
|
2420
|
+
if (newUi) {
|
|
2421
|
+
if (!menuRow) return;
|
|
2422
|
+
void injectNewMenuItems(content, menuRow);
|
|
2423
|
+
return;
|
|
2424
|
+
}
|
|
2156
2425
|
void (async () => {
|
|
2157
2426
|
const config = await getConfig();
|
|
2158
2427
|
if (config.features && config.features.projectMenu === false) return;
|
|
2159
|
-
const project = await resolveProjectPath(
|
|
2428
|
+
const project = await resolveProjectPath(anchor);
|
|
2160
2429
|
if (!project) return;
|
|
2161
|
-
appendAliasItem(content,
|
|
2162
|
-
appendRelocateItem(content,
|
|
2163
|
-
appendOpenFolderItem(content,
|
|
2164
|
-
appendCopyPathItem(content,
|
|
2430
|
+
appendAliasItem(content, anchor, project);
|
|
2431
|
+
appendRelocateItem(content, anchor, project);
|
|
2432
|
+
appendOpenFolderItem(content, anchor, project);
|
|
2433
|
+
appendCopyPathItem(content, anchor, project);
|
|
2165
2434
|
})();
|
|
2166
2435
|
}
|
|
2167
2436
|
|
|
@@ -2554,6 +2823,489 @@
|
|
|
2554
2823
|
return v === "" || v !== "session" && !providers.some((p) => p.id === v);
|
|
2555
2824
|
}
|
|
2556
2825
|
|
|
2826
|
+
// src/inject/features/ws-rows.js
|
|
2827
|
+
var norm2 = (p) => String(p || "").replace(/[\\/]+$/, "");
|
|
2828
|
+
var NEW_ROW_SEL = "section[data-project-id]";
|
|
2829
|
+
var OLD_ROW_SEL = '[data-testid^="workspace-item-"]';
|
|
2830
|
+
var pathByProjectId = /* @__PURE__ */ new Map();
|
|
2831
|
+
function projectRowSelector() {
|
|
2832
|
+
return isNewProjectSidebar() ? NEW_ROW_SEL : OLD_ROW_SEL;
|
|
2833
|
+
}
|
|
2834
|
+
function projectRows(root = document) {
|
|
2835
|
+
return [...root.querySelectorAll(projectRowSelector())];
|
|
2836
|
+
}
|
|
2837
|
+
function rowPath(row) {
|
|
2838
|
+
if (!row) return null;
|
|
2839
|
+
if (row.hasAttribute && row.hasAttribute("data-project-id")) {
|
|
2840
|
+
const host = row.getAttribute("data-project-host");
|
|
2841
|
+
if (host !== null && host !== "local") return null;
|
|
2842
|
+
const id = row.getAttribute("data-project-id");
|
|
2843
|
+
let found = null;
|
|
2844
|
+
for (const el of row.querySelectorAll("[data-task-item-key]")) {
|
|
2845
|
+
const key = el.getAttribute("data-task-item-key") || "";
|
|
2846
|
+
const cut = key.lastIndexOf(":");
|
|
2847
|
+
if (cut > 1) {
|
|
2848
|
+
found = key.slice(0, cut);
|
|
2849
|
+
break;
|
|
2850
|
+
}
|
|
2851
|
+
}
|
|
2852
|
+
if (found) pathByProjectId.set(id, found);
|
|
2853
|
+
return found || pathByProjectId.get(id) || null;
|
|
2854
|
+
}
|
|
2855
|
+
const testid = row.getAttribute && row.getAttribute("data-testid");
|
|
2856
|
+
if (!testid || !testid.startsWith("workspace-item-")) return null;
|
|
2857
|
+
return norm2(testid.slice("workspace-item-".length)) || null;
|
|
2858
|
+
}
|
|
2859
|
+
function findProjectRow(path) {
|
|
2860
|
+
const want = norm2(path);
|
|
2861
|
+
if (!want) return null;
|
|
2862
|
+
for (const row of projectRows()) {
|
|
2863
|
+
const p = rowPath(row);
|
|
2864
|
+
if (p && norm2(p) === want) return row;
|
|
2865
|
+
}
|
|
2866
|
+
return null;
|
|
2867
|
+
}
|
|
2868
|
+
|
|
2869
|
+
// src/inject/features/alias-migration.js
|
|
2870
|
+
var sleep = (ms) => new Promise((r) => setTimeout(r, ms));
|
|
2871
|
+
var basenameOf2 = (p) => String(p || "").replace(/[\\/]+$/, "").split(/[\\/]/).pop() || "";
|
|
2872
|
+
function waitFor(getter, timeoutMs, step) {
|
|
2873
|
+
const start = Date.now();
|
|
2874
|
+
return new Promise((resolve, reject) => {
|
|
2875
|
+
const tick2 = () => {
|
|
2876
|
+
let v = null;
|
|
2877
|
+
try {
|
|
2878
|
+
v = getter();
|
|
2879
|
+
} catch {
|
|
2880
|
+
}
|
|
2881
|
+
if (v) {
|
|
2882
|
+
resolve(v);
|
|
2883
|
+
return;
|
|
2884
|
+
}
|
|
2885
|
+
if (Date.now() - start >= timeoutMs) {
|
|
2886
|
+
reject(new Error(step));
|
|
2887
|
+
return;
|
|
2888
|
+
}
|
|
2889
|
+
setTimeout(tick2, 120);
|
|
2890
|
+
};
|
|
2891
|
+
tick2();
|
|
2892
|
+
});
|
|
2893
|
+
}
|
|
2894
|
+
function setReactInputValue(input, value) {
|
|
2895
|
+
const setter = Object.getOwnPropertyDescriptor(input.constructor.prototype, "value")?.set || Object.getOwnPropertyDescriptor(window.HTMLInputElement.prototype, "value")?.set;
|
|
2896
|
+
if (!setter) throw new Error("input-setter");
|
|
2897
|
+
setter.call(input, value);
|
|
2898
|
+
input.dispatchEvent(new Event("input", { bubbles: true }));
|
|
2899
|
+
}
|
|
2900
|
+
function pressEscape() {
|
|
2901
|
+
try {
|
|
2902
|
+
document.dispatchEvent(new KeyboardEvent("keydown", { key: "Escape", code: "Escape", bubbles: true, cancelable: true }));
|
|
2903
|
+
} catch {
|
|
2904
|
+
}
|
|
2905
|
+
}
|
|
2906
|
+
async function markDismissed() {
|
|
2907
|
+
await rpc("/config", { method: "POST", body: { migrations: { aliasRenameDismissed: true } } });
|
|
2908
|
+
clearConfigCache();
|
|
2909
|
+
}
|
|
2910
|
+
var MIGRATE_LOCK_KEY = "zcodepro:alias-migrate-lock";
|
|
2911
|
+
var MIGRATE_LOCK_MS = 5 * 6e4;
|
|
2912
|
+
function migrateLockFresh() {
|
|
2913
|
+
try {
|
|
2914
|
+
const at = Number(localStorage.getItem(MIGRATE_LOCK_KEY));
|
|
2915
|
+
return Number.isFinite(at) && Date.now() - at < MIGRATE_LOCK_MS;
|
|
2916
|
+
} catch {
|
|
2917
|
+
return false;
|
|
2918
|
+
}
|
|
2919
|
+
}
|
|
2920
|
+
function touchMigrateLock() {
|
|
2921
|
+
try {
|
|
2922
|
+
localStorage.setItem(MIGRATE_LOCK_KEY, String(Date.now()));
|
|
2923
|
+
} catch {
|
|
2924
|
+
}
|
|
2925
|
+
}
|
|
2926
|
+
async function migrateOne(path, alias) {
|
|
2927
|
+
if (document.querySelector('[data-testid="virtual-project-name"], [role="menu"]')) {
|
|
2928
|
+
pressEscape();
|
|
2929
|
+
await sleep(300);
|
|
2930
|
+
}
|
|
2931
|
+
let row = findProjectRow(path);
|
|
2932
|
+
if (!row) {
|
|
2933
|
+
const byName = [...document.querySelectorAll("section[data-project-id]")].filter((el) => {
|
|
2934
|
+
const host = el.getAttribute("data-project-host");
|
|
2935
|
+
return (host === null || host === "local") && el.getAttribute("data-project-name") === basenameOf2(path);
|
|
2936
|
+
});
|
|
2937
|
+
if (byName.length === 1) row = byName[0];
|
|
2938
|
+
}
|
|
2939
|
+
if (!row) throw new Error("project-row");
|
|
2940
|
+
const projectId = row.getAttribute("data-project-id");
|
|
2941
|
+
const rowById = () => document.querySelector(`section[data-project-id="${CSS.escape(projectId)}"]`);
|
|
2942
|
+
try {
|
|
2943
|
+
row.scrollIntoView({ block: "center" });
|
|
2944
|
+
} catch {
|
|
2945
|
+
}
|
|
2946
|
+
const trigger = await waitFor(
|
|
2947
|
+
() => rowById()?.querySelector('[data-testid="virtual-project-menu"]'),
|
|
2948
|
+
4e3,
|
|
2949
|
+
"menu-trigger"
|
|
2950
|
+
);
|
|
2951
|
+
trigger.dispatchEvent(new PointerEvent("pointerdown", { bubbles: true, cancelable: true, pointerId: 1, isPrimary: true, button: 0 }));
|
|
2952
|
+
trigger.dispatchEvent(new PointerEvent("pointerup", { bubbles: true, cancelable: true, pointerId: 1, isPrimary: true, button: 0 }));
|
|
2953
|
+
trigger.click();
|
|
2954
|
+
const menu = await waitFor(() => {
|
|
2955
|
+
for (const m of document.querySelectorAll('[role="menu"]')) {
|
|
2956
|
+
if (m.querySelector('[data-testid="virtual-project-edit"]')) return m;
|
|
2957
|
+
}
|
|
2958
|
+
return null;
|
|
2959
|
+
}, 4e3, "menu-open");
|
|
2960
|
+
menu.querySelector('[data-testid="virtual-project-edit"]').click();
|
|
2961
|
+
const input = await waitFor(
|
|
2962
|
+
() => document.querySelector('[data-testid="virtual-project-name"]'),
|
|
2963
|
+
5e3,
|
|
2964
|
+
"editor-open"
|
|
2965
|
+
);
|
|
2966
|
+
const wantName = alias.trim();
|
|
2967
|
+
setReactInputValue(input, wantName);
|
|
2968
|
+
const save = await waitFor(
|
|
2969
|
+
() => {
|
|
2970
|
+
const btn = document.querySelector('[data-testid="virtual-project-save"]');
|
|
2971
|
+
return btn && !btn.disabled ? btn : null;
|
|
2972
|
+
},
|
|
2973
|
+
4e3,
|
|
2974
|
+
"save-ready"
|
|
2975
|
+
);
|
|
2976
|
+
save.click();
|
|
2977
|
+
await waitFor(() => {
|
|
2978
|
+
const r = rowById();
|
|
2979
|
+
return r && r.getAttribute("data-project-name") === wantName ? r : null;
|
|
2980
|
+
}, 8e3, "name-updated");
|
|
2981
|
+
await sleep(250);
|
|
2982
|
+
if (document.querySelector('[data-testid="virtual-project-name"]')) pressEscape();
|
|
2983
|
+
const res = await rpc("/project/alias", { method: "POST", body: { path, alias: "" } });
|
|
2984
|
+
if (!res.ok) throw new Error("alias-clear");
|
|
2985
|
+
}
|
|
2986
|
+
async function classifyEntry(path, alias, db) {
|
|
2987
|
+
const want = norm0(path);
|
|
2988
|
+
if (db) {
|
|
2989
|
+
let alsoDeleted = false;
|
|
2990
|
+
for (const proj of db.projects || []) {
|
|
2991
|
+
const hit = (proj.roots || []).find((r) => norm0(r.path) === want);
|
|
2992
|
+
if (!hit) continue;
|
|
2993
|
+
if (hit.primary) {
|
|
2994
|
+
if (proj.name === alias) return { state: "done", note: "" };
|
|
2995
|
+
return { state: "", note: "", overridden: !!proj.overridden };
|
|
2996
|
+
}
|
|
2997
|
+
alsoDeleted = (db.deletedRoots || []).some((p) => norm0(p) === want);
|
|
2998
|
+
return { state: "merged", note: proj.name, alsoDeleted };
|
|
2999
|
+
}
|
|
3000
|
+
if ((db.deletedRoots || []).some((p) => norm0(p) === want)) return { state: "deleted", note: "" };
|
|
3001
|
+
return { state: "missing", note: "" };
|
|
3002
|
+
}
|
|
3003
|
+
const localRows = [...document.querySelectorAll("section[data-project-id]")].filter((el) => {
|
|
3004
|
+
const host = el.getAttribute("data-project-host");
|
|
3005
|
+
return host === null || host === "local";
|
|
3006
|
+
});
|
|
3007
|
+
const byPath = localRows.find((el) => norm0(rowPath(el)) === want);
|
|
3008
|
+
if (byPath) {
|
|
3009
|
+
return (byPath.getAttribute("data-project-name") || "") === alias ? { state: "done", note: "" } : { state: "", note: "" };
|
|
3010
|
+
}
|
|
3011
|
+
const byName = localRows.filter((el) => el.getAttribute("data-project-name") === alias);
|
|
3012
|
+
if (byName.length === 1) return { state: "done", note: "" };
|
|
3013
|
+
for (const task of document.querySelectorAll("[data-task-item-key]")) {
|
|
3014
|
+
const key = task.getAttribute("data-task-item-key") || "";
|
|
3015
|
+
const cut = key.lastIndexOf(":");
|
|
3016
|
+
if (cut <= 1 || norm0(key.slice(0, cut)) !== want) continue;
|
|
3017
|
+
const owner = task.closest("section[data-project-id]");
|
|
3018
|
+
const ownerName = owner ? owner.getAttribute("data-project-name") || "" : "";
|
|
3019
|
+
if (ownerName) return { state: "merged", note: ownerName };
|
|
3020
|
+
}
|
|
3021
|
+
return { state: "missing", note: "" };
|
|
3022
|
+
}
|
|
3023
|
+
async function fetchProjectDb() {
|
|
3024
|
+
const res = await rpc("/projects-v2");
|
|
3025
|
+
return res.ok && res.available ? res : null;
|
|
3026
|
+
}
|
|
3027
|
+
var norm0 = (p) => String(p || "").replace(/[\\/]+$/, "");
|
|
3028
|
+
function openMigrationDialog() {
|
|
3029
|
+
ensureStyle();
|
|
3030
|
+
const L = t();
|
|
3031
|
+
let running = false;
|
|
3032
|
+
let decided = false;
|
|
3033
|
+
const decide = () => {
|
|
3034
|
+
if (decided) return;
|
|
3035
|
+
decided = true;
|
|
3036
|
+
void markDismissed();
|
|
3037
|
+
};
|
|
3038
|
+
touchMigrateLock();
|
|
3039
|
+
openDialog({
|
|
3040
|
+
title: L.aliasMigrateTitle,
|
|
3041
|
+
description: L.aliasMigrateDesc,
|
|
3042
|
+
width: "sm:max-w-md",
|
|
3043
|
+
// 迁移不可中途撤销且过程可见:点遮罩不关闭(防误触),右上角 ✕ 关闭
|
|
3044
|
+
dismissOnOutside: false,
|
|
3045
|
+
closable: true,
|
|
3046
|
+
onClose: () => {
|
|
3047
|
+
decide();
|
|
3048
|
+
window.dispatchEvent(new CustomEvent("zcodepro:aliases-changed"));
|
|
3049
|
+
},
|
|
3050
|
+
onMount: ({ body, close }) => {
|
|
3051
|
+
void (async () => {
|
|
3052
|
+
const config = await getConfig(true);
|
|
3053
|
+
const db = await fetchProjectDb();
|
|
3054
|
+
const entries = [];
|
|
3055
|
+
for (const [path, aliasRaw] of Object.entries(config.aliases || {})) {
|
|
3056
|
+
const alias = String(aliasRaw || "").trim();
|
|
3057
|
+
if (!alias) continue;
|
|
3058
|
+
const cls = await classifyEntry(path, alias, db);
|
|
3059
|
+
entries.push({
|
|
3060
|
+
path,
|
|
3061
|
+
alias,
|
|
3062
|
+
checked: cls.state === "" && !cls.overridden,
|
|
3063
|
+
state: cls.state,
|
|
3064
|
+
note: cls.note || "",
|
|
3065
|
+
overridden: !!cls.overridden,
|
|
3066
|
+
alsoDeleted: !!cls.alsoDeleted
|
|
3067
|
+
});
|
|
3068
|
+
}
|
|
3069
|
+
if (!entries.length) {
|
|
3070
|
+
close();
|
|
3071
|
+
return;
|
|
3072
|
+
}
|
|
3073
|
+
const badgesOf = (e) => {
|
|
3074
|
+
const out = [];
|
|
3075
|
+
if (e.state === "run") out.push({ text: L.aliasMigrateRunning, cls: "text-amber-500" });
|
|
3076
|
+
if (e.state === "ok") out.push({ text: L.aliasMigrateStateDone, cls: "text-emerald-600" });
|
|
3077
|
+
if (e.state === "fail") out.push({ text: L.aliasMigrateStateFailed, cls: "text-destructive" });
|
|
3078
|
+
if (e.state === "done") out.push({ text: L.aliasMigrateStateDone, cls: "text-emerald-600" });
|
|
3079
|
+
if (e.state === "merged") out.push({ text: L.aliasMigrateStateMerged.replace("{name}", e.note), cls: "text-amber-500" });
|
|
3080
|
+
if (e.state === "deleted" || e.state === "merged" && e.alsoDeleted) out.push({ text: L.aliasMigrateStateDeleted, cls: "text-foreground-subtle/70" });
|
|
3081
|
+
if (e.state === "missing") out.push({ text: L.aliasMigrateStateMissing, cls: "text-foreground-subtle/70" });
|
|
3082
|
+
if (e.state === "" && e.overridden) out.push({ text: L.aliasMigrateStateRenamed, cls: "text-foreground-subtle/70" });
|
|
3083
|
+
return out;
|
|
3084
|
+
};
|
|
3085
|
+
const progressEl = h("div", { class: "mb-1 text-ui-xs text-foreground-subtle", style: "display:none" });
|
|
3086
|
+
const listEl = h("div", { class: "max-h-[50vh] space-y-1.5 overflow-y-auto" });
|
|
3087
|
+
let deadOpen = false;
|
|
3088
|
+
const renderList = () => {
|
|
3089
|
+
const alive = entries.filter((e) => e.state !== "missing" && e.state !== "deleted");
|
|
3090
|
+
const dead = entries.filter((e) => e.state === "missing" || e.state === "deleted");
|
|
3091
|
+
const rowOf = (e, deadRow) => {
|
|
3092
|
+
const cb = h("input", { type: "checkbox" });
|
|
3093
|
+
cb.checked = e.checked;
|
|
3094
|
+
cb.disabled = running || e.state !== "" && e.state !== "fail" || e.overridden;
|
|
3095
|
+
cb.addEventListener("change", () => {
|
|
3096
|
+
e.checked = cb.checked;
|
|
3097
|
+
});
|
|
3098
|
+
const badges = badgesOf(e);
|
|
3099
|
+
const dim = deadRow || e.state !== "" && e.state !== "fail" && e.state !== "run" || e.overridden;
|
|
3100
|
+
return h(
|
|
3101
|
+
"label",
|
|
3102
|
+
{ class: "flex cursor-pointer items-start gap-2 rounded-lg p-2 transition-colors hover:bg-surface-hover" + (dim ? " opacity-60" : "") },
|
|
3103
|
+
h("span", { class: "mt-0.5" }, cb),
|
|
3104
|
+
h(
|
|
3105
|
+
"span",
|
|
3106
|
+
{ class: "min-w-0 flex-1" },
|
|
3107
|
+
h("span", { class: "block truncate text-ui-sm font-medium text-foreground" }, e.alias),
|
|
3108
|
+
h("span", { class: "block truncate font-mono text-ui-xs text-foreground-subtle" }, e.path)
|
|
3109
|
+
),
|
|
3110
|
+
...badges.map((b) => h("span", { class: "shrink-0 self-center text-ui-xs " + b.cls }, b.text))
|
|
3111
|
+
);
|
|
3112
|
+
};
|
|
3113
|
+
const parts = alive.map((e) => rowOf(e, false));
|
|
3114
|
+
if (dead.length) {
|
|
3115
|
+
const deadRows = h(
|
|
3116
|
+
"div",
|
|
3117
|
+
{ class: "space-y-1", style: deadOpen ? "" : "display:none" },
|
|
3118
|
+
...dead.map((e) => rowOf(e, true))
|
|
3119
|
+
);
|
|
3120
|
+
const toggle2 = h("button", {
|
|
3121
|
+
type: "button",
|
|
3122
|
+
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",
|
|
3123
|
+
onClick: () => {
|
|
3124
|
+
deadOpen = !deadOpen;
|
|
3125
|
+
renderList();
|
|
3126
|
+
}
|
|
3127
|
+
}, (deadOpen ? "\u25BE " : "\u25B8 ") + L.aliasMigrateDeadSummary.replace("{n}", String(dead.length)));
|
|
3128
|
+
parts.push(toggle2, deadRows);
|
|
3129
|
+
}
|
|
3130
|
+
listEl.replaceChildren(...parts);
|
|
3131
|
+
};
|
|
3132
|
+
renderList();
|
|
3133
|
+
const clearDead = async () => {
|
|
3134
|
+
if (running) return;
|
|
3135
|
+
const dead = entries.filter((e) => e.state === "missing" || e.state === "deleted");
|
|
3136
|
+
if (!dead.length) return;
|
|
3137
|
+
running = true;
|
|
3138
|
+
goBtn.setAttribute("disabled", "true");
|
|
3139
|
+
let ok = 0;
|
|
3140
|
+
for (const e of dead) {
|
|
3141
|
+
const r = await rpc("/project/alias", { method: "POST", body: { path: e.path, alias: "" } });
|
|
3142
|
+
if (r.ok) {
|
|
3143
|
+
ok++;
|
|
3144
|
+
entries.splice(entries.indexOf(e), 1);
|
|
3145
|
+
}
|
|
3146
|
+
}
|
|
3147
|
+
running = false;
|
|
3148
|
+
goBtn.removeAttribute("disabled");
|
|
3149
|
+
goBtn.textContent = L.aliasMigrateGo;
|
|
3150
|
+
clearConfigCache();
|
|
3151
|
+
renderList();
|
|
3152
|
+
window.dispatchEvent(new CustomEvent("zcodepro:aliases-changed"));
|
|
3153
|
+
if (ok === dead.length) showToast(L.aliasMigrateDeadCleared.replace("{n}", String(ok)));
|
|
3154
|
+
else showToast(L.aliasMigrateDeadClearFailed, "error");
|
|
3155
|
+
};
|
|
3156
|
+
const goBtn = btnPrimary(L.aliasMigrateGo, () => {
|
|
3157
|
+
void run();
|
|
3158
|
+
}, "min-w-24");
|
|
3159
|
+
const run = async () => {
|
|
3160
|
+
if (running) return;
|
|
3161
|
+
const todo = entries.filter((e) => e.checked);
|
|
3162
|
+
if (!todo.length) return;
|
|
3163
|
+
running = true;
|
|
3164
|
+
goBtn.setAttribute("disabled", "true");
|
|
3165
|
+
goBtn.textContent = L.aliasMigrateRunning;
|
|
3166
|
+
let ok = 0;
|
|
3167
|
+
const failed = [];
|
|
3168
|
+
for (let i = 0; i < todo.length; i++) {
|
|
3169
|
+
const e = todo[i];
|
|
3170
|
+
progressEl.style.display = "";
|
|
3171
|
+
progressEl.textContent = L.aliasMigrateProgress.replace("{i}", String(i + 1)).replace("{n}", String(todo.length)).replace("{name}", e.alias);
|
|
3172
|
+
e.state = "run";
|
|
3173
|
+
renderList();
|
|
3174
|
+
try {
|
|
3175
|
+
await migrateOne(e.path, e.alias);
|
|
3176
|
+
e.state = "ok";
|
|
3177
|
+
e.checked = false;
|
|
3178
|
+
ok++;
|
|
3179
|
+
} catch (err) {
|
|
3180
|
+
console.warn("[zcodepro] alias-migrate: " + e.path + " \u5931\u8D25\u4E8E " + (err && err.message));
|
|
3181
|
+
e.state = "fail";
|
|
3182
|
+
failed.push(e);
|
|
3183
|
+
}
|
|
3184
|
+
renderList();
|
|
3185
|
+
}
|
|
3186
|
+
running = false;
|
|
3187
|
+
progressEl.style.display = "none";
|
|
3188
|
+
goBtn.removeAttribute("disabled");
|
|
3189
|
+
goBtn.textContent = L.aliasMigrateGo;
|
|
3190
|
+
decide();
|
|
3191
|
+
close();
|
|
3192
|
+
if (!failed.length) {
|
|
3193
|
+
showToast(L.aliasMigrateDone.replace("{n}", String(ok)), "ok");
|
|
3194
|
+
} else if (ok) {
|
|
3195
|
+
showToast(L.aliasMigratePartial.replace("{n}", String(ok)).replace("{m}", String(failed.length)), "error");
|
|
3196
|
+
} else {
|
|
3197
|
+
showToast(L.aliasMigrateAllFailed, "error");
|
|
3198
|
+
}
|
|
3199
|
+
};
|
|
3200
|
+
body.append(
|
|
3201
|
+
progressEl,
|
|
3202
|
+
listEl,
|
|
3203
|
+
h("p", { class: "text-ui-xs/relaxed text-foreground-subtle" }, L.aliasMigrateItemHint),
|
|
3204
|
+
(() => {
|
|
3205
|
+
const footer = document.createElement("div");
|
|
3206
|
+
footer.className = "mt-6 flex flex-col-reverse gap-2 sm:flex-row sm:justify-end";
|
|
3207
|
+
const hasDead = entries.some((e) => e.state === "missing" || e.state === "deleted");
|
|
3208
|
+
if (hasDead) {
|
|
3209
|
+
const clearBtn = btnSecondary(L.aliasMigrateClearDead, () => {
|
|
3210
|
+
void clearDead().then(() => {
|
|
3211
|
+
if (!entries.some((e) => e.state === "missing" || e.state === "deleted")) clearBtn.style.display = "none";
|
|
3212
|
+
});
|
|
3213
|
+
});
|
|
3214
|
+
footer.append(clearBtn);
|
|
3215
|
+
}
|
|
3216
|
+
footer.append(
|
|
3217
|
+
btnSecondary(L.aliasMigrateSkip, () => {
|
|
3218
|
+
if (running) return;
|
|
3219
|
+
decide();
|
|
3220
|
+
close();
|
|
3221
|
+
}),
|
|
3222
|
+
goBtn
|
|
3223
|
+
);
|
|
3224
|
+
return footer;
|
|
3225
|
+
})()
|
|
3226
|
+
);
|
|
3227
|
+
})();
|
|
3228
|
+
}
|
|
3229
|
+
});
|
|
3230
|
+
}
|
|
3231
|
+
function migrationCard() {
|
|
3232
|
+
const L = t();
|
|
3233
|
+
const card = h("div", {
|
|
3234
|
+
class: "flex items-center gap-2 rounded-lg p-2",
|
|
3235
|
+
"data-zcodepro-migration-card": ""
|
|
3236
|
+
});
|
|
3237
|
+
const render = (count) => {
|
|
3238
|
+
card.replaceChildren(
|
|
3239
|
+
h(
|
|
3240
|
+
"div",
|
|
3241
|
+
{ class: "min-w-0 flex-1" },
|
|
3242
|
+
h("div", { class: "text-ui-sm font-medium text-foreground" }, L.aliasMigrateCardName),
|
|
3243
|
+
h(
|
|
3244
|
+
"div",
|
|
3245
|
+
{ class: "mt-0.5 text-ui-xs/relaxed text-foreground-subtle" },
|
|
3246
|
+
count === null ? "\u2026" : L.aliasMigrateCardDesc.replace("{n}", String(count))
|
|
3247
|
+
)
|
|
3248
|
+
),
|
|
3249
|
+
btnSmall(L.aliasMigrateRun, () => {
|
|
3250
|
+
openMigrationDialog();
|
|
3251
|
+
})
|
|
3252
|
+
);
|
|
3253
|
+
};
|
|
3254
|
+
render(null);
|
|
3255
|
+
const refresh = async () => {
|
|
3256
|
+
const config = await getConfig(true);
|
|
3257
|
+
const db = await fetchProjectDb();
|
|
3258
|
+
let count = 0;
|
|
3259
|
+
for (const [p, a] of Object.entries(config.aliases || {})) {
|
|
3260
|
+
if (!String(a || "").trim()) continue;
|
|
3261
|
+
const cls = await classifyEntry(p, String(a).trim(), db);
|
|
3262
|
+
if (cls.state === "" && !cls.overridden) count++;
|
|
3263
|
+
}
|
|
3264
|
+
if (!count) {
|
|
3265
|
+
card.remove();
|
|
3266
|
+
return;
|
|
3267
|
+
}
|
|
3268
|
+
render(count);
|
|
3269
|
+
};
|
|
3270
|
+
const onAliasesChanged = () => {
|
|
3271
|
+
if (!card.isConnected) {
|
|
3272
|
+
window.removeEventListener("zcodepro:aliases-changed", onAliasesChanged);
|
|
3273
|
+
return;
|
|
3274
|
+
}
|
|
3275
|
+
void refresh();
|
|
3276
|
+
};
|
|
3277
|
+
window.addEventListener("zcodepro:aliases-changed", onAliasesChanged);
|
|
3278
|
+
void refresh();
|
|
3279
|
+
return card;
|
|
3280
|
+
}
|
|
3281
|
+
function startAliasMigrationWatcher() {
|
|
3282
|
+
if (!officialRenameSupported() && !isNewProjectSidebar()) return;
|
|
3283
|
+
void (async () => {
|
|
3284
|
+
try {
|
|
3285
|
+
const config = await getConfig();
|
|
3286
|
+
const hasAliases = Object.values(config.aliases || {}).some((a) => String(a || "").trim());
|
|
3287
|
+
if (!hasAliases) return;
|
|
3288
|
+
if (config.migrations && config.migrations.aliasRenameDismissed) return;
|
|
3289
|
+
await waitFor(() => document.querySelector("section[data-project-id]"), 45e3, "sidebar");
|
|
3290
|
+
let focused = false;
|
|
3291
|
+
for (let i = 0; i < 600; i++) {
|
|
3292
|
+
if (document.visibilityState === "visible" && document.hasFocus()) {
|
|
3293
|
+
focused = true;
|
|
3294
|
+
break;
|
|
3295
|
+
}
|
|
3296
|
+
await sleep(500);
|
|
3297
|
+
}
|
|
3298
|
+
if (!focused) return;
|
|
3299
|
+
if (migrateLockFresh()) return;
|
|
3300
|
+
await waitFor(() => document.querySelector(".zcodepro-overlay") ? null : true, 12e4, "dialog-busy");
|
|
3301
|
+
const fresh = await getConfig(true);
|
|
3302
|
+
const still = Object.values(fresh.aliases || {}).some((a) => String(a || "").trim());
|
|
3303
|
+
if (still && !(fresh.migrations && fresh.migrations.aliasRenameDismissed)) openMigrationDialog();
|
|
3304
|
+
} catch {
|
|
3305
|
+
}
|
|
3306
|
+
})();
|
|
3307
|
+
}
|
|
3308
|
+
|
|
2557
3309
|
// src/inject/features/styles.js
|
|
2558
3310
|
var STYLE_DEFAULTS = {
|
|
2559
3311
|
rowGap: 20,
|
|
@@ -2728,7 +3480,10 @@
|
|
|
2728
3480
|
`${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
3481
|
`${LIST} [data-testid^="workspace-item-"] > div:first-child{align-self:stretch !important;}`,
|
|
2730
3482
|
`${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;}
|
|
3483
|
+
`${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;}`,
|
|
3484
|
+
// 3.16.1 新结构:项目行(virtual-project-row,固定 h-8)按视觉总量放行内留白;
|
|
3485
|
+
// 分区间距由新侧栏容器自己的布局管理,不动
|
|
3486
|
+
`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
3487
|
);
|
|
2733
3488
|
}
|
|
2734
3489
|
const sts = styles.sidebarTaskSpacing;
|
|
@@ -2739,7 +3494,10 @@
|
|
|
2739
3494
|
`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
3495
|
`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
3496
|
`${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;}
|
|
3497
|
+
`${SCROLL} div.cursor-pointer[class*="pl-8"]{padding-block:${pad}px !important;padding-top:${pad}px !important;padding-bottom:${pad}px !important;}`,
|
|
3498
|
+
// 3.16.1 新结构:任务行(li[data-task-item-key])行内留白 + 相邻行间距
|
|
3499
|
+
`li[data-task-item-key]{padding-block:${Math.max(1, Math.round(pad))}px !important;}`,
|
|
3500
|
+
`li[data-task-item-key] + li[data-task-item-key]{margin-block-start:${m}px !important;}`
|
|
2743
3501
|
);
|
|
2744
3502
|
}
|
|
2745
3503
|
return parts.join("");
|
|
@@ -2780,7 +3538,8 @@
|
|
|
2780
3538
|
thinkingLineHeight: `[data-testid^="chat-assistant-history-content"]`,
|
|
2781
3539
|
userLineHeight: `${CONV} [class*="user-row"] .whitespace-pre-wrap`,
|
|
2782
3540
|
contentWidth: "[data-v4-timeline-content-column]",
|
|
2783
|
-
|
|
3541
|
+
// 双结构:新侧栏项目行 / 旧 testid 行
|
|
3542
|
+
sidebarProjectSpacing: 'section[data-project-id] [data-testid="virtual-project-row"], [data-testid^="workspace-item-"]',
|
|
2784
3543
|
sidebarTaskSpacing: "li[data-task-item-key]"
|
|
2785
3544
|
};
|
|
2786
3545
|
var HL_MARGIN = {
|
|
@@ -2824,6 +3583,7 @@
|
|
|
2824
3583
|
} catch {
|
|
2825
3584
|
}
|
|
2826
3585
|
}
|
|
3586
|
+
var PLUGINS_REPO_URL = "https://github.com/duanluan/zcode-plugins";
|
|
2827
3587
|
function makeUpgradeControls({ endpoint, metaRefresh, idleText }) {
|
|
2828
3588
|
const L = t();
|
|
2829
3589
|
const state = h("span", { class: "min-w-0 flex-1 truncate text-left text-ui-xs/relaxed text-foreground-subtle" });
|
|
@@ -3050,10 +3810,46 @@
|
|
|
3050
3810
|
h("span", { class: "text-foreground-subtle/70" }, `${health.version} \xB7 ${HELPER_URL}`)
|
|
3051
3811
|
);
|
|
3052
3812
|
const rows = h("div", { class: "divide-y divide-border rounded-xl border border-border" });
|
|
3813
|
+
const pluginsStatusLine = h("span", { class: "max-w-40 truncate text-ui-xs/relaxed text-foreground-subtle" }, "\u2026");
|
|
3814
|
+
const pluginsBtn = btnSmall(L.pluginsCheckNow, () => {
|
|
3815
|
+
void runPluginsUpdate();
|
|
3816
|
+
});
|
|
3817
|
+
let pluginsUpdating = false;
|
|
3818
|
+
const runPluginsUpdate = async () => {
|
|
3819
|
+
if (pluginsUpdating) return;
|
|
3820
|
+
pluginsUpdating = true;
|
|
3821
|
+
pluginsBtn.disabled = true;
|
|
3822
|
+
pluginsStatusLine.textContent = L.pluginsUpdating;
|
|
3823
|
+
const res = await rpc("/plugins/update", { method: "POST", body: {} });
|
|
3824
|
+
pluginsUpdating = false;
|
|
3825
|
+
pluginsBtn.disabled = false;
|
|
3826
|
+
if (!res.ok) {
|
|
3827
|
+
pluginsStatusLine.textContent = "";
|
|
3828
|
+
showToast(L.pluginsUpdateFailed + ": " + errText(res), "error");
|
|
3829
|
+
return;
|
|
3830
|
+
}
|
|
3831
|
+
pluginsStatusLine.textContent = res.updated > 0 ? L.pluginsUpdatedDone.replaceAll("{n}", String(res.updated)) : L.pluginsUpToDate;
|
|
3832
|
+
showToast(pluginsStatusLine.textContent, "success");
|
|
3833
|
+
};
|
|
3834
|
+
void (async () => {
|
|
3835
|
+
const cfg = await getConfig(true).catch(() => null);
|
|
3836
|
+
const res = await rpc("/plugins/status");
|
|
3837
|
+
if (!res.ok) {
|
|
3838
|
+
pluginsStatusLine.textContent = "";
|
|
3839
|
+
return;
|
|
3840
|
+
}
|
|
3841
|
+
const n = (res.updates || []).length;
|
|
3842
|
+
if (cfg && (cfg.features || {}).autoUpdatePlugins === true && n > 0) {
|
|
3843
|
+
void runPluginsUpdate();
|
|
3844
|
+
return;
|
|
3845
|
+
}
|
|
3846
|
+
pluginsStatusLine.textContent = n > 0 ? L.pluginsUpdatesFound.replaceAll("{n}", String(n)) : L.pluginsUpToDate;
|
|
3847
|
+
})();
|
|
3053
3848
|
const refreshRows = () => {
|
|
3054
3849
|
const f = config.features || {};
|
|
3055
3850
|
rows.replaceChildren(
|
|
3056
|
-
|
|
3851
|
+
...isNewProjectSidebar() ? [migrationCard()] : [],
|
|
3852
|
+
settingRow(L.featureProjectMenu, isNewProjectSidebar() ? L.featureProjectMenuDescNew : L.featureProjectMenuDesc, f.projectMenu !== false, async () => {
|
|
3057
3853
|
const next = !(f.projectMenu !== false);
|
|
3058
3854
|
if (await setFeature("projectMenu", next)) f.projectMenu = next;
|
|
3059
3855
|
refreshRows();
|
|
@@ -3094,16 +3890,32 @@
|
|
|
3094
3890
|
if (await setFeature("wsRunningSpin", next)) f.wsRunningSpin = next;
|
|
3095
3891
|
refreshRows();
|
|
3096
3892
|
}),
|
|
3097
|
-
|
|
3098
|
-
const
|
|
3099
|
-
|
|
3100
|
-
|
|
3101
|
-
|
|
3102
|
-
|
|
3103
|
-
|
|
3104
|
-
|
|
3105
|
-
|
|
3106
|
-
|
|
3893
|
+
(() => {
|
|
3894
|
+
const repoLink = h("span", {
|
|
3895
|
+
class: "cursor-pointer underline-offset-4 hover:underline",
|
|
3896
|
+
title: PLUGINS_REPO_URL,
|
|
3897
|
+
onClick: (ev) => {
|
|
3898
|
+
ev.stopPropagation();
|
|
3899
|
+
openExternal(PLUGINS_REPO_URL);
|
|
3900
|
+
}
|
|
3901
|
+
}, L.featureAutoUpdatePluginsRepo);
|
|
3902
|
+
const row = settingRow("", "", f.autoUpdatePlugins === true, async () => {
|
|
3903
|
+
const next = !(f.autoUpdatePlugins === true);
|
|
3904
|
+
if (await setFeature("autoUpdatePlugins", next)) f.autoUpdatePlugins = next;
|
|
3905
|
+
refreshRows();
|
|
3906
|
+
}, h("div", { class: "flex items-center gap-2" }, pluginsBtn));
|
|
3907
|
+
const nameEl = row.querySelector(".text-ui-sm.font-medium");
|
|
3908
|
+
if (nameEl) {
|
|
3909
|
+
nameEl.replaceChildren(
|
|
3910
|
+
document.createTextNode(L.featureAutoUpdatePlugins + " "),
|
|
3911
|
+
repoLink,
|
|
3912
|
+
document.createTextNode(" \u63D2\u4EF6")
|
|
3913
|
+
);
|
|
3914
|
+
}
|
|
3915
|
+
const descEl = row.querySelector("[data-zcodepro-row-desc]");
|
|
3916
|
+
if (descEl) descEl.replaceChildren(pluginsStatusLine);
|
|
3917
|
+
return row;
|
|
3918
|
+
})()
|
|
3107
3919
|
);
|
|
3108
3920
|
};
|
|
3109
3921
|
refreshRows();
|
|
@@ -3148,70 +3960,16 @@
|
|
|
3148
3960
|
L.wechatGroupTitle,
|
|
3149
3961
|
L.wechatGroupDesc.replaceAll("{id}", WECHAT_ID),
|
|
3150
3962
|
() => hCopyIcon("size-4 shrink-0 text-foreground-subtle"),
|
|
3151
|
-
async () => {
|
|
3152
|
-
if (await copyToClipboard(WECHAT_ID)) showToast(L.wechatIdCopied);
|
|
3153
|
-
}
|
|
3154
|
-
)
|
|
3155
|
-
);
|
|
3156
|
-
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
|
|
3963
|
+
async () => {
|
|
3964
|
+
if (await copyToClipboard(WECHAT_ID)) showToast(L.wechatIdCopied);
|
|
3965
|
+
}
|
|
3966
|
+
)
|
|
3209
3967
|
);
|
|
3968
|
+
let activeTab = "features";
|
|
3210
3969
|
const paneFeatures = h(
|
|
3211
3970
|
"div",
|
|
3212
3971
|
{ role: "tabpanel", class: "mt-4" },
|
|
3213
3972
|
h("div", {}, rows),
|
|
3214
|
-
pluginsCard,
|
|
3215
3973
|
communityCards
|
|
3216
3974
|
);
|
|
3217
3975
|
const paneStyles = h("div", { role: "tabpanel", class: "mt-4", style: "display:none" });
|
|
@@ -3349,6 +4107,7 @@
|
|
|
3349
4107
|
)
|
|
3350
4108
|
};
|
|
3351
4109
|
const cells = [
|
|
4110
|
+
// 侧栏间距双结构:3.15.x 旧容器/行 + 3.16.1 新项目行(virtual-project-row)与任务行
|
|
3352
4111
|
styleCell(L.sidebarProjectSpacingName, L.sidebarProjectSpacingDesc, "sidebarProjectSpacing", { max: 24 }),
|
|
3353
4112
|
styleCell(L.sidebarTaskSpacingName, L.sidebarTaskSpacingDesc, "sidebarTaskSpacing", { max: 24 }),
|
|
3354
4113
|
widthCell,
|
|
@@ -4868,6 +5627,7 @@
|
|
|
4868
5627
|
h("span", { class: "text-ui-sm text-foreground-subtle/70" }, "\u2026")
|
|
4869
5628
|
);
|
|
4870
5629
|
const hrFacts = h("div", { class: "mt-1.5 grid grid-cols-2 gap-x-4 gap-y-1 sm:grid-cols-3" });
|
|
5630
|
+
const hrInstList = h("div", { class: "mt-1.5 space-y-1", style: "display:none" });
|
|
4871
5631
|
const hrHintLine = h("p", { class: "mt-1.5 text-ui-xs/relaxed text-amber-500", style: "display:none" });
|
|
4872
5632
|
const hrRefresh = async () => {
|
|
4873
5633
|
const res = await rpc("/headroom/status");
|
|
@@ -4876,6 +5636,8 @@
|
|
|
4876
5636
|
h("span", { class: "text-ui-sm text-destructive" }, L.headroomStatusLoadFailed + ": " + errText(res))
|
|
4877
5637
|
);
|
|
4878
5638
|
hrFacts.replaceChildren();
|
|
5639
|
+
hrInstList.replaceChildren();
|
|
5640
|
+
hrInstList.style.display = "none";
|
|
4879
5641
|
hrHintLine.style.display = "none";
|
|
4880
5642
|
return;
|
|
4881
5643
|
}
|
|
@@ -4895,9 +5657,23 @@
|
|
|
4895
5657
|
fact(L.headroomCurrentBackend, hrDevLabel(s.backend)),
|
|
4896
5658
|
fact(L.headroomDesiredBackend, hrDevLabel(s.desiredBackend)),
|
|
4897
5659
|
fact(L.headroomPowerState, HR_PM[s.powerMode] || s.powerMode),
|
|
4898
|
-
fact(L.headroomWatcher, s.watcherRunning ? L.headroomWatcherOn : L.headroomWatcherOff),
|
|
5660
|
+
fact(L.headroomWatcher, s.watcherRunning == null ? "\u2014" : s.watcherRunning ? L.headroomWatcherOn : L.headroomWatcherOff),
|
|
4899
5661
|
fact(L.headroomSaverDetect, HR_DETECT[s.saverDetect] || s.saverDetect)
|
|
4900
5662
|
);
|
|
5663
|
+
const insts = Array.isArray(s.instances) ? s.instances : [];
|
|
5664
|
+
hrInstList.replaceChildren(...insts.map((it) => h(
|
|
5665
|
+
"div",
|
|
5666
|
+
{ class: "flex min-w-0 items-center gap-2" },
|
|
5667
|
+
h("span", { class: "shrink-0 font-mono text-ui-xs text-foreground-subtle" }, `:${it.port}`),
|
|
5668
|
+
h(
|
|
5669
|
+
"span",
|
|
5670
|
+
{ class: "min-w-0 flex-1 truncate text-ui-xs text-foreground-subtle", title: `${it.upstream} | ${it.providers}` },
|
|
5671
|
+
`${it.format} \u2192 ${it.upstream}`
|
|
5672
|
+
),
|
|
5673
|
+
h("span", { class: "max-w-[40%] shrink-0 truncate text-ui-xs text-foreground-subtle/70", title: it.providers }, it.providers),
|
|
5674
|
+
h("span", { class: "shrink-0 text-ui-xs " + (it.up ? "text-emerald-600" : "text-destructive") }, it.up ? L.hrInstRunning : L.hrInstStopped)
|
|
5675
|
+
)));
|
|
5676
|
+
hrInstList.style.display = insts.length ? "" : "none";
|
|
4901
5677
|
hrHintLine.textContent = s.saverHint || "";
|
|
4902
5678
|
hrHintLine.style.display = s.saverHint ? "" : "none";
|
|
4903
5679
|
};
|
|
@@ -5085,6 +5861,7 @@
|
|
|
5085
5861
|
),
|
|
5086
5862
|
hrStatusLine,
|
|
5087
5863
|
hrFacts,
|
|
5864
|
+
hrInstList,
|
|
5088
5865
|
hrHintLine
|
|
5089
5866
|
),
|
|
5090
5867
|
h(
|
|
@@ -5462,7 +6239,7 @@
|
|
|
5462
6239
|
let item = find();
|
|
5463
6240
|
if (!item) {
|
|
5464
6241
|
const ws = workspaceOf(key);
|
|
5465
|
-
const header =
|
|
6242
|
+
const header = findProjectRow(ws);
|
|
5466
6243
|
const expander = header && header.querySelector("[aria-expanded]");
|
|
5467
6244
|
if (expander && expander.getAttribute("aria-expanded") === "false") {
|
|
5468
6245
|
expander.dispatchEvent(new MouseEvent("click", { bubbles: true, cancelable: true }));
|
|
@@ -5608,7 +6385,7 @@
|
|
|
5608
6385
|
return;
|
|
5609
6386
|
}
|
|
5610
6387
|
if (!popupEl) await openPopup();
|
|
5611
|
-
moveHighlight(k === "x" ? 1 :
|
|
6388
|
+
moveHighlight(k === "x" ? -1 : 1);
|
|
5612
6389
|
})();
|
|
5613
6390
|
}, true);
|
|
5614
6391
|
document.addEventListener("keyup", (e) => {
|
|
@@ -5626,6 +6403,7 @@
|
|
|
5626
6403
|
var REVERIFY_MS = 3e3;
|
|
5627
6404
|
var MAP_REFRESH_MS = 6e4;
|
|
5628
6405
|
var installed2 = false;
|
|
6406
|
+
var seenRows = /* @__PURE__ */ new WeakSet();
|
|
5629
6407
|
var enabled2 = true;
|
|
5630
6408
|
var pinned = null;
|
|
5631
6409
|
var resolved = false;
|
|
@@ -5682,7 +6460,17 @@
|
|
|
5682
6460
|
if (first && !walker.nextNode()) first.nodeValue = text;
|
|
5683
6461
|
else el.textContent = text;
|
|
5684
6462
|
}
|
|
5685
|
-
function scheduleEnforce(key) {
|
|
6463
|
+
function scheduleEnforce(key, { immediate = false } = {}) {
|
|
6464
|
+
if (immediate) {
|
|
6465
|
+
if (enabled2 && pinned) {
|
|
6466
|
+
const want = pinned.get(sessIdOf(key));
|
|
6467
|
+
if (want !== void 0) {
|
|
6468
|
+
for (const item of findRows(key)) {
|
|
6469
|
+
for (const el of titleElsOf(item)) writeTitle(el, want);
|
|
6470
|
+
}
|
|
6471
|
+
}
|
|
6472
|
+
}
|
|
6473
|
+
}
|
|
5686
6474
|
if (pendingKeys.has(key)) return;
|
|
5687
6475
|
pendingKeys.add(key);
|
|
5688
6476
|
setTimeout(() => {
|
|
@@ -5718,7 +6506,13 @@
|
|
|
5718
6506
|
if (!enabled2 || !pinned || pinned.size === 0) return;
|
|
5719
6507
|
for (const item of document.querySelectorAll(TASK_SEL)) {
|
|
5720
6508
|
const key = isMismatch(item);
|
|
5721
|
-
if (key)
|
|
6509
|
+
if (!key) {
|
|
6510
|
+
seenRows.add(item);
|
|
6511
|
+
continue;
|
|
6512
|
+
}
|
|
6513
|
+
const fresh = !seenRows.has(item);
|
|
6514
|
+
seenRows.add(item);
|
|
6515
|
+
scheduleEnforce(key, { immediate: fresh });
|
|
5722
6516
|
}
|
|
5723
6517
|
}
|
|
5724
6518
|
var inTaskRow2 = (node) => !!(node instanceof Element && node.closest && node.closest(TASK_SEL));
|
|
@@ -5875,7 +6669,7 @@
|
|
|
5875
6669
|
var installed3 = false;
|
|
5876
6670
|
var knownKeys = /* @__PURE__ */ new Set();
|
|
5877
6671
|
var attempted = /* @__PURE__ */ new Set();
|
|
5878
|
-
var
|
|
6672
|
+
var sleep2 = (ms) => new Promise((r) => setTimeout(r, ms));
|
|
5879
6673
|
function sessIdOf2(key) {
|
|
5880
6674
|
const i = key.indexOf(":sess_");
|
|
5881
6675
|
return i > 0 ? key.slice(i + 1) : "";
|
|
@@ -5908,7 +6702,7 @@
|
|
|
5908
6702
|
}
|
|
5909
6703
|
async function onNewTaskRow(key) {
|
|
5910
6704
|
const selDeadline = Date.now() + SELECT_WAIT_MS;
|
|
5911
|
-
while (currentKey() !== key && Date.now() < selDeadline) await
|
|
6705
|
+
while (currentKey() !== key && Date.now() < selDeadline) await sleep2(200);
|
|
5912
6706
|
if (currentKey() !== key) return;
|
|
5913
6707
|
const cfg = await getConfig().catch(() => null);
|
|
5914
6708
|
if (!cfg || !cfg.titleGen || cfg.titleGen.enabled !== true) return;
|
|
@@ -5920,7 +6714,7 @@
|
|
|
5920
6714
|
while (Date.now() < msgDeadline) {
|
|
5921
6715
|
texts = userTexts();
|
|
5922
6716
|
if (texts.length) break;
|
|
5923
|
-
await
|
|
6717
|
+
await sleep2(400);
|
|
5924
6718
|
}
|
|
5925
6719
|
if (!texts.length) return;
|
|
5926
6720
|
let assistantSeen = false;
|
|
@@ -5943,7 +6737,7 @@
|
|
|
5943
6737
|
let lastChange = Date.now();
|
|
5944
6738
|
try {
|
|
5945
6739
|
while (Date.now() - startAt < COLLECT_MAX_MS) {
|
|
5946
|
-
await
|
|
6740
|
+
await sleep2(500);
|
|
5947
6741
|
if (currentKey() !== key) {
|
|
5948
6742
|
lastChange = Date.now();
|
|
5949
6743
|
continue;
|
|
@@ -5963,7 +6757,7 @@
|
|
|
5963
6757
|
if (linkDominant(texts.join("\n"))) {
|
|
5964
6758
|
const deadline = Date.now() + 6e4;
|
|
5965
6759
|
while (Date.now() < deadline) {
|
|
5966
|
-
await
|
|
6760
|
+
await sleep2(2e3);
|
|
5967
6761
|
if (currentKey() !== key) continue;
|
|
5968
6762
|
const a = assistantText();
|
|
5969
6763
|
if (a && a.length > 80) {
|
|
@@ -5976,7 +6770,7 @@
|
|
|
5976
6770
|
let res = await callTitleGen();
|
|
5977
6771
|
for (const delay of [5e3, 2e4]) {
|
|
5978
6772
|
if (res && res.ok) break;
|
|
5979
|
-
await
|
|
6773
|
+
await sleep2(delay);
|
|
5980
6774
|
res = await callTitleGen();
|
|
5981
6775
|
}
|
|
5982
6776
|
if (res && res.ok && res.written && res.title) {
|
|
@@ -6033,115 +6827,8 @@
|
|
|
6033
6827
|
});
|
|
6034
6828
|
}
|
|
6035
6829
|
|
|
6036
|
-
// src/inject/features/pinned-expand.js
|
|
6037
|
-
var installed4 = false;
|
|
6038
|
-
var keepCollapsed = false;
|
|
6039
|
-
var CONFIG_POLL_MIN_MS = 5e3;
|
|
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;
|
|
6050
|
-
}
|
|
6051
|
-
}
|
|
6052
|
-
} catch {
|
|
6053
|
-
}
|
|
6054
|
-
return false;
|
|
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);
|
|
6085
|
-
document.addEventListener("click", (e) => {
|
|
6086
|
-
const row = e.target.closest && e.target.closest('[data-testid^="workspace-item-"]');
|
|
6087
|
-
if (row) row.__zcodeproUserTouched = Date.now();
|
|
6088
|
-
}, true);
|
|
6089
|
-
}
|
|
6090
|
-
function currentTaskRow() {
|
|
6091
|
-
for (const el of document.querySelectorAll("[data-task-item-key]")) {
|
|
6092
|
-
if ((el.className + "").includes("bg-selected")) return el;
|
|
6093
|
-
}
|
|
6094
|
-
return null;
|
|
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);
|
|
6123
|
-
}
|
|
6124
|
-
if (settledAt && Date.now() - settledAt >= 1e3) {
|
|
6125
|
-
const h2 = headOf();
|
|
6126
|
-
if (h2 && h2.getAttribute("aria-expanded") === "true" && !userTouched2()) {
|
|
6127
|
-
collapseNavSafe(h2);
|
|
6128
|
-
}
|
|
6129
|
-
return done();
|
|
6130
|
-
}
|
|
6131
|
-
setTimeout(tick2, 200);
|
|
6132
|
-
};
|
|
6133
|
-
const done = () => {
|
|
6134
|
-
wsRow.__zcodeproSuppending = false;
|
|
6135
|
-
};
|
|
6136
|
-
wsRow.__zcodeproSuppending = true;
|
|
6137
|
-
setTimeout(tick2, 400);
|
|
6138
|
-
}
|
|
6139
|
-
function cssEscape(s) {
|
|
6140
|
-
return String(s).replace(/(["\\\]])/g, "\\$1");
|
|
6141
|
-
}
|
|
6142
|
-
|
|
6143
6830
|
// src/inject/features/ws-running.js
|
|
6144
|
-
var
|
|
6831
|
+
var installed4 = false;
|
|
6145
6832
|
var enabled3 = true;
|
|
6146
6833
|
var SCAN_DEBOUNCE_MS4 = 150;
|
|
6147
6834
|
var SCAN_FALLBACK_MS4 = 5e3;
|
|
@@ -6150,34 +6837,148 @@
|
|
|
6150
6837
|
var PEEK_SETTLE_MS = 160;
|
|
6151
6838
|
var PEEK_MAX_MS = 1500;
|
|
6152
6839
|
var PEEK_UNMOUNT_WAIT_MS = 800;
|
|
6153
|
-
var
|
|
6154
|
-
var
|
|
6840
|
+
var CONFIG_POLL_MIN_MS = 5e3;
|
|
6841
|
+
var CONFIG_POLL_MAX_MS = 6e4;
|
|
6155
6842
|
var TASK_SEL3 = "[data-task-item-key]";
|
|
6156
|
-
var WS_SEL =
|
|
6843
|
+
var WS_SEL = () => projectRowSelector();
|
|
6844
|
+
function findWsRow(ws) {
|
|
6845
|
+
return findProjectRow(ws);
|
|
6846
|
+
}
|
|
6847
|
+
var LOADER_FALLBACK_PATHS = [
|
|
6848
|
+
"M12 2v4",
|
|
6849
|
+
"m16.2 7.8 2.9-2.9",
|
|
6850
|
+
"M18 12h4",
|
|
6851
|
+
"m19.8 16.2-2.9 2.9",
|
|
6852
|
+
"M12 18v4",
|
|
6853
|
+
"m7.8 19.8-2.9-2.9",
|
|
6854
|
+
"M6 12H2",
|
|
6855
|
+
"m4.2 7.8 2.9-2.9"
|
|
6856
|
+
];
|
|
6857
|
+
function makeLoaderSvg(baseClass) {
|
|
6858
|
+
const ns = "http://www.w3.org/2000/svg";
|
|
6859
|
+
const proto = document.querySelector("svg.lucide-loader");
|
|
6860
|
+
if (proto) {
|
|
6861
|
+
const clone = proto.cloneNode(true);
|
|
6862
|
+
const origClass = proto.getAttribute("class") || "";
|
|
6863
|
+
const keep = origClass.split(/\s+/).filter((c) => /^(size-|text-)/.test(c)).join(" ");
|
|
6864
|
+
clone.setAttribute("class", ((keep || baseClass) + " animate-spin zcodepro-ws-loader").trim());
|
|
6865
|
+
return clone;
|
|
6866
|
+
}
|
|
6867
|
+
const svg = document.createElementNS(ns, "svg");
|
|
6868
|
+
svg.setAttribute("viewBox", "0 0 24 24");
|
|
6869
|
+
svg.setAttribute("fill", "none");
|
|
6870
|
+
svg.setAttribute("stroke", "currentColor");
|
|
6871
|
+
svg.setAttribute("stroke-width", "2");
|
|
6872
|
+
svg.setAttribute("stroke-linecap", "round");
|
|
6873
|
+
svg.setAttribute("stroke-linejoin", "round");
|
|
6874
|
+
svg.setAttribute("class", (baseClass + " animate-spin zcodepro-ws-loader").trim());
|
|
6875
|
+
for (const d of LOADER_FALLBACK_PATHS) {
|
|
6876
|
+
const path = document.createElementNS(ns, "path");
|
|
6877
|
+
path.setAttribute("d", d);
|
|
6878
|
+
svg.append(path);
|
|
6879
|
+
}
|
|
6880
|
+
return svg;
|
|
6881
|
+
}
|
|
6882
|
+
function setRunningIcon(holder, on) {
|
|
6883
|
+
if (!holder) return;
|
|
6884
|
+
if (on) {
|
|
6885
|
+
if (holder.querySelector(":scope > svg.zcodepro-ws-loader")) return;
|
|
6886
|
+
const orig0 = holder.querySelector(":scope > svg:not(.zcodepro-ws-loader)");
|
|
6887
|
+
const base = (orig0 ? orig0.getAttribute("class") || "" : "size-4").replace(/lucide-[a-z-]*/g, "").trim() || "size-4";
|
|
6888
|
+
holder.append(makeLoaderSvg(base));
|
|
6889
|
+
} else {
|
|
6890
|
+
holder.querySelectorAll(":scope > svg.zcodepro-ws-loader").forEach((el) => el.remove());
|
|
6891
|
+
}
|
|
6892
|
+
}
|
|
6893
|
+
function iconHolderOf(row) {
|
|
6894
|
+
if (row.hasAttribute && row.hasAttribute("data-project-id")) {
|
|
6895
|
+
const toggle2 = row.querySelector('[data-testid="virtual-project-toggle"]');
|
|
6896
|
+
return toggle2 ? toggle2.querySelector(":scope > span") : null;
|
|
6897
|
+
}
|
|
6898
|
+
return row.firstElementChild && row.firstElementChild.querySelector(":scope > span");
|
|
6899
|
+
}
|
|
6900
|
+
function isRunningRow(el) {
|
|
6901
|
+
const scope = el.firstElementChild;
|
|
6902
|
+
if (!scope) return false;
|
|
6903
|
+
const svg = scope.querySelector('svg[class*="lucide-loader"]');
|
|
6904
|
+
return !!svg;
|
|
6905
|
+
}
|
|
6157
6906
|
var runningByWs = /* @__PURE__ */ new Map();
|
|
6158
6907
|
var peekTimers = /* @__PURE__ */ new Map();
|
|
6159
6908
|
var activePeeks = /* @__PURE__ */ new Set();
|
|
6160
6909
|
var peekedWs = /* @__PURE__ */ new Set();
|
|
6161
6910
|
var wsWithRows = /* @__PURE__ */ new Set();
|
|
6911
|
+
var servicesRef = null;
|
|
6912
|
+
function findServices() {
|
|
6913
|
+
if (servicesRef) return servicesRef;
|
|
6914
|
+
try {
|
|
6915
|
+
const rootEl = document.getElementById("root");
|
|
6916
|
+
const containerKey = rootEl && Object.keys(rootEl).find((k) => k.startsWith("__reactContainer$"));
|
|
6917
|
+
if (!containerKey) return null;
|
|
6918
|
+
const seen = /* @__PURE__ */ new Set();
|
|
6919
|
+
let found = null;
|
|
6920
|
+
const scanObj = (o) => {
|
|
6921
|
+
if (!o || typeof o !== "object" || seen.has(o) || found) return;
|
|
6922
|
+
seen.add(o);
|
|
6923
|
+
const ts = o.zcodeTaskService;
|
|
6924
|
+
if (ts && typeof ts === "object" && typeof ts.releaseWorkspacePreparation === "function") found = o;
|
|
6925
|
+
};
|
|
6926
|
+
let visited = 0;
|
|
6927
|
+
const visit = (f) => {
|
|
6928
|
+
if (!f || found || visited > 6e4) return;
|
|
6929
|
+
visited++;
|
|
6930
|
+
for (const holder of [f.memoizedProps, f.memoizedState]) {
|
|
6931
|
+
if (!holder || typeof holder !== "object") continue;
|
|
6932
|
+
scanObj(holder);
|
|
6933
|
+
for (const v of Object.values(holder)) {
|
|
6934
|
+
if (v && typeof v === "object") scanObj(v);
|
|
6935
|
+
}
|
|
6936
|
+
}
|
|
6937
|
+
visit(f.child);
|
|
6938
|
+
visit(f.sibling);
|
|
6939
|
+
};
|
|
6940
|
+
visit(rootEl[containerKey]);
|
|
6941
|
+
if (found) servicesRef = found;
|
|
6942
|
+
return found;
|
|
6943
|
+
} catch {
|
|
6944
|
+
return null;
|
|
6945
|
+
}
|
|
6946
|
+
}
|
|
6947
|
+
async function authoritativeIdle(ws) {
|
|
6948
|
+
const services = findServices();
|
|
6949
|
+
const ts = services && services.zcodeTaskService;
|
|
6950
|
+
if (!ts || typeof ts.listActiveTaskIds !== "function") return null;
|
|
6951
|
+
try {
|
|
6952
|
+
const base = String(ws).replace(/[\\/]+$/, "");
|
|
6953
|
+
const a = await ts.listActiveTaskIds({ workspacePath: base });
|
|
6954
|
+
const b = await ts.listActiveTaskIds({ workspacePath: base + "/" });
|
|
6955
|
+
const ids = [...Array.isArray(a) ? a : [], ...Array.isArray(b) ? b : []].map(String);
|
|
6956
|
+
if (!Array.isArray(a) || !Array.isArray(b)) return null;
|
|
6957
|
+
if (!ids.length) return true;
|
|
6958
|
+
const st = await rpc("/task-statuses?ids=" + encodeURIComponent(ids.join(","))).catch(() => null);
|
|
6959
|
+
const TERMINAL = /* @__PURE__ */ new Set(["completed", "error", "interrupted"]);
|
|
6960
|
+
const live = (id) => {
|
|
6961
|
+
const rec = st && st.ok && st.available ? st.statuses[id] : void 0;
|
|
6962
|
+
if (rec === void 0) return true;
|
|
6963
|
+
if (!TERMINAL.has(rec.status)) return true;
|
|
6964
|
+
return Date.now() - rec.updatedAt < 3e5;
|
|
6965
|
+
};
|
|
6966
|
+
return !ids.some(live);
|
|
6967
|
+
} catch {
|
|
6968
|
+
return null;
|
|
6969
|
+
}
|
|
6970
|
+
}
|
|
6162
6971
|
function workspaceOf2(key) {
|
|
6163
6972
|
const i = key.indexOf(":sess_");
|
|
6164
6973
|
return i > 0 ? key.slice(0, i) : key;
|
|
6165
6974
|
}
|
|
6166
|
-
function findWsRow(ws) {
|
|
6167
|
-
return document.querySelector(`[data-testid="workspace-item-${CSS.escape(ws)}"]`);
|
|
6168
|
-
}
|
|
6169
6975
|
function wsHead(row) {
|
|
6170
6976
|
return row.matches("[aria-expanded]") ? row : row.querySelector("[aria-expanded]");
|
|
6171
6977
|
}
|
|
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"));
|
|
6176
|
-
}
|
|
6177
6978
|
function domRowsOf(ws) {
|
|
6178
6979
|
return [...document.querySelectorAll(TASK_SEL3)].filter((e) => workspaceOf2(e.getAttribute("data-task-item-key") || "") === ws);
|
|
6179
6980
|
}
|
|
6180
|
-
function
|
|
6981
|
+
function currentTaskRow() {
|
|
6181
6982
|
for (const el of document.querySelectorAll(TASK_SEL3)) {
|
|
6182
6983
|
if ((el.className + "").includes("bg-selected")) return el;
|
|
6183
6984
|
}
|
|
@@ -6190,7 +6991,7 @@
|
|
|
6190
6991
|
}
|
|
6191
6992
|
};
|
|
6192
6993
|
function toggleNavSafe(head) {
|
|
6193
|
-
const cur =
|
|
6994
|
+
const cur = currentTaskRow();
|
|
6194
6995
|
const backKey = cur ? cur.getAttribute("data-task-item-key") : "";
|
|
6195
6996
|
synthClick(head);
|
|
6196
6997
|
if (!backKey) return;
|
|
@@ -6258,17 +7059,169 @@
|
|
|
6258
7059
|
}
|
|
6259
7060
|
function apply() {
|
|
6260
7061
|
const seen = /* @__PURE__ */ new Set();
|
|
6261
|
-
for (const row of document.querySelectorAll(WS_SEL)) {
|
|
6262
|
-
const path = row
|
|
7062
|
+
for (const row of document.querySelectorAll(WS_SEL())) {
|
|
7063
|
+
const path = rowPath(row);
|
|
7064
|
+
if (!path) continue;
|
|
6263
7065
|
seen.add(path);
|
|
6264
7066
|
const head = wsHead(row);
|
|
6265
7067
|
const collapsed = !head || head.getAttribute("aria-expanded") === "false";
|
|
6266
|
-
const
|
|
6267
|
-
const
|
|
6268
|
-
|
|
6269
|
-
|
|
7068
|
+
const domRunning = !!(runningByWs.get(path) && runningByWs.get(path).size);
|
|
7069
|
+
const normP = (v) => String(v || "").replace(/[\\/]+$/, "");
|
|
7070
|
+
const running = enabled3 && collapsed && (activeProjectPaths.size ? [...activeProjectPaths].some((p2) => normP(p2) === normP(path)) : domRunning);
|
|
7071
|
+
const icon = iconHolderOf(row);
|
|
7072
|
+
icon?.classList.toggle("zcodepro-ws-running", running);
|
|
7073
|
+
setRunningIcon(icon, running);
|
|
7074
|
+
}
|
|
7075
|
+
applySectionSpin();
|
|
6270
7076
|
for (const ws of [...runningByWs.keys()]) if (!seen.has(ws)) runningByWs.delete(ws);
|
|
6271
7077
|
}
|
|
7078
|
+
var headInfoCache = /* @__PURE__ */ new WeakMap();
|
|
7079
|
+
var PROJECT_HEAD_TEXTS = /* @__PURE__ */ new Set(["\u9879\u76EE", "projects"]);
|
|
7080
|
+
var TASK_HEAD_TEXTS = /* @__PURE__ */ new Set(["\u4EFB\u52A1", "tasks"]);
|
|
7081
|
+
function kindFromHeadText(head) {
|
|
7082
|
+
const text = (head.textContent || "").trim().toLowerCase();
|
|
7083
|
+
if (PROJECT_HEAD_TEXTS.has(text)) return "project";
|
|
7084
|
+
if (TASK_HEAD_TEXTS.has(text)) return "task";
|
|
7085
|
+
return null;
|
|
7086
|
+
}
|
|
7087
|
+
function sectionHeads() {
|
|
7088
|
+
const heads = [];
|
|
7089
|
+
for (const sv of document.querySelectorAll("svg[data-purpose-section-chevron]")) {
|
|
7090
|
+
const btn = sv.closest("button");
|
|
7091
|
+
if (btn) heads.push(btn);
|
|
7092
|
+
}
|
|
7093
|
+
for (const h3 of document.querySelectorAll("h3")) heads.push(h3);
|
|
7094
|
+
return heads.map((head) => {
|
|
7095
|
+
const cached = headInfoCache.get(head);
|
|
7096
|
+
if (cached) return { head, cont: cached.cont, kind: cached.kind };
|
|
7097
|
+
const textKind = head.tagName === "BUTTON" ? kindFromHeadText(head) : "task";
|
|
7098
|
+
let cont = head.parentElement;
|
|
7099
|
+
while (cont && !cont.querySelector("li[data-task-item-key]") && cont !== document.body) cont = cont.parentElement;
|
|
7100
|
+
const contOk = cont && cont !== document.body;
|
|
7101
|
+
const kind = textKind || (contOk ? cont.querySelector("section[data-project-id]") ? "project" : "task" : null);
|
|
7102
|
+
headInfoCache.set(head, { cont: contOk ? cont : null, kind });
|
|
7103
|
+
return { head, cont: contOk ? cont : null, kind };
|
|
7104
|
+
}).filter((x) => x.head);
|
|
7105
|
+
}
|
|
7106
|
+
var SEC_SPIN_CLASS = "zcodepro-ws-sec-spin";
|
|
7107
|
+
var anyActiveCache = { at: 0, value: null, busy: false };
|
|
7108
|
+
var sectionActive = { task: false, project: false };
|
|
7109
|
+
var activeProjectPaths = /* @__PURE__ */ new Set();
|
|
7110
|
+
setInterval(() => {
|
|
7111
|
+
if (!anyActiveCache.busy && Date.now() - anyActiveCache.at >= 1e4) globalAnyActive();
|
|
7112
|
+
}, 1e4);
|
|
7113
|
+
function globalAnyActive() {
|
|
7114
|
+
if (anyActiveCache.value !== null && Date.now() - anyActiveCache.at < 1e4) return anyActiveCache.value;
|
|
7115
|
+
if (anyActiveCache.busy) return anyActiveCache.value === true;
|
|
7116
|
+
anyActiveCache.busy = true;
|
|
7117
|
+
sectionActive.task = false;
|
|
7118
|
+
sectionActive.project = false;
|
|
7119
|
+
activeProjectPaths = /* @__PURE__ */ new Set();
|
|
7120
|
+
void (async () => {
|
|
7121
|
+
let hit = null;
|
|
7122
|
+
try {
|
|
7123
|
+
const res = await rpc("/projects-v2").catch(() => null);
|
|
7124
|
+
const services = findServices();
|
|
7125
|
+
const ts = services && services.zcodeTaskService;
|
|
7126
|
+
if (res && res.ok && res.available && ts && typeof ts.listActiveTaskIds === "function") {
|
|
7127
|
+
hit = false;
|
|
7128
|
+
const projPaths = /* @__PURE__ */ new Set();
|
|
7129
|
+
for (const proj of res.projects || []) {
|
|
7130
|
+
for (const r of proj.roots || []) {
|
|
7131
|
+
const b = String(r.path || "").replace(/[\\/]+$/, "");
|
|
7132
|
+
if (b) projPaths.add(b);
|
|
7133
|
+
}
|
|
7134
|
+
}
|
|
7135
|
+
const taskSidePaths = /* @__PURE__ */ new Set();
|
|
7136
|
+
for (const el of document.querySelectorAll("[data-task-item-key]")) {
|
|
7137
|
+
const sec = el.closest("section[data-project-id]");
|
|
7138
|
+
if (sec) continue;
|
|
7139
|
+
const k = el.getAttribute("data-task-item-key") || "";
|
|
7140
|
+
const cut = k.lastIndexOf(":");
|
|
7141
|
+
if (cut > 1) taskSidePaths.add(k.slice(0, cut).replace(/[\\/]+$/, ""));
|
|
7142
|
+
}
|
|
7143
|
+
const scanPaths = /* @__PURE__ */ new Set([...projPaths, ...taskSidePaths]);
|
|
7144
|
+
const byKind = { task: /* @__PURE__ */ new Set(), project: /* @__PURE__ */ new Set() };
|
|
7145
|
+
const byKindByPath = /* @__PURE__ */ new Map();
|
|
7146
|
+
const rootToProject = /* @__PURE__ */ new Map();
|
|
7147
|
+
const projectPaths = /* @__PURE__ */ new Map();
|
|
7148
|
+
for (const proj of res.projects || []) {
|
|
7149
|
+
const names = [];
|
|
7150
|
+
for (const r of proj.roots || []) {
|
|
7151
|
+
const b = String(r.path || "").replace(/[\\/]+$/, "");
|
|
7152
|
+
if (b) {
|
|
7153
|
+
rootToProject.set(b, proj.name);
|
|
7154
|
+
names.push(b);
|
|
7155
|
+
}
|
|
7156
|
+
}
|
|
7157
|
+
projectPaths.set(proj.name, names);
|
|
7158
|
+
}
|
|
7159
|
+
for (const base of scanPaths) {
|
|
7160
|
+
const a = await ts.listActiveTaskIds({ workspacePath: base });
|
|
7161
|
+
const b = await ts.listActiveTaskIds({ workspacePath: base + "/" });
|
|
7162
|
+
const ids = [...Array.isArray(a) ? a : [], ...Array.isArray(b) ? b : []].map(String);
|
|
7163
|
+
if (!ids.length) continue;
|
|
7164
|
+
byKindByPath.set(base, ids);
|
|
7165
|
+
const kind = projPaths.has(base) ? "project" : "task";
|
|
7166
|
+
for (const id of ids) byKind[kind].add(id);
|
|
7167
|
+
}
|
|
7168
|
+
const allIds = [...byKind.task, ...byKind.project];
|
|
7169
|
+
const st = allIds.length ? await rpc("/task-statuses?ids=" + encodeURIComponent(allIds.join(","))).catch(() => null) : null;
|
|
7170
|
+
const TERMINAL = /* @__PURE__ */ new Set(["completed", "error", "interrupted"]);
|
|
7171
|
+
const live = (id) => {
|
|
7172
|
+
const rec = st && st.ok && st.available ? st.statuses[id] : void 0;
|
|
7173
|
+
if (rec === void 0) return true;
|
|
7174
|
+
if (!TERMINAL.has(rec.status)) return true;
|
|
7175
|
+
return Date.now() - rec.updatedAt < 3e5;
|
|
7176
|
+
};
|
|
7177
|
+
activeProjectPaths = /* @__PURE__ */ new Set();
|
|
7178
|
+
for (const [base, ids] of byKindByPath) {
|
|
7179
|
+
if (!projPaths.has(base)) continue;
|
|
7180
|
+
if (ids.some(live)) {
|
|
7181
|
+
const projName = rootToProject.get(base);
|
|
7182
|
+
if (projName) for (const p2 of projectPaths.get(projName) || []) activeProjectPaths.add(p2);
|
|
7183
|
+
}
|
|
7184
|
+
}
|
|
7185
|
+
const taskDomRunning = !!document.querySelector('[data-task-item-key]:not(section[data-project-id] *) svg[class*="lucide-loader"]');
|
|
7186
|
+
if (taskDomRunning && [...byKind.task].some(live)) sectionActive.task = true;
|
|
7187
|
+
if ([...byKind.project].some(live)) sectionActive.project = true;
|
|
7188
|
+
hit = sectionActive.task || sectionActive.project;
|
|
7189
|
+
}
|
|
7190
|
+
} catch {
|
|
7191
|
+
}
|
|
7192
|
+
if (hit !== null) anyActiveCache = { at: Date.now(), value: hit, busy: false };
|
|
7193
|
+
else anyActiveCache.busy = false;
|
|
7194
|
+
apply();
|
|
7195
|
+
})();
|
|
7196
|
+
return anyActiveCache.value === true;
|
|
7197
|
+
}
|
|
7198
|
+
function applySectionSpin() {
|
|
7199
|
+
if (!enabled3) {
|
|
7200
|
+
document.querySelectorAll("." + SEC_SPIN_CLASS).forEach((el) => el.remove());
|
|
7201
|
+
return;
|
|
7202
|
+
}
|
|
7203
|
+
for (const { head, cont, kind } of sectionHeads()) {
|
|
7204
|
+
const running = !!(cont && cont.querySelector('li[data-task-item-key] svg[class*="lucide-loader"]'));
|
|
7205
|
+
let expanded = true;
|
|
7206
|
+
if (head.tagName === "BUTTON") expanded = head.getAttribute("aria-expanded") !== "false";
|
|
7207
|
+
else {
|
|
7208
|
+
const list = head.nextElementSibling;
|
|
7209
|
+
expanded = !list || list.offsetHeight > 0;
|
|
7210
|
+
}
|
|
7211
|
+
if (!kind) return;
|
|
7212
|
+
const scoped = kind === "project" ? sectionActive.project : sectionActive.task;
|
|
7213
|
+
const want = !expanded && scoped;
|
|
7214
|
+
const existing = head.querySelector(":scope > ." + SEC_SPIN_CLASS);
|
|
7215
|
+
if (want && !existing) {
|
|
7216
|
+
const span = document.createElement("span");
|
|
7217
|
+
span.className = "flex size-4 shrink-0 items-center justify-center " + SEC_SPIN_CLASS;
|
|
7218
|
+
span.append(makeLoaderSvg("size-4"));
|
|
7219
|
+
head.prepend(span);
|
|
7220
|
+
} else if (!want && existing) {
|
|
7221
|
+
existing.remove();
|
|
7222
|
+
}
|
|
7223
|
+
}
|
|
7224
|
+
}
|
|
6272
7225
|
function schedulePeek(ws, delay) {
|
|
6273
7226
|
clearTimeout(peekTimers.get(ws));
|
|
6274
7227
|
peekTimers.set(ws, setTimeout(() => {
|
|
@@ -6300,6 +7253,24 @@
|
|
|
6300
7253
|
}
|
|
6301
7254
|
var peekChain = Promise.resolve();
|
|
6302
7255
|
async function peek(ws, opts) {
|
|
7256
|
+
if (!opts?.manual) {
|
|
7257
|
+
const auth = await authoritativeIdle(ws);
|
|
7258
|
+
if (auth !== null) {
|
|
7259
|
+
if (auth) {
|
|
7260
|
+
runningByWs.delete(ws);
|
|
7261
|
+
} else {
|
|
7262
|
+
let set = runningByWs.get(ws);
|
|
7263
|
+
if (!set) {
|
|
7264
|
+
set = /* @__PURE__ */ new Set();
|
|
7265
|
+
runningByWs.set(ws, set);
|
|
7266
|
+
}
|
|
7267
|
+
set.add(ws + ":active");
|
|
7268
|
+
schedulePeek(ws, PEEK_REPEAT_MS);
|
|
7269
|
+
}
|
|
7270
|
+
apply();
|
|
7271
|
+
return true;
|
|
7272
|
+
}
|
|
7273
|
+
}
|
|
6303
7274
|
const run = () => peekInner(ws, opts);
|
|
6304
7275
|
const p = peekChain.then(run, run);
|
|
6305
7276
|
peekChain = p.catch(() => {
|
|
@@ -6311,7 +7282,7 @@
|
|
|
6311
7282
|
const row = findWsRow(ws);
|
|
6312
7283
|
const head = row && wsHead(row);
|
|
6313
7284
|
if (!row || !head || head.getAttribute("aria-expanded") !== "false") return false;
|
|
6314
|
-
if (!
|
|
7285
|
+
if (!currentTaskRow()) {
|
|
6315
7286
|
schedulePeek(ws, PEEK_REPEAT_MS);
|
|
6316
7287
|
return false;
|
|
6317
7288
|
}
|
|
@@ -6327,9 +7298,10 @@
|
|
|
6327
7298
|
document.body.append(frozen);
|
|
6328
7299
|
row.style.visibility = "hidden";
|
|
6329
7300
|
const hider = installPeekHider(ws);
|
|
7301
|
+
let readOk = false;
|
|
6330
7302
|
try {
|
|
6331
7303
|
toggleNavSafe(head);
|
|
6332
|
-
await settleAndRead(ws);
|
|
7304
|
+
readOk = await settleAndRead(ws);
|
|
6333
7305
|
const rowNow = findWsRow(ws) || row;
|
|
6334
7306
|
const headNow = wsHead(rowNow);
|
|
6335
7307
|
if (headNow && headNow.getAttribute("aria-expanded") === "true" && !userTouched(rowNow)) {
|
|
@@ -6345,10 +7317,10 @@
|
|
|
6345
7317
|
apply();
|
|
6346
7318
|
const set = runningByWs.get(ws);
|
|
6347
7319
|
if (set && set.size && enabled3) schedulePeek(ws, PEEK_REPEAT_MS);
|
|
6348
|
-
return
|
|
7320
|
+
return readOk;
|
|
6349
7321
|
}
|
|
6350
7322
|
function wsRunningSnapshot() {
|
|
6351
|
-
const curKey =
|
|
7323
|
+
const curKey = currentTaskRow()?.getAttribute("data-task-item-key") || "";
|
|
6352
7324
|
return {
|
|
6353
7325
|
running: [...runningByWs.entries()].filter(([, set]) => set.size > 0).map(([ws]) => ws),
|
|
6354
7326
|
current: curKey ? workspaceOf2(curKey) || null : null
|
|
@@ -6378,6 +7350,7 @@
|
|
|
6378
7350
|
const t0 = Date.now();
|
|
6379
7351
|
let lastCount = -1;
|
|
6380
7352
|
let stableAt = 0;
|
|
7353
|
+
let zeroRows = false;
|
|
6381
7354
|
const timer = setInterval(() => {
|
|
6382
7355
|
const rows = domRowsOf(ws);
|
|
6383
7356
|
const elapsed = Date.now() - t0;
|
|
@@ -6389,7 +7362,7 @@
|
|
|
6389
7362
|
if (!settled && elapsed < PEEK_MAX_MS) return;
|
|
6390
7363
|
clearInterval(timer);
|
|
6391
7364
|
if (lastCount === 0) {
|
|
6392
|
-
|
|
7365
|
+
zeroRows = true;
|
|
6393
7366
|
} else {
|
|
6394
7367
|
let set = runningByWs.get(ws);
|
|
6395
7368
|
if (!set) {
|
|
@@ -6402,7 +7375,7 @@
|
|
|
6402
7375
|
else set.delete(key);
|
|
6403
7376
|
}
|
|
6404
7377
|
}
|
|
6405
|
-
resolve();
|
|
7378
|
+
resolve(!zeroRows);
|
|
6406
7379
|
}, 80);
|
|
6407
7380
|
});
|
|
6408
7381
|
}
|
|
@@ -6443,18 +7416,18 @@
|
|
|
6443
7416
|
}
|
|
6444
7417
|
function relevant(muts) {
|
|
6445
7418
|
for (const m of muts) {
|
|
6446
|
-
if (inSel(m.target, TASK_SEL3) || inSel(m.target, WS_SEL)) return true;
|
|
7419
|
+
if (inSel(m.target, TASK_SEL3) || inSel(m.target, WS_SEL())) return true;
|
|
6447
7420
|
for (const n of m.addedNodes) {
|
|
6448
|
-
if (n instanceof Element && (n.matches(TASK_SEL3) || n.matches(WS_SEL) || n.querySelector(TASK_SEL3) || n.querySelector(WS_SEL))) return true;
|
|
7421
|
+
if (n instanceof Element && (n.matches(TASK_SEL3) || n.matches(WS_SEL()) || n.querySelector(TASK_SEL3) || n.querySelector(WS_SEL()))) return true;
|
|
6449
7422
|
}
|
|
6450
7423
|
for (const n of m.removedNodes) {
|
|
6451
|
-
if (n instanceof Element && (n.matches(TASK_SEL3) || n.matches(WS_SEL) || n.querySelector(TASK_SEL3))) return true;
|
|
7424
|
+
if (n instanceof Element && (n.matches(TASK_SEL3) || n.matches(WS_SEL()) || n.querySelector(TASK_SEL3))) return true;
|
|
6452
7425
|
}
|
|
6453
7426
|
}
|
|
6454
7427
|
return false;
|
|
6455
7428
|
}
|
|
6456
|
-
var
|
|
6457
|
-
async function
|
|
7429
|
+
var pollMs = CONFIG_POLL_MIN_MS;
|
|
7430
|
+
async function refreshConfig() {
|
|
6458
7431
|
try {
|
|
6459
7432
|
const res = await rpc("/config");
|
|
6460
7433
|
if (res && res.ok && res.config && res.config.features) {
|
|
@@ -6472,19 +7445,19 @@
|
|
|
6472
7445
|
}
|
|
6473
7446
|
return false;
|
|
6474
7447
|
}
|
|
6475
|
-
function
|
|
7448
|
+
function pollConfig() {
|
|
6476
7449
|
setTimeout(async () => {
|
|
6477
|
-
if (document.hidden)
|
|
6478
|
-
else
|
|
6479
|
-
|
|
6480
|
-
},
|
|
7450
|
+
if (document.hidden) pollMs = CONFIG_POLL_MAX_MS;
|
|
7451
|
+
else pollMs = await refreshConfig() ? CONFIG_POLL_MIN_MS : Math.min(Math.round(pollMs * 1.5), CONFIG_POLL_MAX_MS);
|
|
7452
|
+
pollConfig();
|
|
7453
|
+
}, pollMs);
|
|
6481
7454
|
}
|
|
6482
7455
|
var scanDebounce4 = 0;
|
|
6483
7456
|
function startWsRunningSpin() {
|
|
6484
|
-
if (
|
|
6485
|
-
|
|
6486
|
-
void
|
|
6487
|
-
|
|
7457
|
+
if (installed4 || typeof document === "undefined") return;
|
|
7458
|
+
installed4 = true;
|
|
7459
|
+
void refreshConfig();
|
|
7460
|
+
pollConfig();
|
|
6488
7461
|
const observer2 = new MutationObserver((muts) => {
|
|
6489
7462
|
if (!relevant(muts)) return;
|
|
6490
7463
|
handleRemovals(muts);
|
|
@@ -6505,14 +7478,13 @@
|
|
|
6505
7478
|
});
|
|
6506
7479
|
document.addEventListener("click", (e) => {
|
|
6507
7480
|
if (!e.isTrusted) return;
|
|
6508
|
-
const row = e.target instanceof Element && e.target.closest(WS_SEL);
|
|
7481
|
+
const row = e.target instanceof Element && e.target.closest(WS_SEL());
|
|
6509
7482
|
if (row) wsTouchAt.set(row, Date.now());
|
|
6510
7483
|
}, true);
|
|
6511
7484
|
}
|
|
6512
7485
|
|
|
6513
7486
|
// src/inject/features/idle-reclaim.js
|
|
6514
7487
|
var CHECK_MS = 3e4;
|
|
6515
|
-
var WS_SEL2 = '[data-testid^="workspace-item-"]';
|
|
6516
7488
|
var MIN_MINUTES = 1;
|
|
6517
7489
|
var MAX_MINUTES = 1440;
|
|
6518
7490
|
var idleSince = /* @__PURE__ */ new Map();
|
|
@@ -6520,46 +7492,16 @@
|
|
|
6520
7492
|
var scanDisabledLogged = false;
|
|
6521
7493
|
var bootAt = Date.now();
|
|
6522
7494
|
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() {
|
|
7495
|
+
async function sidebarWorkspaces() {
|
|
6560
7496
|
const out = /* @__PURE__ */ new Set();
|
|
6561
|
-
|
|
6562
|
-
|
|
7497
|
+
const res = await rpc("/projects-v2").catch(() => null);
|
|
7498
|
+
if (res && res.ok && res.available) {
|
|
7499
|
+
for (const proj of res.projects || []) {
|
|
7500
|
+
for (const r of proj.roots || []) {
|
|
7501
|
+
const p = String(r.path || "").replace(/[\/]+$/, "");
|
|
7502
|
+
if (p) out.add(p);
|
|
7503
|
+
}
|
|
7504
|
+
}
|
|
6563
7505
|
}
|
|
6564
7506
|
return out;
|
|
6565
7507
|
}
|
|
@@ -6578,8 +7520,14 @@
|
|
|
6578
7520
|
}
|
|
6579
7521
|
}
|
|
6580
7522
|
async function tryReclaim(ws, cooldownMs) {
|
|
6581
|
-
const
|
|
6582
|
-
if (
|
|
7523
|
+
const auth = await authoritativeIdle(ws);
|
|
7524
|
+
if (auth === null) {
|
|
7525
|
+
const verifiedIdle = await verifyWorkspaceNotRunning(ws);
|
|
7526
|
+
if (!verifiedIdle) {
|
|
7527
|
+
blockUntil.set(ws, Date.now() + cooldownMs);
|
|
7528
|
+
return;
|
|
7529
|
+
}
|
|
7530
|
+
} else if (!auth) {
|
|
6583
7531
|
blockUntil.set(ws, Date.now() + cooldownMs);
|
|
6584
7532
|
return;
|
|
6585
7533
|
}
|
|
@@ -6609,7 +7557,7 @@
|
|
|
6609
7557
|
}
|
|
6610
7558
|
const busy = new Set(snap.running);
|
|
6611
7559
|
busy.add(snap.current);
|
|
6612
|
-
const workspaces = sidebarWorkspaces();
|
|
7560
|
+
const workspaces = await sidebarWorkspaces();
|
|
6613
7561
|
for (const ws of [...idleSince.keys(), ...blockUntil.keys()]) {
|
|
6614
7562
|
if (!workspaces.has(ws)) {
|
|
6615
7563
|
idleSince.delete(ws);
|
|
@@ -6665,24 +7613,34 @@
|
|
|
6665
7613
|
var SYNC_DEBOUNCE_MS = 150;
|
|
6666
7614
|
var SCAN_FALLBACK_MS5 = 5e3;
|
|
6667
7615
|
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"]';
|
|
7616
|
+
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
7617
|
var enabled4 = true;
|
|
6670
7618
|
var rowEl = null;
|
|
6671
7619
|
var origs = null;
|
|
6672
7620
|
var syncTimer = 0;
|
|
6673
7621
|
var widthObserver = null;
|
|
6674
7622
|
var widthObserved = null;
|
|
6675
|
-
function
|
|
6676
|
-
const
|
|
6677
|
-
|
|
6678
|
-
|
|
6679
|
-
|
|
6680
|
-
|
|
6681
|
-
|
|
6682
|
-
|
|
6683
|
-
|
|
6684
|
-
|
|
6685
|
-
|
|
7623
|
+
function findParts() {
|
|
7624
|
+
const newTask = document.querySelector('[data-testid="task-new-button"]');
|
|
7625
|
+
if (!newTask) return null;
|
|
7626
|
+
if (!isNewProjectSidebar()) {
|
|
7627
|
+
const menu = newTask.parentElement;
|
|
7628
|
+
if (!menu || !menu.querySelector('[data-testid="automations-open"]')) return null;
|
|
7629
|
+
const search2 = menu.querySelector('button [class*="lucide-search"]')?.closest("button");
|
|
7630
|
+
const auto2 = menu.querySelector('[data-testid="automations-open"]');
|
|
7631
|
+
const plugin2 = menu.querySelector('[data-testid="plugin-store-sidebar-open"]');
|
|
7632
|
+
return search2 && auto2 && plugin2 ? { newTask, search: search2, auto: auto2, plugin: plugin2, hideEls: [menu] } : null;
|
|
7633
|
+
}
|
|
7634
|
+
const search = document.querySelector('[data-testid="sidebar-search-open"]');
|
|
7635
|
+
const auto = document.querySelector('[data-testid="automations-open"]');
|
|
7636
|
+
const plugin = document.querySelector('[data-testid="plugin-store-sidebar-open"]');
|
|
7637
|
+
if (!search || !auto || !plugin) return null;
|
|
7638
|
+
const hideEls = [.../* @__PURE__ */ new Set([
|
|
7639
|
+
newTask.closest('[data-testid="sidebar-primary-navigation"]'),
|
|
7640
|
+
auto.closest('[data-testid="sidebar-primary-navigation"]'),
|
|
7641
|
+
search.closest('[data-testid="sidebar-search-toolbar"]')
|
|
7642
|
+
])].filter(Boolean);
|
|
7643
|
+
return hideEls.length ? { newTask, search, auto, plugin, hideEls } : null;
|
|
6686
7644
|
}
|
|
6687
7645
|
function nameOf(orig, nameSel, fallback) {
|
|
6688
7646
|
let name = nameSel && (orig.querySelector(nameSel)?.textContent || "").trim();
|
|
@@ -6708,6 +7666,7 @@
|
|
|
6708
7666
|
else btn.removeAttribute("data-active");
|
|
6709
7667
|
if (kind === "auto" || kind === "plugin") btn.setAttribute("aria-pressed", on ? "true" : "false");
|
|
6710
7668
|
}
|
|
7669
|
+
var lastSelectedKey = "";
|
|
6711
7670
|
function syncActive() {
|
|
6712
7671
|
if (!origs || !rowEl) return;
|
|
6713
7672
|
const auto = origs.auto.getAttribute("aria-pressed") === "true";
|
|
@@ -6717,23 +7676,37 @@
|
|
|
6717
7676
|
for (const el of document.querySelectorAll(ROW_SEL)) {
|
|
6718
7677
|
if ((el.className + "").includes("bg-selected")) {
|
|
6719
7678
|
selected = true;
|
|
7679
|
+
lastSelectedKey = el.getAttribute("data-task-item-key") || lastSelectedKey;
|
|
6720
7680
|
break;
|
|
6721
7681
|
}
|
|
6722
7682
|
}
|
|
6723
|
-
|
|
7683
|
+
let newTaskOn = false;
|
|
7684
|
+
if (!selected && lastSelectedKey) {
|
|
7685
|
+
const stillMounted = document.querySelector(`${ROW_SEL}[data-task-item-key="${CSS.escape(lastSelectedKey)}"]`);
|
|
7686
|
+
if (stillMounted) {
|
|
7687
|
+
newTaskOn = !auto && !plugin;
|
|
7688
|
+
lastSelectedKey = "";
|
|
7689
|
+
} else {
|
|
7690
|
+
const btn = rowEl?.querySelector('[data-kind="newTask"]');
|
|
7691
|
+
newTaskOn = btn ? btn.getAttribute("data-active") === "1" : false;
|
|
7692
|
+
}
|
|
7693
|
+
} else if (!selected) {
|
|
7694
|
+
newTaskOn = !auto && !plugin;
|
|
7695
|
+
}
|
|
7696
|
+
setActive("newTask", newTaskOn);
|
|
6724
7697
|
setActive("search", palette);
|
|
6725
7698
|
setActive("auto", auto);
|
|
6726
7699
|
setActive("plugin", plugin);
|
|
6727
7700
|
}
|
|
6728
7701
|
function rebuild() {
|
|
6729
|
-
const
|
|
6730
|
-
if (!menu) return false;
|
|
6731
|
-
const next = originalsOf(menu);
|
|
7702
|
+
const parts = findParts();
|
|
6732
7703
|
const navRow = document.querySelector('[data-testid="desktop-top-nav-back"]')?.parentElement;
|
|
6733
|
-
if (!
|
|
6734
|
-
if (origs && origs.
|
|
6735
|
-
|
|
6736
|
-
|
|
7704
|
+
if (!parts || !navRow) return false;
|
|
7705
|
+
if (origs && origs.hideEls[0] !== parts.hideEls[0]) {
|
|
7706
|
+
for (const el of origs.hideEls) el.classList.remove(HIDE_CLASS);
|
|
7707
|
+
}
|
|
7708
|
+
for (const el of parts.hideEls) el.classList.add(HIDE_CLASS);
|
|
7709
|
+
origs = parts;
|
|
6737
7710
|
rowEl?.remove();
|
|
6738
7711
|
navRow.classList.add("zcodepro-tb-hidden-native");
|
|
6739
7712
|
const L = t();
|
|
@@ -6748,17 +7721,17 @@
|
|
|
6748
7721
|
setTimeout(syncActive, 150);
|
|
6749
7722
|
}
|
|
6750
7723
|
});
|
|
6751
|
-
const newBtn = mk("newTask",
|
|
6752
|
-
const icon = iconOf(
|
|
7724
|
+
const newBtn = mk("newTask", parts.newTask, "span.truncate", L.tbNewTask);
|
|
7725
|
+
const icon = iconOf(parts.newTask);
|
|
6753
7726
|
if (icon) newBtn.append(icon);
|
|
6754
|
-
const searchBtn = mk("search",
|
|
6755
|
-
const sIcon = iconOf(
|
|
7727
|
+
const searchBtn = mk("search", parts.search, "span.truncate", L.tbSearch);
|
|
7728
|
+
const sIcon = iconOf(parts.search);
|
|
6756
7729
|
if (sIcon) searchBtn.append(sIcon);
|
|
6757
|
-
const autoBtn = mk("auto",
|
|
6758
|
-
const aIcon = iconOf(
|
|
7730
|
+
const autoBtn = mk("auto", parts.auto, null, L.tbAutomations);
|
|
7731
|
+
const aIcon = iconOf(parts.auto);
|
|
6759
7732
|
if (aIcon) autoBtn.append(aIcon);
|
|
6760
|
-
const pluginBtn = mk("plugin",
|
|
6761
|
-
const pIcon = iconOf(
|
|
7733
|
+
const pluginBtn = mk("plugin", parts.plugin, null, L.tbPluginStore);
|
|
7734
|
+
const pIcon = iconOf(parts.plugin);
|
|
6762
7735
|
if (pIcon) pluginBtn.append(pIcon);
|
|
6763
7736
|
rowEl = h("div", { class: "zcodepro-tb-row" }, newBtn, searchBtn, autoBtn, pluginBtn);
|
|
6764
7737
|
const updBtn = [...navRow.querySelectorAll("button")].find((b) => /bg-(success|emerald)/.test(b.className || ""));
|
|
@@ -6773,7 +7746,7 @@
|
|
|
6773
7746
|
}
|
|
6774
7747
|
var NARROW_SIDEBAR_PX = 260;
|
|
6775
7748
|
function sidebarTooNarrow() {
|
|
6776
|
-
const scroll = document.querySelector(".flex.flex-1.min-h-0.flex-col.gap-3.overflow-y-auto");
|
|
7749
|
+
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
7750
|
if (!scroll) return false;
|
|
6778
7751
|
if (!widthObserver) widthObserver = new ResizeObserver(() => scheduleSync());
|
|
6779
7752
|
if (widthObserved !== scroll) {
|
|
@@ -6785,18 +7758,18 @@
|
|
|
6785
7758
|
}
|
|
6786
7759
|
function sync() {
|
|
6787
7760
|
if (!enabled4) return;
|
|
6788
|
-
const
|
|
6789
|
-
if (!
|
|
7761
|
+
const parts = findParts();
|
|
7762
|
+
if (!parts) {
|
|
6790
7763
|
if (rowEl) rowEl.style.display = "none";
|
|
6791
7764
|
return;
|
|
6792
7765
|
}
|
|
6793
7766
|
if (sidebarCollapsed() || sidebarTooNarrow()) {
|
|
6794
7767
|
if (rowEl) rowEl.style.display = "none";
|
|
6795
|
-
|
|
7768
|
+
for (const el of parts.hideEls) el.classList.remove(HIDE_CLASS);
|
|
6796
7769
|
document.querySelectorAll(".zcodepro-tb-hidden-native").forEach((el) => el.classList.remove("zcodepro-tb-hidden-native"));
|
|
6797
7770
|
return;
|
|
6798
7771
|
}
|
|
6799
|
-
const alive = origs && origs.
|
|
7772
|
+
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
7773
|
if (!alive && !rebuild()) {
|
|
6801
7774
|
if (rowEl) rowEl.style.display = "none";
|
|
6802
7775
|
setTimeout(scheduleSync, 400);
|
|
@@ -6805,7 +7778,7 @@
|
|
|
6805
7778
|
}
|
|
6806
7779
|
const navRow = document.querySelector('[data-testid="desktop-top-nav-back"]')?.parentElement;
|
|
6807
7780
|
if (navRow) navRow.classList.add("zcodepro-tb-hidden-native");
|
|
6808
|
-
|
|
7781
|
+
for (const el of parts.hideEls) el.classList.add(HIDE_CLASS);
|
|
6809
7782
|
if (rowEl) rowEl.style.display = "";
|
|
6810
7783
|
syncActive();
|
|
6811
7784
|
}
|
|
@@ -6839,12 +7812,12 @@
|
|
|
6839
7812
|
rowEl?.remove();
|
|
6840
7813
|
rowEl = null;
|
|
6841
7814
|
if (origs) {
|
|
6842
|
-
origs.
|
|
7815
|
+
for (const el of origs.hideEls) el.classList.remove(HIDE_CLASS);
|
|
6843
7816
|
document.querySelectorAll(".zcodepro-tb-hidden-native").forEach((el) => el.classList.remove("zcodepro-tb-hidden-native"));
|
|
6844
7817
|
origs = null;
|
|
6845
7818
|
}
|
|
6846
7819
|
}
|
|
6847
|
-
async function
|
|
7820
|
+
async function refreshConfig2() {
|
|
6848
7821
|
const cfg = await getConfig(true).catch(() => null);
|
|
6849
7822
|
enabled4 = !cfg || !cfg.features || cfg.features.toolbarIcons !== false;
|
|
6850
7823
|
if (enabled4) sync();
|
|
@@ -6853,9 +7826,9 @@
|
|
|
6853
7826
|
function startToolbarIcons() {
|
|
6854
7827
|
ensureStyle();
|
|
6855
7828
|
window.addEventListener("zcodepro:config-changed", () => {
|
|
6856
|
-
void
|
|
7829
|
+
void refreshConfig2();
|
|
6857
7830
|
});
|
|
6858
|
-
void
|
|
7831
|
+
void refreshConfig2();
|
|
6859
7832
|
new MutationObserver((muts) => {
|
|
6860
7833
|
if (relevantMutations(muts)) scheduleSync();
|
|
6861
7834
|
}).observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ["class", "aria-pressed"] });
|
|
@@ -6877,8 +7850,8 @@
|
|
|
6877
7850
|
var syncTimer2 = 0;
|
|
6878
7851
|
function findPinnedHeader() {
|
|
6879
7852
|
for (const h3 of document.querySelectorAll("h3")) {
|
|
6880
|
-
const
|
|
6881
|
-
if (
|
|
7853
|
+
const list = h3.nextElementSibling;
|
|
7854
|
+
if (list && list.querySelector("li[data-task-item-key]")) return h3;
|
|
6882
7855
|
}
|
|
6883
7856
|
return null;
|
|
6884
7857
|
}
|
|
@@ -6974,7 +7947,7 @@
|
|
|
6974
7947
|
h3.parentElement?.classList.remove(COLLAPSED_CLASS);
|
|
6975
7948
|
}
|
|
6976
7949
|
}
|
|
6977
|
-
async function
|
|
7950
|
+
async function refreshConfig3() {
|
|
6978
7951
|
const cfg = await getConfig(true).catch(() => null);
|
|
6979
7952
|
enabled5 = !cfg || !cfg.features || cfg.features.pinnedCollapse !== false;
|
|
6980
7953
|
if (enabled5) sync2();
|
|
@@ -6983,9 +7956,9 @@
|
|
|
6983
7956
|
function startPinnedCollapse() {
|
|
6984
7957
|
ensureStyle();
|
|
6985
7958
|
window.addEventListener("zcodepro:config-changed", () => {
|
|
6986
|
-
void
|
|
7959
|
+
void refreshConfig3();
|
|
6987
7960
|
});
|
|
6988
|
-
void
|
|
7961
|
+
void refreshConfig3();
|
|
6989
7962
|
new MutationObserver((muts) => {
|
|
6990
7963
|
if (relevantMutations2(muts)) scheduleSync2();
|
|
6991
7964
|
}).observe(document.body, { childList: true, subtree: true });
|
|
@@ -7060,6 +8033,10 @@
|
|
|
7060
8033
|
void startAliasWatcher();
|
|
7061
8034
|
} catch {
|
|
7062
8035
|
}
|
|
8036
|
+
try {
|
|
8037
|
+
startAliasMigrationWatcher();
|
|
8038
|
+
} catch {
|
|
8039
|
+
}
|
|
7063
8040
|
try {
|
|
7064
8041
|
startTaskOrderWatcher();
|
|
7065
8042
|
} catch {
|
|
@@ -7080,10 +8057,6 @@
|
|
|
7080
8057
|
startImageMenu();
|
|
7081
8058
|
} catch {
|
|
7082
8059
|
}
|
|
7083
|
-
try {
|
|
7084
|
-
startPinnedExpandSuppression();
|
|
7085
|
-
} catch {
|
|
7086
|
-
}
|
|
7087
8060
|
try {
|
|
7088
8061
|
startWsRunningSpin();
|
|
7089
8062
|
} catch {
|