zcode-pro 0.20.2 → 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 +1433 -434
- 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-gen.js +41 -0
- 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();
|
|
@@ -3154,64 +3966,10 @@
|
|
|
3154
3966
|
)
|
|
3155
3967
|
);
|
|
3156
3968
|
let activeTab = "features";
|
|
3157
|
-
const pluginsStatusLine = h("span", { class: "text-ui-xs/relaxed text-foreground-subtle" }, "\u2026");
|
|
3158
|
-
const pluginsBtn = btnSmall(L.pluginsCheckNow, () => {
|
|
3159
|
-
void runPluginsUpdate();
|
|
3160
|
-
});
|
|
3161
|
-
const runPluginsUpdate = async () => {
|
|
3162
|
-
pluginsBtn.disabled = true;
|
|
3163
|
-
pluginsStatusLine.textContent = L.pluginsUpdating;
|
|
3164
|
-
const res = await rpc("/plugins/update", { method: "POST", body: {} });
|
|
3165
|
-
pluginsBtn.disabled = false;
|
|
3166
|
-
if (!res.ok) {
|
|
3167
|
-
pluginsStatusLine.textContent = "";
|
|
3168
|
-
showToast(L.pluginsUpdateFailed + ": " + errText(res), "error");
|
|
3169
|
-
return;
|
|
3170
|
-
}
|
|
3171
|
-
pluginsStatusLine.textContent = res.updated > 0 ? L.pluginsUpdatedDone.replaceAll("{n}", String(res.updated)) : L.pluginsUpToDate;
|
|
3172
|
-
showToast(pluginsStatusLine.textContent, "success");
|
|
3173
|
-
};
|
|
3174
|
-
void (async () => {
|
|
3175
|
-
const res = await rpc("/plugins/status");
|
|
3176
|
-
if (!res.ok) {
|
|
3177
|
-
pluginsStatusLine.textContent = "";
|
|
3178
|
-
return;
|
|
3179
|
-
}
|
|
3180
|
-
pluginsStatusLine.textContent = (res.updates || []).length > 0 ? L.pluginsUpdatesFound.replaceAll("{n}", String(res.updates.length)) : L.pluginsUpToDate;
|
|
3181
|
-
})();
|
|
3182
|
-
const PLUGINS_REPO_URL = "https://github.com/duanluan/zcode-plugins";
|
|
3183
|
-
const repoName = "zcode-plugins";
|
|
3184
|
-
const titleParts = L.pluginsUpdateTitle.split(repoName);
|
|
3185
|
-
const pluginsTitle = h("div", { class: "truncate text-ui-sm font-medium text-foreground" });
|
|
3186
|
-
if (titleParts.length === 2 && typeof window.zcode?.openExternal === "function") {
|
|
3187
|
-
pluginsTitle.append(
|
|
3188
|
-
titleParts[0],
|
|
3189
|
-
h("span", {
|
|
3190
|
-
class: "cursor-pointer underline-offset-4 hover:underline",
|
|
3191
|
-
title: PLUGINS_REPO_URL,
|
|
3192
|
-
onClick: () => openExternal(PLUGINS_REPO_URL)
|
|
3193
|
-
}, repoName),
|
|
3194
|
-
titleParts[1]
|
|
3195
|
-
);
|
|
3196
|
-
} else {
|
|
3197
|
-
pluginsTitle.append(L.pluginsUpdateTitle);
|
|
3198
|
-
}
|
|
3199
|
-
const pluginsCard = h(
|
|
3200
|
-
"div",
|
|
3201
|
-
{ class: "mt-3 flex items-center justify-between gap-2 rounded-xl border border-border p-2" },
|
|
3202
|
-
h(
|
|
3203
|
-
"div",
|
|
3204
|
-
{ class: "min-w-0" },
|
|
3205
|
-
pluginsTitle,
|
|
3206
|
-
h("div", { class: "mt-0.5 truncate text-ui-xs/relaxed text-foreground-subtle" }, pluginsStatusLine)
|
|
3207
|
-
),
|
|
3208
|
-
pluginsBtn
|
|
3209
|
-
);
|
|
3210
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) : "";
|
|
@@ -5892,9 +6686,23 @@
|
|
|
5892
6686
|
return ((el ? el.textContent : r.innerText) || "").trim();
|
|
5893
6687
|
}).filter(Boolean);
|
|
5894
6688
|
}
|
|
6689
|
+
var URL_RE = /https?:\/\/[^\s\u4e00-\u9fff\u3000-\u303f\uff00-\uffef]+/g;
|
|
6690
|
+
function assistantText() {
|
|
6691
|
+
const els = [...document.querySelectorAll('[class*="@md/conversation"] [class*="assistant-row"]')].filter((e) => !e.querySelector("[data-is-streaming]"));
|
|
6692
|
+
const last = els[els.length - 1];
|
|
6693
|
+
if (!last) return "";
|
|
6694
|
+
const text = (last.innerText || "").replace(URL_RE, "").trim();
|
|
6695
|
+
return text.slice(0, 600);
|
|
6696
|
+
}
|
|
6697
|
+
function linkDominant(t2) {
|
|
6698
|
+
const raw = t2.replace(/\s+/g, "");
|
|
6699
|
+
if (!raw) return true;
|
|
6700
|
+
const stripped = raw.replace(URL_RE, "");
|
|
6701
|
+
return stripped.length < raw.length / 3;
|
|
6702
|
+
}
|
|
5895
6703
|
async function onNewTaskRow(key) {
|
|
5896
6704
|
const selDeadline = Date.now() + SELECT_WAIT_MS;
|
|
5897
|
-
while (currentKey() !== key && Date.now() < selDeadline) await
|
|
6705
|
+
while (currentKey() !== key && Date.now() < selDeadline) await sleep2(200);
|
|
5898
6706
|
if (currentKey() !== key) return;
|
|
5899
6707
|
const cfg = await getConfig().catch(() => null);
|
|
5900
6708
|
if (!cfg || !cfg.titleGen || cfg.titleGen.enabled !== true) return;
|
|
@@ -5906,7 +6714,7 @@
|
|
|
5906
6714
|
while (Date.now() < msgDeadline) {
|
|
5907
6715
|
texts = userTexts();
|
|
5908
6716
|
if (texts.length) break;
|
|
5909
|
-
await
|
|
6717
|
+
await sleep2(400);
|
|
5910
6718
|
}
|
|
5911
6719
|
if (!texts.length) return;
|
|
5912
6720
|
let assistantSeen = false;
|
|
@@ -5929,7 +6737,7 @@
|
|
|
5929
6737
|
let lastChange = Date.now();
|
|
5930
6738
|
try {
|
|
5931
6739
|
while (Date.now() - startAt < COLLECT_MAX_MS) {
|
|
5932
|
-
await
|
|
6740
|
+
await sleep2(500);
|
|
5933
6741
|
if (currentKey() !== key) {
|
|
5934
6742
|
lastChange = Date.now();
|
|
5935
6743
|
continue;
|
|
@@ -5946,11 +6754,23 @@
|
|
|
5946
6754
|
convObserver.disconnect();
|
|
5947
6755
|
}
|
|
5948
6756
|
if (!texts.length) return;
|
|
6757
|
+
if (linkDominant(texts.join("\n"))) {
|
|
6758
|
+
const deadline = Date.now() + 6e4;
|
|
6759
|
+
while (Date.now() < deadline) {
|
|
6760
|
+
await sleep2(2e3);
|
|
6761
|
+
if (currentKey() !== key) continue;
|
|
6762
|
+
const a = assistantText();
|
|
6763
|
+
if (a && a.length > 80) {
|
|
6764
|
+
texts.push(`\uFF08\u9996\u8F6E\u56DE\u7B54\u6458\u8981\uFF09${a}`);
|
|
6765
|
+
break;
|
|
6766
|
+
}
|
|
6767
|
+
}
|
|
6768
|
+
}
|
|
5949
6769
|
const callTitleGen = () => rpc("/title-gen/run", { method: "POST", body: { sessId, text: texts.join("\n") } }).catch(() => null);
|
|
5950
6770
|
let res = await callTitleGen();
|
|
5951
6771
|
for (const delay of [5e3, 2e4]) {
|
|
5952
6772
|
if (res && res.ok) break;
|
|
5953
|
-
await
|
|
6773
|
+
await sleep2(delay);
|
|
5954
6774
|
res = await callTitleGen();
|
|
5955
6775
|
}
|
|
5956
6776
|
if (res && res.ok && res.written && res.title) {
|
|
@@ -6007,115 +6827,8 @@
|
|
|
6007
6827
|
});
|
|
6008
6828
|
}
|
|
6009
6829
|
|
|
6010
|
-
// src/inject/features/pinned-expand.js
|
|
6011
|
-
var installed4 = false;
|
|
6012
|
-
var keepCollapsed = false;
|
|
6013
|
-
var CONFIG_POLL_MIN_MS = 5e3;
|
|
6014
|
-
var CONFIG_POLL_MAX_MS = 6e4;
|
|
6015
|
-
var pollMs = CONFIG_POLL_MIN_MS;
|
|
6016
|
-
async function refreshConfig() {
|
|
6017
|
-
try {
|
|
6018
|
-
const res = await rpc("/config");
|
|
6019
|
-
if (res && res.ok && res.config && res.config.features) {
|
|
6020
|
-
const next = res.config.features.pinnedKeepCollapsed !== false;
|
|
6021
|
-
if (next !== keepCollapsed) {
|
|
6022
|
-
keepCollapsed = next;
|
|
6023
|
-
return true;
|
|
6024
|
-
}
|
|
6025
|
-
}
|
|
6026
|
-
} catch {
|
|
6027
|
-
}
|
|
6028
|
-
return false;
|
|
6029
|
-
}
|
|
6030
|
-
function pollConfig() {
|
|
6031
|
-
setTimeout(async () => {
|
|
6032
|
-
if (document.hidden) pollMs = CONFIG_POLL_MAX_MS;
|
|
6033
|
-
else pollMs = await refreshConfig() ? CONFIG_POLL_MIN_MS : Math.min(Math.round(pollMs * 1.5), CONFIG_POLL_MAX_MS);
|
|
6034
|
-
pollConfig();
|
|
6035
|
-
}, pollMs);
|
|
6036
|
-
}
|
|
6037
|
-
function startPinnedExpandSuppression() {
|
|
6038
|
-
if (installed4 || typeof document === "undefined") return;
|
|
6039
|
-
installed4 = true;
|
|
6040
|
-
void refreshConfig();
|
|
6041
|
-
pollConfig();
|
|
6042
|
-
document.addEventListener("visibilitychange", () => {
|
|
6043
|
-
if (!document.hidden) void refreshConfig();
|
|
6044
|
-
});
|
|
6045
|
-
document.addEventListener("click", (e) => {
|
|
6046
|
-
if (!keepCollapsed) return;
|
|
6047
|
-
const taskRow = e.target.closest && e.target.closest('[data-testid^="task-item-"]');
|
|
6048
|
-
if (!taskRow) return;
|
|
6049
|
-
const key = taskRow.getAttribute("data-task-item-key") || "";
|
|
6050
|
-
const sep = key.lastIndexOf(":");
|
|
6051
|
-
if (sep <= 0) return;
|
|
6052
|
-
const wsKey = key.slice(0, sep);
|
|
6053
|
-
const wsRow = document.querySelector(`[data-testid="workspace-item-${cssEscape(wsKey)}"]`);
|
|
6054
|
-
if (!wsRow || wsRow.getAttribute("aria-expanded") !== "false") return;
|
|
6055
|
-
const head = wsRow.matches("[aria-expanded]") ? wsRow : wsRow.querySelector("[aria-expanded]");
|
|
6056
|
-
if (!head) return;
|
|
6057
|
-
collapseAfterContentLoaded(wsRow);
|
|
6058
|
-
}, true);
|
|
6059
|
-
document.addEventListener("click", (e) => {
|
|
6060
|
-
const row = e.target.closest && e.target.closest('[data-testid^="workspace-item-"]');
|
|
6061
|
-
if (row) row.__zcodeproUserTouched = Date.now();
|
|
6062
|
-
}, true);
|
|
6063
|
-
}
|
|
6064
|
-
function currentTaskRow() {
|
|
6065
|
-
for (const el of document.querySelectorAll("[data-task-item-key]")) {
|
|
6066
|
-
if ((el.className + "").includes("bg-selected")) return el;
|
|
6067
|
-
}
|
|
6068
|
-
return null;
|
|
6069
|
-
}
|
|
6070
|
-
function collapseNavSafe(head) {
|
|
6071
|
-
const cur = currentTaskRow();
|
|
6072
|
-
const backKey = cur ? cur.getAttribute("data-task-item-key") : "";
|
|
6073
|
-
head.dispatchEvent(new MouseEvent("click", { bubbles: true, cancelable: true }));
|
|
6074
|
-
if (!backKey) return;
|
|
6075
|
-
const back = cur && cur.isConnected ? cur : document.querySelector(`[data-task-item-key="${cssEscape(backKey)}"]`);
|
|
6076
|
-
if (back) back.dispatchEvent(new MouseEvent("click", { bubbles: true, cancelable: true }));
|
|
6077
|
-
}
|
|
6078
|
-
function collapseAfterContentLoaded(wsRow) {
|
|
6079
|
-
const deadline = Date.now() + 25e3;
|
|
6080
|
-
let lastLen = (document.querySelector("main") || document.body).innerText.length;
|
|
6081
|
-
let grewAt = 0;
|
|
6082
|
-
let settledAt = 0;
|
|
6083
|
-
const headOf = () => {
|
|
6084
|
-
const h2 = wsRow.matches("[aria-expanded]") ? wsRow : wsRow.querySelector("[aria-expanded]");
|
|
6085
|
-
return h2 || null;
|
|
6086
|
-
};
|
|
6087
|
-
const userTouched2 = () => wsRow.__zcodeproUserTouched && Date.now() - wsRow.__zcodeproUserTouched < 800;
|
|
6088
|
-
const tick2 = () => {
|
|
6089
|
-
if (!keepCollapsed || Date.now() > deadline || !wsRow.isConnected) return done();
|
|
6090
|
-
const len = (document.querySelector("main") || document.body).innerText.length;
|
|
6091
|
-
if (len > lastLen) grewAt = Date.now();
|
|
6092
|
-
if (grewAt && Date.now() - grewAt >= 1e3) settledAt = settledAt || Date.now();
|
|
6093
|
-
lastLen = len;
|
|
6094
|
-
const head = headOf();
|
|
6095
|
-
if (head && head.getAttribute("aria-expanded") === "true" && !userTouched2()) {
|
|
6096
|
-
collapseNavSafe(head);
|
|
6097
|
-
}
|
|
6098
|
-
if (settledAt && Date.now() - settledAt >= 1e3) {
|
|
6099
|
-
const h2 = headOf();
|
|
6100
|
-
if (h2 && h2.getAttribute("aria-expanded") === "true" && !userTouched2()) {
|
|
6101
|
-
collapseNavSafe(h2);
|
|
6102
|
-
}
|
|
6103
|
-
return done();
|
|
6104
|
-
}
|
|
6105
|
-
setTimeout(tick2, 200);
|
|
6106
|
-
};
|
|
6107
|
-
const done = () => {
|
|
6108
|
-
wsRow.__zcodeproSuppending = false;
|
|
6109
|
-
};
|
|
6110
|
-
wsRow.__zcodeproSuppending = true;
|
|
6111
|
-
setTimeout(tick2, 400);
|
|
6112
|
-
}
|
|
6113
|
-
function cssEscape(s) {
|
|
6114
|
-
return String(s).replace(/(["\\\]])/g, "\\$1");
|
|
6115
|
-
}
|
|
6116
|
-
|
|
6117
6830
|
// src/inject/features/ws-running.js
|
|
6118
|
-
var
|
|
6831
|
+
var installed4 = false;
|
|
6119
6832
|
var enabled3 = true;
|
|
6120
6833
|
var SCAN_DEBOUNCE_MS4 = 150;
|
|
6121
6834
|
var SCAN_FALLBACK_MS4 = 5e3;
|
|
@@ -6124,34 +6837,148 @@
|
|
|
6124
6837
|
var PEEK_SETTLE_MS = 160;
|
|
6125
6838
|
var PEEK_MAX_MS = 1500;
|
|
6126
6839
|
var PEEK_UNMOUNT_WAIT_MS = 800;
|
|
6127
|
-
var
|
|
6128
|
-
var
|
|
6840
|
+
var CONFIG_POLL_MIN_MS = 5e3;
|
|
6841
|
+
var CONFIG_POLL_MAX_MS = 6e4;
|
|
6129
6842
|
var TASK_SEL3 = "[data-task-item-key]";
|
|
6130
|
-
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
|
+
}
|
|
6131
6906
|
var runningByWs = /* @__PURE__ */ new Map();
|
|
6132
6907
|
var peekTimers = /* @__PURE__ */ new Map();
|
|
6133
6908
|
var activePeeks = /* @__PURE__ */ new Set();
|
|
6134
6909
|
var peekedWs = /* @__PURE__ */ new Set();
|
|
6135
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
|
+
}
|
|
6136
6971
|
function workspaceOf2(key) {
|
|
6137
6972
|
const i = key.indexOf(":sess_");
|
|
6138
6973
|
return i > 0 ? key.slice(0, i) : key;
|
|
6139
6974
|
}
|
|
6140
|
-
function findWsRow(ws) {
|
|
6141
|
-
return document.querySelector(`[data-testid="workspace-item-${CSS.escape(ws)}"]`);
|
|
6142
|
-
}
|
|
6143
6975
|
function wsHead(row) {
|
|
6144
6976
|
return row.matches("[aria-expanded]") ? row : row.querySelector("[aria-expanded]");
|
|
6145
6977
|
}
|
|
6146
|
-
function isRunningRow(el) {
|
|
6147
|
-
const holder = el.firstElementChild && el.firstElementChild.querySelector(":scope > span");
|
|
6148
|
-
if (!holder) return false;
|
|
6149
|
-
return [...holder.children].some((c) => c.tagName === "svg" && (c.getAttribute("class") || "").includes("lucide-loader"));
|
|
6150
|
-
}
|
|
6151
6978
|
function domRowsOf(ws) {
|
|
6152
6979
|
return [...document.querySelectorAll(TASK_SEL3)].filter((e) => workspaceOf2(e.getAttribute("data-task-item-key") || "") === ws);
|
|
6153
6980
|
}
|
|
6154
|
-
function
|
|
6981
|
+
function currentTaskRow() {
|
|
6155
6982
|
for (const el of document.querySelectorAll(TASK_SEL3)) {
|
|
6156
6983
|
if ((el.className + "").includes("bg-selected")) return el;
|
|
6157
6984
|
}
|
|
@@ -6164,7 +6991,7 @@
|
|
|
6164
6991
|
}
|
|
6165
6992
|
};
|
|
6166
6993
|
function toggleNavSafe(head) {
|
|
6167
|
-
const cur =
|
|
6994
|
+
const cur = currentTaskRow();
|
|
6168
6995
|
const backKey = cur ? cur.getAttribute("data-task-item-key") : "";
|
|
6169
6996
|
synthClick(head);
|
|
6170
6997
|
if (!backKey) return;
|
|
@@ -6232,17 +7059,169 @@
|
|
|
6232
7059
|
}
|
|
6233
7060
|
function apply() {
|
|
6234
7061
|
const seen = /* @__PURE__ */ new Set();
|
|
6235
|
-
for (const row of document.querySelectorAll(WS_SEL)) {
|
|
6236
|
-
const path = row
|
|
7062
|
+
for (const row of document.querySelectorAll(WS_SEL())) {
|
|
7063
|
+
const path = rowPath(row);
|
|
7064
|
+
if (!path) continue;
|
|
6237
7065
|
seen.add(path);
|
|
6238
7066
|
const head = wsHead(row);
|
|
6239
7067
|
const collapsed = !head || head.getAttribute("aria-expanded") === "false";
|
|
6240
|
-
const
|
|
6241
|
-
const
|
|
6242
|
-
|
|
6243
|
-
|
|
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();
|
|
6244
7076
|
for (const ws of [...runningByWs.keys()]) if (!seen.has(ws)) runningByWs.delete(ws);
|
|
6245
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
|
+
}
|
|
6246
7225
|
function schedulePeek(ws, delay) {
|
|
6247
7226
|
clearTimeout(peekTimers.get(ws));
|
|
6248
7227
|
peekTimers.set(ws, setTimeout(() => {
|
|
@@ -6274,6 +7253,24 @@
|
|
|
6274
7253
|
}
|
|
6275
7254
|
var peekChain = Promise.resolve();
|
|
6276
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
|
+
}
|
|
6277
7274
|
const run = () => peekInner(ws, opts);
|
|
6278
7275
|
const p = peekChain.then(run, run);
|
|
6279
7276
|
peekChain = p.catch(() => {
|
|
@@ -6285,7 +7282,7 @@
|
|
|
6285
7282
|
const row = findWsRow(ws);
|
|
6286
7283
|
const head = row && wsHead(row);
|
|
6287
7284
|
if (!row || !head || head.getAttribute("aria-expanded") !== "false") return false;
|
|
6288
|
-
if (!
|
|
7285
|
+
if (!currentTaskRow()) {
|
|
6289
7286
|
schedulePeek(ws, PEEK_REPEAT_MS);
|
|
6290
7287
|
return false;
|
|
6291
7288
|
}
|
|
@@ -6301,9 +7298,10 @@
|
|
|
6301
7298
|
document.body.append(frozen);
|
|
6302
7299
|
row.style.visibility = "hidden";
|
|
6303
7300
|
const hider = installPeekHider(ws);
|
|
7301
|
+
let readOk = false;
|
|
6304
7302
|
try {
|
|
6305
7303
|
toggleNavSafe(head);
|
|
6306
|
-
await settleAndRead(ws);
|
|
7304
|
+
readOk = await settleAndRead(ws);
|
|
6307
7305
|
const rowNow = findWsRow(ws) || row;
|
|
6308
7306
|
const headNow = wsHead(rowNow);
|
|
6309
7307
|
if (headNow && headNow.getAttribute("aria-expanded") === "true" && !userTouched(rowNow)) {
|
|
@@ -6319,10 +7317,10 @@
|
|
|
6319
7317
|
apply();
|
|
6320
7318
|
const set = runningByWs.get(ws);
|
|
6321
7319
|
if (set && set.size && enabled3) schedulePeek(ws, PEEK_REPEAT_MS);
|
|
6322
|
-
return
|
|
7320
|
+
return readOk;
|
|
6323
7321
|
}
|
|
6324
7322
|
function wsRunningSnapshot() {
|
|
6325
|
-
const curKey =
|
|
7323
|
+
const curKey = currentTaskRow()?.getAttribute("data-task-item-key") || "";
|
|
6326
7324
|
return {
|
|
6327
7325
|
running: [...runningByWs.entries()].filter(([, set]) => set.size > 0).map(([ws]) => ws),
|
|
6328
7326
|
current: curKey ? workspaceOf2(curKey) || null : null
|
|
@@ -6352,6 +7350,7 @@
|
|
|
6352
7350
|
const t0 = Date.now();
|
|
6353
7351
|
let lastCount = -1;
|
|
6354
7352
|
let stableAt = 0;
|
|
7353
|
+
let zeroRows = false;
|
|
6355
7354
|
const timer = setInterval(() => {
|
|
6356
7355
|
const rows = domRowsOf(ws);
|
|
6357
7356
|
const elapsed = Date.now() - t0;
|
|
@@ -6363,7 +7362,7 @@
|
|
|
6363
7362
|
if (!settled && elapsed < PEEK_MAX_MS) return;
|
|
6364
7363
|
clearInterval(timer);
|
|
6365
7364
|
if (lastCount === 0) {
|
|
6366
|
-
|
|
7365
|
+
zeroRows = true;
|
|
6367
7366
|
} else {
|
|
6368
7367
|
let set = runningByWs.get(ws);
|
|
6369
7368
|
if (!set) {
|
|
@@ -6376,7 +7375,7 @@
|
|
|
6376
7375
|
else set.delete(key);
|
|
6377
7376
|
}
|
|
6378
7377
|
}
|
|
6379
|
-
resolve();
|
|
7378
|
+
resolve(!zeroRows);
|
|
6380
7379
|
}, 80);
|
|
6381
7380
|
});
|
|
6382
7381
|
}
|
|
@@ -6417,18 +7416,18 @@
|
|
|
6417
7416
|
}
|
|
6418
7417
|
function relevant(muts) {
|
|
6419
7418
|
for (const m of muts) {
|
|
6420
|
-
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;
|
|
6421
7420
|
for (const n of m.addedNodes) {
|
|
6422
|
-
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;
|
|
6423
7422
|
}
|
|
6424
7423
|
for (const n of m.removedNodes) {
|
|
6425
|
-
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;
|
|
6426
7425
|
}
|
|
6427
7426
|
}
|
|
6428
7427
|
return false;
|
|
6429
7428
|
}
|
|
6430
|
-
var
|
|
6431
|
-
async function
|
|
7429
|
+
var pollMs = CONFIG_POLL_MIN_MS;
|
|
7430
|
+
async function refreshConfig() {
|
|
6432
7431
|
try {
|
|
6433
7432
|
const res = await rpc("/config");
|
|
6434
7433
|
if (res && res.ok && res.config && res.config.features) {
|
|
@@ -6446,19 +7445,19 @@
|
|
|
6446
7445
|
}
|
|
6447
7446
|
return false;
|
|
6448
7447
|
}
|
|
6449
|
-
function
|
|
7448
|
+
function pollConfig() {
|
|
6450
7449
|
setTimeout(async () => {
|
|
6451
|
-
if (document.hidden)
|
|
6452
|
-
else
|
|
6453
|
-
|
|
6454
|
-
},
|
|
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);
|
|
6455
7454
|
}
|
|
6456
7455
|
var scanDebounce4 = 0;
|
|
6457
7456
|
function startWsRunningSpin() {
|
|
6458
|
-
if (
|
|
6459
|
-
|
|
6460
|
-
void
|
|
6461
|
-
|
|
7457
|
+
if (installed4 || typeof document === "undefined") return;
|
|
7458
|
+
installed4 = true;
|
|
7459
|
+
void refreshConfig();
|
|
7460
|
+
pollConfig();
|
|
6462
7461
|
const observer2 = new MutationObserver((muts) => {
|
|
6463
7462
|
if (!relevant(muts)) return;
|
|
6464
7463
|
handleRemovals(muts);
|
|
@@ -6479,14 +7478,13 @@
|
|
|
6479
7478
|
});
|
|
6480
7479
|
document.addEventListener("click", (e) => {
|
|
6481
7480
|
if (!e.isTrusted) return;
|
|
6482
|
-
const row = e.target instanceof Element && e.target.closest(WS_SEL);
|
|
7481
|
+
const row = e.target instanceof Element && e.target.closest(WS_SEL());
|
|
6483
7482
|
if (row) wsTouchAt.set(row, Date.now());
|
|
6484
7483
|
}, true);
|
|
6485
7484
|
}
|
|
6486
7485
|
|
|
6487
7486
|
// src/inject/features/idle-reclaim.js
|
|
6488
7487
|
var CHECK_MS = 3e4;
|
|
6489
|
-
var WS_SEL2 = '[data-testid^="workspace-item-"]';
|
|
6490
7488
|
var MIN_MINUTES = 1;
|
|
6491
7489
|
var MAX_MINUTES = 1440;
|
|
6492
7490
|
var idleSince = /* @__PURE__ */ new Map();
|
|
@@ -6494,46 +7492,16 @@
|
|
|
6494
7492
|
var scanDisabledLogged = false;
|
|
6495
7493
|
var bootAt = Date.now();
|
|
6496
7494
|
var startupSweepDone = false;
|
|
6497
|
-
|
|
6498
|
-
function findServices() {
|
|
6499
|
-
if (servicesRef) return servicesRef;
|
|
6500
|
-
try {
|
|
6501
|
-
const rootEl = document.getElementById("root");
|
|
6502
|
-
const containerKey = rootEl && Object.keys(rootEl).find((k) => k.startsWith("__reactContainer$"));
|
|
6503
|
-
if (!containerKey) return null;
|
|
6504
|
-
const seen = /* @__PURE__ */ new Set();
|
|
6505
|
-
let found = null;
|
|
6506
|
-
const scanObj = (o) => {
|
|
6507
|
-
if (!o || typeof o !== "object" || seen.has(o) || found) return;
|
|
6508
|
-
seen.add(o);
|
|
6509
|
-
const ts = o.zcodeTaskService;
|
|
6510
|
-
if (ts && typeof ts === "object" && typeof ts.releaseWorkspacePreparation === "function") found = o;
|
|
6511
|
-
};
|
|
6512
|
-
let visited = 0;
|
|
6513
|
-
const visit = (f) => {
|
|
6514
|
-
if (!f || found || visited > 6e4) return;
|
|
6515
|
-
visited++;
|
|
6516
|
-
for (const holder of [f.memoizedProps, f.memoizedState]) {
|
|
6517
|
-
if (!holder || typeof holder !== "object") continue;
|
|
6518
|
-
scanObj(holder);
|
|
6519
|
-
for (const v of Object.values(holder)) {
|
|
6520
|
-
if (v && typeof v === "object") scanObj(v);
|
|
6521
|
-
}
|
|
6522
|
-
}
|
|
6523
|
-
visit(f.child);
|
|
6524
|
-
visit(f.sibling);
|
|
6525
|
-
};
|
|
6526
|
-
visit(rootEl[containerKey]);
|
|
6527
|
-
if (found) servicesRef = found;
|
|
6528
|
-
return found;
|
|
6529
|
-
} catch {
|
|
6530
|
-
return null;
|
|
6531
|
-
}
|
|
6532
|
-
}
|
|
6533
|
-
function sidebarWorkspaces() {
|
|
7495
|
+
async function sidebarWorkspaces() {
|
|
6534
7496
|
const out = /* @__PURE__ */ new Set();
|
|
6535
|
-
|
|
6536
|
-
|
|
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
|
+
}
|
|
6537
7505
|
}
|
|
6538
7506
|
return out;
|
|
6539
7507
|
}
|
|
@@ -6552,8 +7520,14 @@
|
|
|
6552
7520
|
}
|
|
6553
7521
|
}
|
|
6554
7522
|
async function tryReclaim(ws, cooldownMs) {
|
|
6555
|
-
const
|
|
6556
|
-
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) {
|
|
6557
7531
|
blockUntil.set(ws, Date.now() + cooldownMs);
|
|
6558
7532
|
return;
|
|
6559
7533
|
}
|
|
@@ -6583,7 +7557,7 @@
|
|
|
6583
7557
|
}
|
|
6584
7558
|
const busy = new Set(snap.running);
|
|
6585
7559
|
busy.add(snap.current);
|
|
6586
|
-
const workspaces = sidebarWorkspaces();
|
|
7560
|
+
const workspaces = await sidebarWorkspaces();
|
|
6587
7561
|
for (const ws of [...idleSince.keys(), ...blockUntil.keys()]) {
|
|
6588
7562
|
if (!workspaces.has(ws)) {
|
|
6589
7563
|
idleSince.delete(ws);
|
|
@@ -6639,24 +7613,34 @@
|
|
|
6639
7613
|
var SYNC_DEBOUNCE_MS = 150;
|
|
6640
7614
|
var SCAN_FALLBACK_MS5 = 5e3;
|
|
6641
7615
|
var ROW_SEL = "[data-task-item-key]";
|
|
6642
|
-
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"]';
|
|
6643
7617
|
var enabled4 = true;
|
|
6644
7618
|
var rowEl = null;
|
|
6645
7619
|
var origs = null;
|
|
6646
7620
|
var syncTimer = 0;
|
|
6647
7621
|
var widthObserver = null;
|
|
6648
7622
|
var widthObserved = null;
|
|
6649
|
-
function
|
|
6650
|
-
const
|
|
6651
|
-
|
|
6652
|
-
|
|
6653
|
-
|
|
6654
|
-
|
|
6655
|
-
|
|
6656
|
-
|
|
6657
|
-
|
|
6658
|
-
|
|
6659
|
-
|
|
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;
|
|
6660
7644
|
}
|
|
6661
7645
|
function nameOf(orig, nameSel, fallback) {
|
|
6662
7646
|
let name = nameSel && (orig.querySelector(nameSel)?.textContent || "").trim();
|
|
@@ -6682,6 +7666,7 @@
|
|
|
6682
7666
|
else btn.removeAttribute("data-active");
|
|
6683
7667
|
if (kind === "auto" || kind === "plugin") btn.setAttribute("aria-pressed", on ? "true" : "false");
|
|
6684
7668
|
}
|
|
7669
|
+
var lastSelectedKey = "";
|
|
6685
7670
|
function syncActive() {
|
|
6686
7671
|
if (!origs || !rowEl) return;
|
|
6687
7672
|
const auto = origs.auto.getAttribute("aria-pressed") === "true";
|
|
@@ -6691,23 +7676,37 @@
|
|
|
6691
7676
|
for (const el of document.querySelectorAll(ROW_SEL)) {
|
|
6692
7677
|
if ((el.className + "").includes("bg-selected")) {
|
|
6693
7678
|
selected = true;
|
|
7679
|
+
lastSelectedKey = el.getAttribute("data-task-item-key") || lastSelectedKey;
|
|
6694
7680
|
break;
|
|
6695
7681
|
}
|
|
6696
7682
|
}
|
|
6697
|
-
|
|
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);
|
|
6698
7697
|
setActive("search", palette);
|
|
6699
7698
|
setActive("auto", auto);
|
|
6700
7699
|
setActive("plugin", plugin);
|
|
6701
7700
|
}
|
|
6702
7701
|
function rebuild() {
|
|
6703
|
-
const
|
|
6704
|
-
if (!menu) return false;
|
|
6705
|
-
const next = originalsOf(menu);
|
|
7702
|
+
const parts = findParts();
|
|
6706
7703
|
const navRow = document.querySelector('[data-testid="desktop-top-nav-back"]')?.parentElement;
|
|
6707
|
-
if (!
|
|
6708
|
-
if (origs && origs.
|
|
6709
|
-
|
|
6710
|
-
|
|
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;
|
|
6711
7710
|
rowEl?.remove();
|
|
6712
7711
|
navRow.classList.add("zcodepro-tb-hidden-native");
|
|
6713
7712
|
const L = t();
|
|
@@ -6722,17 +7721,17 @@
|
|
|
6722
7721
|
setTimeout(syncActive, 150);
|
|
6723
7722
|
}
|
|
6724
7723
|
});
|
|
6725
|
-
const newBtn = mk("newTask",
|
|
6726
|
-
const icon = iconOf(
|
|
7724
|
+
const newBtn = mk("newTask", parts.newTask, "span.truncate", L.tbNewTask);
|
|
7725
|
+
const icon = iconOf(parts.newTask);
|
|
6727
7726
|
if (icon) newBtn.append(icon);
|
|
6728
|
-
const searchBtn = mk("search",
|
|
6729
|
-
const sIcon = iconOf(
|
|
7727
|
+
const searchBtn = mk("search", parts.search, "span.truncate", L.tbSearch);
|
|
7728
|
+
const sIcon = iconOf(parts.search);
|
|
6730
7729
|
if (sIcon) searchBtn.append(sIcon);
|
|
6731
|
-
const autoBtn = mk("auto",
|
|
6732
|
-
const aIcon = iconOf(
|
|
7730
|
+
const autoBtn = mk("auto", parts.auto, null, L.tbAutomations);
|
|
7731
|
+
const aIcon = iconOf(parts.auto);
|
|
6733
7732
|
if (aIcon) autoBtn.append(aIcon);
|
|
6734
|
-
const pluginBtn = mk("plugin",
|
|
6735
|
-
const pIcon = iconOf(
|
|
7733
|
+
const pluginBtn = mk("plugin", parts.plugin, null, L.tbPluginStore);
|
|
7734
|
+
const pIcon = iconOf(parts.plugin);
|
|
6736
7735
|
if (pIcon) pluginBtn.append(pIcon);
|
|
6737
7736
|
rowEl = h("div", { class: "zcodepro-tb-row" }, newBtn, searchBtn, autoBtn, pluginBtn);
|
|
6738
7737
|
const updBtn = [...navRow.querySelectorAll("button")].find((b) => /bg-(success|emerald)/.test(b.className || ""));
|
|
@@ -6747,7 +7746,7 @@
|
|
|
6747
7746
|
}
|
|
6748
7747
|
var NARROW_SIDEBAR_PX = 260;
|
|
6749
7748
|
function sidebarTooNarrow() {
|
|
6750
|
-
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");
|
|
6751
7750
|
if (!scroll) return false;
|
|
6752
7751
|
if (!widthObserver) widthObserver = new ResizeObserver(() => scheduleSync());
|
|
6753
7752
|
if (widthObserved !== scroll) {
|
|
@@ -6759,18 +7758,18 @@
|
|
|
6759
7758
|
}
|
|
6760
7759
|
function sync() {
|
|
6761
7760
|
if (!enabled4) return;
|
|
6762
|
-
const
|
|
6763
|
-
if (!
|
|
7761
|
+
const parts = findParts();
|
|
7762
|
+
if (!parts) {
|
|
6764
7763
|
if (rowEl) rowEl.style.display = "none";
|
|
6765
7764
|
return;
|
|
6766
7765
|
}
|
|
6767
7766
|
if (sidebarCollapsed() || sidebarTooNarrow()) {
|
|
6768
7767
|
if (rowEl) rowEl.style.display = "none";
|
|
6769
|
-
|
|
7768
|
+
for (const el of parts.hideEls) el.classList.remove(HIDE_CLASS);
|
|
6770
7769
|
document.querySelectorAll(".zcodepro-tb-hidden-native").forEach((el) => el.classList.remove("zcodepro-tb-hidden-native"));
|
|
6771
7770
|
return;
|
|
6772
7771
|
}
|
|
6773
|
-
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;
|
|
6774
7773
|
if (!alive && !rebuild()) {
|
|
6775
7774
|
if (rowEl) rowEl.style.display = "none";
|
|
6776
7775
|
setTimeout(scheduleSync, 400);
|
|
@@ -6779,7 +7778,7 @@
|
|
|
6779
7778
|
}
|
|
6780
7779
|
const navRow = document.querySelector('[data-testid="desktop-top-nav-back"]')?.parentElement;
|
|
6781
7780
|
if (navRow) navRow.classList.add("zcodepro-tb-hidden-native");
|
|
6782
|
-
|
|
7781
|
+
for (const el of parts.hideEls) el.classList.add(HIDE_CLASS);
|
|
6783
7782
|
if (rowEl) rowEl.style.display = "";
|
|
6784
7783
|
syncActive();
|
|
6785
7784
|
}
|
|
@@ -6813,12 +7812,12 @@
|
|
|
6813
7812
|
rowEl?.remove();
|
|
6814
7813
|
rowEl = null;
|
|
6815
7814
|
if (origs) {
|
|
6816
|
-
origs.
|
|
7815
|
+
for (const el of origs.hideEls) el.classList.remove(HIDE_CLASS);
|
|
6817
7816
|
document.querySelectorAll(".zcodepro-tb-hidden-native").forEach((el) => el.classList.remove("zcodepro-tb-hidden-native"));
|
|
6818
7817
|
origs = null;
|
|
6819
7818
|
}
|
|
6820
7819
|
}
|
|
6821
|
-
async function
|
|
7820
|
+
async function refreshConfig2() {
|
|
6822
7821
|
const cfg = await getConfig(true).catch(() => null);
|
|
6823
7822
|
enabled4 = !cfg || !cfg.features || cfg.features.toolbarIcons !== false;
|
|
6824
7823
|
if (enabled4) sync();
|
|
@@ -6827,9 +7826,9 @@
|
|
|
6827
7826
|
function startToolbarIcons() {
|
|
6828
7827
|
ensureStyle();
|
|
6829
7828
|
window.addEventListener("zcodepro:config-changed", () => {
|
|
6830
|
-
void
|
|
7829
|
+
void refreshConfig2();
|
|
6831
7830
|
});
|
|
6832
|
-
void
|
|
7831
|
+
void refreshConfig2();
|
|
6833
7832
|
new MutationObserver((muts) => {
|
|
6834
7833
|
if (relevantMutations(muts)) scheduleSync();
|
|
6835
7834
|
}).observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ["class", "aria-pressed"] });
|
|
@@ -6851,8 +7850,8 @@
|
|
|
6851
7850
|
var syncTimer2 = 0;
|
|
6852
7851
|
function findPinnedHeader() {
|
|
6853
7852
|
for (const h3 of document.querySelectorAll("h3")) {
|
|
6854
|
-
const
|
|
6855
|
-
if (
|
|
7853
|
+
const list = h3.nextElementSibling;
|
|
7854
|
+
if (list && list.querySelector("li[data-task-item-key]")) return h3;
|
|
6856
7855
|
}
|
|
6857
7856
|
return null;
|
|
6858
7857
|
}
|
|
@@ -6948,7 +7947,7 @@
|
|
|
6948
7947
|
h3.parentElement?.classList.remove(COLLAPSED_CLASS);
|
|
6949
7948
|
}
|
|
6950
7949
|
}
|
|
6951
|
-
async function
|
|
7950
|
+
async function refreshConfig3() {
|
|
6952
7951
|
const cfg = await getConfig(true).catch(() => null);
|
|
6953
7952
|
enabled5 = !cfg || !cfg.features || cfg.features.pinnedCollapse !== false;
|
|
6954
7953
|
if (enabled5) sync2();
|
|
@@ -6957,9 +7956,9 @@
|
|
|
6957
7956
|
function startPinnedCollapse() {
|
|
6958
7957
|
ensureStyle();
|
|
6959
7958
|
window.addEventListener("zcodepro:config-changed", () => {
|
|
6960
|
-
void
|
|
7959
|
+
void refreshConfig3();
|
|
6961
7960
|
});
|
|
6962
|
-
void
|
|
7961
|
+
void refreshConfig3();
|
|
6963
7962
|
new MutationObserver((muts) => {
|
|
6964
7963
|
if (relevantMutations2(muts)) scheduleSync2();
|
|
6965
7964
|
}).observe(document.body, { childList: true, subtree: true });
|
|
@@ -7034,6 +8033,10 @@
|
|
|
7034
8033
|
void startAliasWatcher();
|
|
7035
8034
|
} catch {
|
|
7036
8035
|
}
|
|
8036
|
+
try {
|
|
8037
|
+
startAliasMigrationWatcher();
|
|
8038
|
+
} catch {
|
|
8039
|
+
}
|
|
7037
8040
|
try {
|
|
7038
8041
|
startTaskOrderWatcher();
|
|
7039
8042
|
} catch {
|
|
@@ -7054,10 +8057,6 @@
|
|
|
7054
8057
|
startImageMenu();
|
|
7055
8058
|
} catch {
|
|
7056
8059
|
}
|
|
7057
|
-
try {
|
|
7058
|
-
startPinnedExpandSuppression();
|
|
7059
|
-
} catch {
|
|
7060
|
-
}
|
|
7061
8060
|
try {
|
|
7062
8061
|
startWsRunningSpin();
|
|
7063
8062
|
} catch {
|