dsh-life-pack 0.3.65 → 0.3.67
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/dist/client.js +1327 -223
- package/dist/client.js.map +1 -1
- package/package.json +2 -2
package/dist/client.js
CHANGED
|
@@ -471,7 +471,7 @@ window.__ModuleLoader__.load({
|
|
|
471
471
|
path: "/api/ilife-manager"
|
|
472
472
|
};
|
|
473
473
|
//#endregion
|
|
474
|
-
//#region ../../node_modules/.pnpm/dsh-plugin-update@0.18.
|
|
474
|
+
//#region ../../node_modules/.pnpm/dsh-plugin-update@0.18.7/node_modules/dsh-plugin-update/dist/config.js
|
|
475
475
|
const DEFAULT_PANEL_POLL_MS = 1e3;
|
|
476
476
|
function assertPrefix(value, role) {
|
|
477
477
|
if (typeof value !== "string" || value.length === 0) throw new Error("[dsh-plugin-update] " + role + " 非法:须为非空字符串(收到 " + JSON.stringify(value) + ")");
|
|
@@ -485,6 +485,7 @@ window.__ModuleLoader__.load({
|
|
|
485
485
|
updateCheck: checked + ".updateCheck",
|
|
486
486
|
updateInstall: checked + ".updateInstall",
|
|
487
487
|
updateChangelog: checked + ".updateChangelog",
|
|
488
|
+
updateCheckFallback: checked + ".updateCheckFallback",
|
|
488
489
|
logAppend: checked + ".logAppend"
|
|
489
490
|
};
|
|
490
491
|
}
|
|
@@ -492,71 +493,7 @@ window.__ModuleLoader__.load({
|
|
|
492
493
|
return buildPhoneNames(prefix).logAppend;
|
|
493
494
|
}
|
|
494
495
|
//#endregion
|
|
495
|
-
//#region ../../node_modules/.pnpm/dsh-plugin-update@0.18.
|
|
496
|
-
const COPY_BUDGET_CHARS = 1500;
|
|
497
|
-
const REDACTED_PATH = "<路径>";
|
|
498
|
-
const REDACTED_SECRET = "<脱敏>";
|
|
499
|
-
const ABSOLUTE_PATH_RE = /[A-Za-z]:\\[^\s"']*|\\\\[^\s"'()\[\];]+|(^|[\s"'(\[=,])\/\/[^\s"'()\[\];]+|(^|[\s"'(\[=:,])\/(?!\/)[^\s"'()\[\];]+/g;
|
|
500
|
-
const URL_USERINFO_RE = /[A-Za-z][A-Za-z0-9+.-]*:\/\/[^\s/]*@/;
|
|
501
|
-
const NPM_TOKEN_RE = /\bnpm_[A-Za-z0-9_-]{8,}/g;
|
|
502
|
-
const GITHUB_TOKEN_RE = /\b(?:gh[pousr]_[A-Za-z0-9]{8,}|github_pat_[A-Za-z0-9_]{10,})/g;
|
|
503
|
-
const SK_TOKEN_RE = /\bsk-[A-Za-z0-9_-]{6,}/g;
|
|
504
|
-
const BEARER_TOKEN_RE = /(\bbearer\s+)[A-Za-z0-9._~+/-=]{6,}/gi;
|
|
505
|
-
const CRED_PAIR_RE = /(\b(?:token|password|passwd|pwd|api[_-]?key|access[_-]?key|auth[_-]?token|secret|cookie)\s*[:=]\s*)("[^"]+"|'[^']+'|[^\s'";,)\]]+)/gi;
|
|
506
|
-
const EMAIL_RE = /\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}/g;
|
|
507
|
-
function flattenWhitespace(text) {
|
|
508
|
-
return String(text ?? "").replace(/\s+/g, " ").trim();
|
|
509
|
-
}
|
|
510
|
-
function applyPathRule(text) {
|
|
511
|
-
ABSOLUTE_PATH_RE.lastIndex = 0;
|
|
512
|
-
return text.replace(ABSOLUTE_PATH_RE, (_whole, g1, g2) => {
|
|
513
|
-
return `${g1 ?? g2 ?? ""}${REDACTED_PATH}`;
|
|
514
|
-
});
|
|
515
|
-
}
|
|
516
|
-
function applyTokenRule(text) {
|
|
517
|
-
NPM_TOKEN_RE.lastIndex = 0;
|
|
518
|
-
GITHUB_TOKEN_RE.lastIndex = 0;
|
|
519
|
-
SK_TOKEN_RE.lastIndex = 0;
|
|
520
|
-
BEARER_TOKEN_RE.lastIndex = 0;
|
|
521
|
-
return text.replace(NPM_TOKEN_RE, REDACTED_SECRET).replace(GITHUB_TOKEN_RE, REDACTED_SECRET).replace(SK_TOKEN_RE, REDACTED_SECRET).replace(BEARER_TOKEN_RE, (_whole, prefix) => `${prefix}${REDACTED_SECRET}`);
|
|
522
|
-
}
|
|
523
|
-
function applyCredPairRule(text) {
|
|
524
|
-
CRED_PAIR_RE.lastIndex = 0;
|
|
525
|
-
return text.replace(CRED_PAIR_RE, (_whole, head) => `${head}${REDACTED_SECRET}`);
|
|
526
|
-
}
|
|
527
|
-
function applyEmailRule(text) {
|
|
528
|
-
EMAIL_RE.lastIndex = 0;
|
|
529
|
-
return text.replace(EMAIL_RE, REDACTED_SECRET);
|
|
530
|
-
}
|
|
531
|
-
function hasUserinfo(text) {
|
|
532
|
-
URL_USERINFO_RE.lastIndex = 0;
|
|
533
|
-
return URL_USERINFO_RE.test(text);
|
|
534
|
-
}
|
|
535
|
-
function truncateToWordBoundary(text, max) {
|
|
536
|
-
const input = String(text ?? "");
|
|
537
|
-
if (input.length <= max) return input;
|
|
538
|
-
const slice = input.slice(0, max);
|
|
539
|
-
const lastSpace = slice.lastIndexOf(" ");
|
|
540
|
-
let cut = lastSpace > 0 ? slice.slice(0, lastSpace) : slice;
|
|
541
|
-
const lastOpen = cut.lastIndexOf("<");
|
|
542
|
-
if (lastOpen > cut.lastIndexOf(">")) cut = cut.slice(0, lastOpen).trimEnd();
|
|
543
|
-
if (!cut) cut = slice;
|
|
544
|
-
return `${cut}\u2026`;
|
|
545
|
-
}
|
|
546
|
-
function truncateForCopy(text) {
|
|
547
|
-
return truncateToWordBoundary(text, COPY_BUDGET_CHARS);
|
|
548
|
-
}
|
|
549
|
-
function scrubWithoutBudget(text) {
|
|
550
|
-
return applyEmailRule(applyCredPairRule(applyTokenRule(applyPathRule(text))));
|
|
551
|
-
}
|
|
552
|
-
function sanitizeForCopy(text) {
|
|
553
|
-
const flat = flattenWhitespace(String(text ?? ""));
|
|
554
|
-
if (!flat) return "";
|
|
555
|
-
if (hasUserinfo(flat)) return "";
|
|
556
|
-
return truncateForCopy(scrubWithoutBudget(flat));
|
|
557
|
-
}
|
|
558
|
-
//#endregion
|
|
559
|
-
//#region ../../node_modules/.pnpm/dsh-plugin-update@0.18.5/node_modules/dsh-plugin-update/dist/service.js
|
|
496
|
+
//#region ../../node_modules/.pnpm/dsh-plugin-update@0.18.7/node_modules/dsh-plugin-update/dist/version-judgment.js
|
|
560
497
|
function updateError(code) {
|
|
561
498
|
return Object.assign(new Error(code), { code });
|
|
562
499
|
}
|
|
@@ -643,7 +580,7 @@ window.__ModuleLoader__.load({
|
|
|
643
580
|
return 0;
|
|
644
581
|
}
|
|
645
582
|
//#endregion
|
|
646
|
-
//#region ../../node_modules/.pnpm/dsh-plugin-update@0.18.
|
|
583
|
+
//#region ../../node_modules/.pnpm/dsh-plugin-update@0.18.7/node_modules/dsh-plugin-update/dist/lang.js
|
|
647
584
|
function normalizeLangTag(tag) {
|
|
648
585
|
if (typeof tag !== "string") return "zh";
|
|
649
586
|
const s = tag.trim().toLowerCase().replace(/_/g, "-");
|
|
@@ -785,7 +722,7 @@ window.__ModuleLoader__.load({
|
|
|
785
722
|
};
|
|
786
723
|
}
|
|
787
724
|
//#endregion
|
|
788
|
-
//#region ../../node_modules/.pnpm/dsh-plugin-update@0.18.
|
|
725
|
+
//#region ../../node_modules/.pnpm/dsh-plugin-update@0.18.7/node_modules/dsh-plugin-update/dist/bilingual.js
|
|
789
726
|
const BILINGUAL_STRINGS = {
|
|
790
727
|
"entry.label.idle": {
|
|
791
728
|
en: "Check for updates",
|
|
@@ -1187,6 +1124,16 @@ window.__ModuleLoader__.load({
|
|
|
1187
1124
|
zh: "安装版本 {latest}",
|
|
1188
1125
|
draft: true
|
|
1189
1126
|
},
|
|
1127
|
+
"panel.banner.update-gated-title": {
|
|
1128
|
+
en: "Version {latest} was just published and is still gated ({unlock}); installing now will fail — use Install fallback build below if you cannot wait.",
|
|
1129
|
+
zh: "新版本 {latest} 刚发布未满门,{unlock}可装;现在点安装会失败,等不及可先装合规版。",
|
|
1130
|
+
draft: true
|
|
1131
|
+
},
|
|
1132
|
+
"panel.action.install-gated-title": {
|
|
1133
|
+
en: "Come back {unlock} to install {latest}; it is still gated and would fail now.",
|
|
1134
|
+
zh: "{unlock}再来装 {latest} 吧,现在装会被门拦住。",
|
|
1135
|
+
draft: true
|
|
1136
|
+
},
|
|
1190
1137
|
"panel.banner.done": {
|
|
1191
1138
|
en: "Up to date. No update needed.",
|
|
1192
1139
|
zh: "已是最新,无需更新。",
|
|
@@ -1252,6 +1199,16 @@ window.__ModuleLoader__.load({
|
|
|
1252
1199
|
zh: "已确认该失败提示;下次查询版本信息或安装将重新评估。",
|
|
1253
1200
|
draft: true
|
|
1254
1201
|
},
|
|
1202
|
+
"panel.toast.fallback-unavailable": {
|
|
1203
|
+
en: "No compliant build for this failure; see the diagnostics or retry later.",
|
|
1204
|
+
zh: "这次失败用不上合规版,请看诊断信息或稍后重试。",
|
|
1205
|
+
draft: true
|
|
1206
|
+
},
|
|
1207
|
+
"panel.toast.fallback-wait": {
|
|
1208
|
+
en: "Latest should clear around {time}; no earlier compliant build for now.",
|
|
1209
|
+
zh: "最新版约 {time} 可装,暂无更早的合规版。",
|
|
1210
|
+
draft: true
|
|
1211
|
+
},
|
|
1255
1212
|
"panel.strip.running": {
|
|
1256
1213
|
en: "Running",
|
|
1257
1214
|
zh: "运行版",
|
|
@@ -1412,6 +1369,36 @@ window.__ModuleLoader__.load({
|
|
|
1412
1369
|
zh: "确认已知晓该失败:返回可安装页,下次查询或安装将重新评估",
|
|
1413
1370
|
draft: true
|
|
1414
1371
|
},
|
|
1372
|
+
"panel.action.install-fallback": {
|
|
1373
|
+
en: "Install compliant build",
|
|
1374
|
+
zh: "装合规版",
|
|
1375
|
+
draft: true
|
|
1376
|
+
},
|
|
1377
|
+
"panel.action.install-fallback-title": {
|
|
1378
|
+
en: "Resolve an age-compliant version first, then confirm; never installs an older version silently",
|
|
1379
|
+
zh: "先决议一个满门限的版本再请你确认,不会静默装旧版",
|
|
1380
|
+
draft: true
|
|
1381
|
+
},
|
|
1382
|
+
"panel.action.install-fallback-confirm": {
|
|
1383
|
+
en: "Confirm install {version}",
|
|
1384
|
+
zh: "确认装 {version}",
|
|
1385
|
+
draft: true
|
|
1386
|
+
},
|
|
1387
|
+
"panel.action.install-fallback-confirm-title": {
|
|
1388
|
+
en: "Install this exact version now",
|
|
1389
|
+
zh: "点下去即安装该精确版本",
|
|
1390
|
+
draft: true
|
|
1391
|
+
},
|
|
1392
|
+
"panel.action.wait-latest": {
|
|
1393
|
+
en: "Wait for latest",
|
|
1394
|
+
zh: "等新版",
|
|
1395
|
+
draft: true
|
|
1396
|
+
},
|
|
1397
|
+
"panel.action.wait-latest-title": {
|
|
1398
|
+
en: "Dismiss this failure; install again once the latest clears the age gate",
|
|
1399
|
+
zh: "收起这次失败;最新版满门限后可再装",
|
|
1400
|
+
draft: true
|
|
1401
|
+
},
|
|
1415
1402
|
"panel.action.copy-diag": {
|
|
1416
1403
|
en: "Copy diagnostics",
|
|
1417
1404
|
zh: "复制诊断",
|
|
@@ -2037,6 +2024,41 @@ window.__ModuleLoader__.load({
|
|
|
2037
2024
|
zh: "请重试一次;若持续,请提交诊断信息至插件作者。",
|
|
2038
2025
|
draft: true
|
|
2039
2026
|
},
|
|
2027
|
+
"batch.banner.age-gated": {
|
|
2028
|
+
en: "{n} plugin(s) are blocked by the 24-hour age gate.",
|
|
2029
|
+
zh: "{n} 个插件的最新版被 24 小时年龄门挡住。",
|
|
2030
|
+
draft: true
|
|
2031
|
+
},
|
|
2032
|
+
"batch.banner.gated-wait": {
|
|
2033
|
+
en: "{n} plugin(s) are blocked by the 24-hour age gate and nothing is installable right now; installable in about {time}.",
|
|
2034
|
+
zh: "{n} 个插件的最新版被 24 小时年龄门挡住,现在还没有可装的版本;约 {time} 后可装。",
|
|
2035
|
+
draft: true
|
|
2036
|
+
},
|
|
2037
|
+
"batch.banner.compliant-done-title": {
|
|
2038
|
+
en: "Actual install result for these {n} plugin(s):",
|
|
2039
|
+
zh: "这 {n} 个插件的实际安装结果:",
|
|
2040
|
+
draft: true
|
|
2041
|
+
},
|
|
2042
|
+
"batch.banner.compliant-done": {
|
|
2043
|
+
en: "{title}: installed {version}, not the latest {target} (the latest did not go through).",
|
|
2044
|
+
zh: "{title}:已装 {version},不是最新 {target}(最新版没装成)。",
|
|
2045
|
+
draft: true
|
|
2046
|
+
},
|
|
2047
|
+
"batch.banner.compliant-done-gated": {
|
|
2048
|
+
en: "{title}: installed {version}; the latest {target} is still blocked by the 24-hour age gate (installable in about {time}).",
|
|
2049
|
+
zh: "{title}:已装 {version};最新 {target} 仍被 24 小时年龄门挡着,约 {time} 后可装。",
|
|
2050
|
+
draft: true
|
|
2051
|
+
},
|
|
2052
|
+
"batch.banner.compliant-confirm": {
|
|
2053
|
+
en: "Install these compliant builds: {list}?",
|
|
2054
|
+
zh: "确认安装以下合规版:{list}?",
|
|
2055
|
+
draft: true
|
|
2056
|
+
},
|
|
2057
|
+
"batch.action.install-compliant-confirm": {
|
|
2058
|
+
en: "Confirm and install these {n}",
|
|
2059
|
+
zh: "确认装这 {n} 个",
|
|
2060
|
+
draft: true
|
|
2061
|
+
},
|
|
2040
2062
|
"batch.banner.failed-title": {
|
|
2041
2063
|
en: "{n} failed to install.",
|
|
2042
2064
|
zh: "{n} 个插件安装失败。",
|
|
@@ -2202,6 +2224,11 @@ window.__ModuleLoader__.load({
|
|
|
2202
2224
|
zh: "失败 {code}:{detail}",
|
|
2203
2225
|
draft: true
|
|
2204
2226
|
},
|
|
2227
|
+
"batch.row.compliant-done": {
|
|
2228
|
+
en: "Installed {version}, not the latest {target} (the latest did not go through)",
|
|
2229
|
+
zh: "已装 {version},不是最新 {target}(最新版这次没装上)",
|
|
2230
|
+
draft: true
|
|
2231
|
+
},
|
|
2205
2232
|
"batch.diag.source-job": {
|
|
2206
2233
|
en: "(Source: background job record)",
|
|
2207
2234
|
zh: "(来源:后台任务执行记录)",
|
|
@@ -2237,6 +2264,11 @@ window.__ModuleLoader__.load({
|
|
|
2237
2264
|
zh: "此行缺少取消排队所需的信息,暂无法取消;请待下次刷新后重试。",
|
|
2238
2265
|
draft: true
|
|
2239
2266
|
},
|
|
2267
|
+
"batch.toast.compliant-installed": {
|
|
2268
|
+
en: "Requested {a} compliant build(s) (not the latest: it is still age-gated); {b} did not go through.",
|
|
2269
|
+
zh: "已请求安装 {a} 个合规版(不是最新版:最新版仍被年龄门挡着);{b} 个没装成。",
|
|
2270
|
+
draft: true
|
|
2271
|
+
},
|
|
2240
2272
|
"batch.toast.cancel-ok": {
|
|
2241
2273
|
en: "Queue cancelled: this plugin will not wait.",
|
|
2242
2274
|
zh: "已取消排队:此插件将不再等待。",
|
|
@@ -2467,7 +2499,7 @@ window.__ModuleLoader__.load({
|
|
|
2467
2499
|
}
|
|
2468
2500
|
const BILINGUAL_CSS = [".dsh-upd-bi{display:inline;overflow-wrap:anywhere}", ".dsh-upd-bi [lang]{overflow-wrap:anywhere}"].join("\n");
|
|
2469
2501
|
//#endregion
|
|
2470
|
-
//#region ../../node_modules/.pnpm/dsh-plugin-update@0.18.
|
|
2502
|
+
//#region ../../node_modules/.pnpm/dsh-plugin-update@0.18.7/node_modules/dsh-plugin-update/dist/changelog.js
|
|
2471
2503
|
const CHANGELOG_MAX_CHARS = 65536;
|
|
2472
2504
|
const CHANGELOG_ALL_CATEGORIES = [
|
|
2473
2505
|
"Added",
|
|
@@ -3575,7 +3607,7 @@ ${note}${blocks.join("\n")}
|
|
|
3575
3607
|
}
|
|
3576
3608
|
}
|
|
3577
3609
|
//#endregion
|
|
3578
|
-
//#region ../../node_modules/.pnpm/dsh-plugin-update@0.18.
|
|
3610
|
+
//#region ../../node_modules/.pnpm/dsh-plugin-update@0.18.7/node_modules/dsh-plugin-update/dist/log-events.js
|
|
3579
3611
|
const LOG_EVENT_CALL = "host.call";
|
|
3580
3612
|
const LOG_EVENT_CALL_FAIL = "host.call.fail";
|
|
3581
3613
|
const LOG_EVENT_INSTALL_EXEC = "update.install.exec";
|
|
@@ -3826,7 +3858,7 @@ ${note}${blocks.join("\n")}
|
|
|
3826
3858
|
};
|
|
3827
3859
|
}
|
|
3828
3860
|
//#endregion
|
|
3829
|
-
//#region ../../node_modules/.pnpm/dsh-plugin-update@0.18.
|
|
3861
|
+
//#region ../../node_modules/.pnpm/dsh-plugin-update@0.18.7/node_modules/dsh-plugin-update/dist/codes.js
|
|
3830
3862
|
const BLOCKED_REASONS = [
|
|
3831
3863
|
"unknown-profile",
|
|
3832
3864
|
"channel-mismatch",
|
|
@@ -3861,8 +3893,25 @@ ${note}${blocks.join("\n")}
|
|
|
3861
3893
|
return typeof code === "string" && isOneOf(CHECK_SIDE_FAILURE_CODES, code.trim());
|
|
3862
3894
|
}
|
|
3863
3895
|
//#endregion
|
|
3864
|
-
//#region ../../node_modules/.pnpm/dsh-plugin-update@0.18.
|
|
3896
|
+
//#region ../../node_modules/.pnpm/dsh-plugin-update@0.18.7/node_modules/dsh-plugin-update/dist/install-cause.js
|
|
3865
3897
|
const CAUSE_KINDS = ["minimum-release-age"];
|
|
3898
|
+
const CAUSE_SIGNATURES = [{
|
|
3899
|
+
kind: "minimum-release-age",
|
|
3900
|
+
codes: ["install-failed"],
|
|
3901
|
+
stages: ["exec"],
|
|
3902
|
+
token: "[ERR_PNPM_MINIMUM_RELEASE_AGE_VIOLATION]",
|
|
3903
|
+
pattern: /(?<spec>@?[a-z0-9][a-z0-9._/-]*@[0-9][A-Za-z0-9._-]*)[\s\S]*?published[\s\S]{0,120}?(?<published>[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}(?:\.[0-9]+)?Z?)[\s\S]*?cutoff[\s\S]{0,120}?(?<cutoff>[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}(?:\.[0-9]+)?Z?)/
|
|
3904
|
+
}];
|
|
3905
|
+
function toMs(value) {
|
|
3906
|
+
try {
|
|
3907
|
+
if (typeof value === "number" && Number.isFinite(value) && value > 0) return value;
|
|
3908
|
+
if (typeof value === "string" && value.trim()) {
|
|
3909
|
+
const ms = Date.parse(value.trim());
|
|
3910
|
+
if (Number.isFinite(ms) && ms > 0) return ms;
|
|
3911
|
+
}
|
|
3912
|
+
} catch {}
|
|
3913
|
+
return null;
|
|
3914
|
+
}
|
|
3866
3915
|
function causePackageNameOf(spec) {
|
|
3867
3916
|
try {
|
|
3868
3917
|
const s = String(spec ?? "").trim();
|
|
@@ -3902,118 +3951,133 @@ ${note}${blocks.join("\n")}
|
|
|
3902
3951
|
return null;
|
|
3903
3952
|
}
|
|
3904
3953
|
}
|
|
3954
|
+
const WINDOW_PATTERN = /less than (?<windowMinutes>[0-9]{1,7}) minutes? ago/;
|
|
3955
|
+
const WINDOW_MINUTES_MAX = 5256e3;
|
|
3956
|
+
function parseWindowMinutes(detail) {
|
|
3957
|
+
try {
|
|
3958
|
+
const matched = WINDOW_PATTERN.exec(detail);
|
|
3959
|
+
if (!matched?.groups) return null;
|
|
3960
|
+
const n = Number(matched.groups["windowMinutes"]);
|
|
3961
|
+
if (!Number.isInteger(n) || n <= 0 || n > WINDOW_MINUTES_MAX) return null;
|
|
3962
|
+
return n;
|
|
3963
|
+
} catch {
|
|
3964
|
+
return null;
|
|
3965
|
+
}
|
|
3966
|
+
}
|
|
3967
|
+
function interpretInstallCause(input) {
|
|
3968
|
+
try {
|
|
3969
|
+
const errorCode = String(input?.errorCode ?? "");
|
|
3970
|
+
const detail = input?.detail;
|
|
3971
|
+
if (!errorCode || typeof detail !== "string" || !detail.trim()) return null;
|
|
3972
|
+
const nowMs = toMs(input?.nowMs) ?? Date.now();
|
|
3973
|
+
for (const sig of CAUSE_SIGNATURES) {
|
|
3974
|
+
const codes = sig.codes;
|
|
3975
|
+
const stages = sig.stages;
|
|
3976
|
+
if (!codes.includes(errorCode)) continue;
|
|
3977
|
+
if (stages.length > 0 && typeof input?.stage === "string" && input.stage) {
|
|
3978
|
+
if (!stages.includes(input.stage)) continue;
|
|
3979
|
+
}
|
|
3980
|
+
if (!detail.includes(sig.token)) continue;
|
|
3981
|
+
const matched = sig.pattern.exec(detail);
|
|
3982
|
+
if (!matched || !matched.groups) continue;
|
|
3983
|
+
const spec = String(matched.groups["spec"] ?? "").trim();
|
|
3984
|
+
if (!spec) continue;
|
|
3985
|
+
const publishedAtMs = matched.groups["published"] ? toMs(matched.groups["published"]) : null;
|
|
3986
|
+
const cutoffMs = matched.groups["cutoff"] ? toMs(matched.groups["cutoff"]) : null;
|
|
3987
|
+
const windowMinutes = parseWindowMinutes(detail);
|
|
3988
|
+
let unlockAtMs;
|
|
3989
|
+
if (publishedAtMs !== null && windowMinutes !== null) {
|
|
3990
|
+
const unlock = publishedAtMs + windowMinutes * 6e4;
|
|
3991
|
+
if (unlock > nowMs) unlockAtMs = unlock;
|
|
3992
|
+
} else if (publishedAtMs !== null && cutoffMs !== null) {
|
|
3993
|
+
const windowMs = nowMs - cutoffMs;
|
|
3994
|
+
const unlock = publishedAtMs + windowMs;
|
|
3995
|
+
if (windowMs > 0 && unlock > nowMs) unlockAtMs = unlock;
|
|
3996
|
+
}
|
|
3997
|
+
const at = spec.lastIndexOf("@");
|
|
3998
|
+
return {
|
|
3999
|
+
kind: sig.kind,
|
|
4000
|
+
spec,
|
|
4001
|
+
packageName: causePackageNameOf(spec),
|
|
4002
|
+
packageVersion: at > 0 ? spec.slice(at + 1) || null : null,
|
|
4003
|
+
publishedAtMs,
|
|
4004
|
+
cutoffMs,
|
|
4005
|
+
windowMinutes,
|
|
4006
|
+
...unlockAtMs !== void 0 ? { unlockAtMs } : {},
|
|
4007
|
+
blame: blameCausePackage(spec, input?.targetPackageName)
|
|
4008
|
+
};
|
|
4009
|
+
}
|
|
4010
|
+
return null;
|
|
4011
|
+
} catch {
|
|
4012
|
+
return null;
|
|
4013
|
+
}
|
|
4014
|
+
}
|
|
3905
4015
|
//#endregion
|
|
3906
|
-
//#region ../../node_modules/.pnpm/dsh-plugin-update@0.18.
|
|
3907
|
-
|
|
3908
|
-
|
|
4016
|
+
//#region ../../node_modules/.pnpm/dsh-plugin-update@0.18.7/node_modules/dsh-plugin-update/dist/redaction.js
|
|
4017
|
+
const COPY_BUDGET_CHARS = 1500;
|
|
4018
|
+
const REDACTED_PATH = "<路径>";
|
|
4019
|
+
const REDACTED_SECRET = "<脱敏>";
|
|
4020
|
+
const ABSOLUTE_PATH_RE = /[A-Za-z]:\\[^\s"']*|\\\\[^\s"'()\[\];]+|(^|[\s"'(\[=,])\/\/[^\s"'()\[\];]+|(^|[\s"'(\[=:,])\/(?!\/)[^\s"'()\[\];]+/g;
|
|
4021
|
+
const URL_USERINFO_RE = /[A-Za-z][A-Za-z0-9+.-]*:\/\/[^\s/]*@/;
|
|
4022
|
+
const NPM_TOKEN_RE = /\bnpm_[A-Za-z0-9_-]{8,}/g;
|
|
4023
|
+
const GITHUB_TOKEN_RE = /\b(?:gh[pousr]_[A-Za-z0-9]{8,}|github_pat_[A-Za-z0-9_]{10,})/g;
|
|
4024
|
+
const SK_TOKEN_RE = /\bsk-[A-Za-z0-9_-]{6,}/g;
|
|
4025
|
+
const BEARER_TOKEN_RE = /(\bbearer\s+)[A-Za-z0-9._~+/-=]{6,}/gi;
|
|
4026
|
+
const CRED_PAIR_RE = /(\b(?:token|password|passwd|pwd|api[_-]?key|access[_-]?key|auth[_-]?token|secret|cookie)\s*[:=]\s*)("[^"]+"|'[^']+'|[^\s'";,)\]]+)/gi;
|
|
4027
|
+
const EMAIL_RE = /\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}/g;
|
|
4028
|
+
function flattenWhitespace(text) {
|
|
4029
|
+
return String(text ?? "").replace(/\s+/g, " ").trim();
|
|
3909
4030
|
}
|
|
3910
|
-
|
|
3911
|
-
|
|
3912
|
-
|
|
3913
|
-
|
|
3914
|
-
|
|
3915
|
-
border: "--dsh-update-border",
|
|
3916
|
-
borderStrong: "--dsh-update-border-strong",
|
|
3917
|
-
buttonBg: "--dsh-update-button-bg",
|
|
3918
|
-
primary: "--dsh-update-primary",
|
|
3919
|
-
primaryDeep: "--dsh-update-primary-deep",
|
|
3920
|
-
focus: "--dsh-update-focus",
|
|
3921
|
-
okBg: "--dsh-update-ok-bg",
|
|
3922
|
-
okBorder: "--dsh-update-ok-border",
|
|
3923
|
-
okText: "--dsh-update-ok-text",
|
|
3924
|
-
warnBg: "--dsh-update-warn-bg",
|
|
3925
|
-
warnBorder: "--dsh-update-warn-border",
|
|
3926
|
-
warnText: "--dsh-update-warn-text",
|
|
3927
|
-
badBg: "--dsh-update-bad-bg",
|
|
3928
|
-
badBorder: "--dsh-update-bad-border",
|
|
3929
|
-
badText: "--dsh-update-bad-text",
|
|
3930
|
-
busyBg: "--dsh-update-busy-bg",
|
|
3931
|
-
busyBorder: "--dsh-update-busy-border",
|
|
3932
|
-
busyText: "--dsh-update-busy-text",
|
|
3933
|
-
newText: "--dsh-update-new-text",
|
|
3934
|
-
newOkText: "--dsh-update-new-ok-text",
|
|
3935
|
-
fontSans: "--dsh-update-font-sans",
|
|
3936
|
-
fontSerif: "--dsh-update-font-serif",
|
|
3937
|
-
fontMono: "--dsh-update-font-mono",
|
|
3938
|
-
shadow: "--dsh-update-shadow",
|
|
3939
|
-
radiusPanel: "--dsh-update-radius-panel",
|
|
3940
|
-
radiusButton: "--dsh-update-radius-button",
|
|
3941
|
-
radiusBadge: "--dsh-update-radius-badge",
|
|
3942
|
-
entryFontSize: "--dsh-update-entry-font-size",
|
|
3943
|
-
entryPadding: "--dsh-update-entry-padding",
|
|
3944
|
-
entryBorderRadius: "--dsh-update-entry-border-radius",
|
|
3945
|
-
entryScale: "--dsh-update-entry-scale",
|
|
3946
|
-
panelFontSize: "--dsh-update-panel-font-size",
|
|
3947
|
-
panelChapterFontSize: "--dsh-update-panel-chapter-font-size",
|
|
3948
|
-
panelBannerTitleFontSize: "--dsh-update-panel-banner-title-font-size",
|
|
3949
|
-
panelLogFontSize: "--dsh-update-panel-log-font-size",
|
|
3950
|
-
panelSmallFontSize: "--dsh-update-panel-small-font-size"
|
|
3951
|
-
};
|
|
3952
|
-
const THEME_TOKEN_COLOR_KEYS = /* @__PURE__ */ new Set([
|
|
3953
|
-
"text",
|
|
3954
|
-
"textMuted",
|
|
3955
|
-
"bg",
|
|
3956
|
-
"bgSoft",
|
|
3957
|
-
"border",
|
|
3958
|
-
"borderStrong",
|
|
3959
|
-
"buttonBg",
|
|
3960
|
-
"primary",
|
|
3961
|
-
"primaryDeep",
|
|
3962
|
-
"focus",
|
|
3963
|
-
"okBg",
|
|
3964
|
-
"okBorder",
|
|
3965
|
-
"okText",
|
|
3966
|
-
"warnBg",
|
|
3967
|
-
"warnBorder",
|
|
3968
|
-
"warnText",
|
|
3969
|
-
"badBg",
|
|
3970
|
-
"badBorder",
|
|
3971
|
-
"badText",
|
|
3972
|
-
"busyBg",
|
|
3973
|
-
"busyBorder",
|
|
3974
|
-
"busyText",
|
|
3975
|
-
"newText",
|
|
3976
|
-
"newOkText"
|
|
3977
|
-
]);
|
|
3978
|
-
function themeTokensError(raw) {
|
|
3979
|
-
return /* @__PURE__ */ new Error(`[dsh-plugin-update] \u4E3B\u9898\u53C2\u6570 themeTokens \u975E\u6CD5\uFF1A\u53EA\u6536\u5DF2\u77E5 token \u952E\uFF08\u989C\u8272\u7528 hex \u6216\u82F1\u6587\u540D\uFF0C\u5B57\u4F53/\u5706\u89D2/\u9634\u5F71/\u5C3A\u5BF8\u4E3A\u5B89\u5168 CSS \u503C\uFF0CentryScale \u4E3A\u5927\u4E8E 0 \u7684\u6709\u9650\u6570\uFF09\uFF08\u6536\u5230 ${JSON.stringify(raw ?? null)})`);
|
|
4031
|
+
function applyPathRule(text) {
|
|
4032
|
+
ABSOLUTE_PATH_RE.lastIndex = 0;
|
|
4033
|
+
return text.replace(ABSOLUTE_PATH_RE, (_whole, g1, g2) => {
|
|
4034
|
+
return `${g1 ?? g2 ?? ""}${REDACTED_PATH}`;
|
|
4035
|
+
});
|
|
3980
4036
|
}
|
|
3981
|
-
function
|
|
3982
|
-
|
|
3983
|
-
|
|
3984
|
-
|
|
3985
|
-
|
|
3986
|
-
|
|
3987
|
-
if (/javascript\s*:/i.test(v)) return false;
|
|
3988
|
-
return true;
|
|
4037
|
+
function applyTokenRule(text) {
|
|
4038
|
+
NPM_TOKEN_RE.lastIndex = 0;
|
|
4039
|
+
GITHUB_TOKEN_RE.lastIndex = 0;
|
|
4040
|
+
SK_TOKEN_RE.lastIndex = 0;
|
|
4041
|
+
BEARER_TOKEN_RE.lastIndex = 0;
|
|
4042
|
+
return text.replace(NPM_TOKEN_RE, REDACTED_SECRET).replace(GITHUB_TOKEN_RE, REDACTED_SECRET).replace(SK_TOKEN_RE, REDACTED_SECRET).replace(BEARER_TOKEN_RE, (_whole, prefix) => `${prefix}${REDACTED_SECRET}`);
|
|
3989
4043
|
}
|
|
3990
|
-
function
|
|
3991
|
-
|
|
3992
|
-
|
|
3993
|
-
return /^(?:#[0-9a-fA-F]{3}|#[0-9a-fA-F]{6}|#[0-9a-fA-F]{8}|[a-zA-Z]+)$/.test(v);
|
|
4044
|
+
function applyCredPairRule(text) {
|
|
4045
|
+
CRED_PAIR_RE.lastIndex = 0;
|
|
4046
|
+
return text.replace(CRED_PAIR_RE, (_whole, head) => `${head}${REDACTED_SECRET}`);
|
|
3994
4047
|
}
|
|
3995
|
-
function
|
|
3996
|
-
|
|
3997
|
-
|
|
3998
|
-
for (const key of Object.keys(tokens)) if (!Object.prototype.hasOwnProperty.call(THEME_TOKEN_VARS, key)) throw themeTokensError(tokens);
|
|
3999
|
-
const parts = [];
|
|
4000
|
-
for (const key of Object.keys(THEME_TOKEN_VARS)) {
|
|
4001
|
-
const value = tokens[key];
|
|
4002
|
-
if (value === void 0) continue;
|
|
4003
|
-
if (key === "entryScale") {
|
|
4004
|
-
if (typeof value !== "number" || !Number.isFinite(value) || value <= 0) throw themeTokensError(tokens);
|
|
4005
|
-
parts.push(THEME_TOKEN_VARS[key] + ":" + String(value));
|
|
4006
|
-
continue;
|
|
4007
|
-
}
|
|
4008
|
-
if (typeof value !== "string") throw themeTokensError(tokens);
|
|
4009
|
-
const text = value.trim();
|
|
4010
|
-
if (THEME_TOKEN_COLOR_KEYS.has(key)) {
|
|
4011
|
-
if (!isThemeColorValue(text)) throw themeTokensError(tokens);
|
|
4012
|
-
} else if (!isSafeThemeCssValue(text)) throw themeTokensError(tokens);
|
|
4013
|
-
parts.push(THEME_TOKEN_VARS[key] + ":" + text);
|
|
4014
|
-
}
|
|
4015
|
-
return parts.join(";");
|
|
4048
|
+
function applyEmailRule(text) {
|
|
4049
|
+
EMAIL_RE.lastIndex = 0;
|
|
4050
|
+
return text.replace(EMAIL_RE, REDACTED_SECRET);
|
|
4016
4051
|
}
|
|
4052
|
+
function hasUserinfo(text) {
|
|
4053
|
+
URL_USERINFO_RE.lastIndex = 0;
|
|
4054
|
+
return URL_USERINFO_RE.test(text);
|
|
4055
|
+
}
|
|
4056
|
+
function truncateToWordBoundary(text, max) {
|
|
4057
|
+
const input = String(text ?? "");
|
|
4058
|
+
if (input.length <= max) return input;
|
|
4059
|
+
const slice = input.slice(0, max);
|
|
4060
|
+
const lastSpace = slice.lastIndexOf(" ");
|
|
4061
|
+
let cut = lastSpace > 0 ? slice.slice(0, lastSpace) : slice;
|
|
4062
|
+
const lastOpen = cut.lastIndexOf("<");
|
|
4063
|
+
if (lastOpen > cut.lastIndexOf(">")) cut = cut.slice(0, lastOpen).trimEnd();
|
|
4064
|
+
if (!cut) cut = slice;
|
|
4065
|
+
return `${cut}\u2026`;
|
|
4066
|
+
}
|
|
4067
|
+
function truncateForCopy(text) {
|
|
4068
|
+
return truncateToWordBoundary(text, COPY_BUDGET_CHARS);
|
|
4069
|
+
}
|
|
4070
|
+
function scrubWithoutBudget(text) {
|
|
4071
|
+
return applyEmailRule(applyCredPairRule(applyTokenRule(applyPathRule(text))));
|
|
4072
|
+
}
|
|
4073
|
+
function sanitizeForCopy(text) {
|
|
4074
|
+
const flat = flattenWhitespace(String(text ?? ""));
|
|
4075
|
+
if (!flat) return "";
|
|
4076
|
+
if (hasUserinfo(flat)) return "";
|
|
4077
|
+
return truncateForCopy(scrubWithoutBudget(flat));
|
|
4078
|
+
}
|
|
4079
|
+
//#endregion
|
|
4080
|
+
//#region ../../node_modules/.pnpm/dsh-plugin-update@0.18.7/node_modules/dsh-plugin-update/dist/panel-copy.js
|
|
4017
4081
|
const BLOCKED_KEYS = {
|
|
4018
4082
|
"unknown-profile": {
|
|
4019
4083
|
title: "panel.blocked.unknown-profile.title",
|
|
@@ -4323,6 +4387,118 @@ ${note}${blocks.join("\n")}
|
|
|
4323
4387
|
` ${copyText("panel.diag.copy.block.remedy", l, { remedy })}`
|
|
4324
4388
|
].join("\n");
|
|
4325
4389
|
}
|
|
4390
|
+
//#endregion
|
|
4391
|
+
//#region ../../node_modules/.pnpm/dsh-plugin-update@0.18.7/node_modules/dsh-plugin-update/dist/panel.js
|
|
4392
|
+
function normalizePanelTheme(value) {
|
|
4393
|
+
return value === "archive" ? "archive" : "default";
|
|
4394
|
+
}
|
|
4395
|
+
const THEME_TOKEN_VARS = {
|
|
4396
|
+
text: "--dsh-update-text",
|
|
4397
|
+
textMuted: "--dsh-update-text-muted",
|
|
4398
|
+
bg: "--dsh-update-bg",
|
|
4399
|
+
bgSoft: "--dsh-update-bg-soft",
|
|
4400
|
+
border: "--dsh-update-border",
|
|
4401
|
+
borderStrong: "--dsh-update-border-strong",
|
|
4402
|
+
buttonBg: "--dsh-update-button-bg",
|
|
4403
|
+
primary: "--dsh-update-primary",
|
|
4404
|
+
primaryDeep: "--dsh-update-primary-deep",
|
|
4405
|
+
focus: "--dsh-update-focus",
|
|
4406
|
+
okBg: "--dsh-update-ok-bg",
|
|
4407
|
+
okBorder: "--dsh-update-ok-border",
|
|
4408
|
+
okText: "--dsh-update-ok-text",
|
|
4409
|
+
warnBg: "--dsh-update-warn-bg",
|
|
4410
|
+
warnBorder: "--dsh-update-warn-border",
|
|
4411
|
+
warnText: "--dsh-update-warn-text",
|
|
4412
|
+
badBg: "--dsh-update-bad-bg",
|
|
4413
|
+
badBorder: "--dsh-update-bad-border",
|
|
4414
|
+
badText: "--dsh-update-bad-text",
|
|
4415
|
+
busyBg: "--dsh-update-busy-bg",
|
|
4416
|
+
busyBorder: "--dsh-update-busy-border",
|
|
4417
|
+
busyText: "--dsh-update-busy-text",
|
|
4418
|
+
newText: "--dsh-update-new-text",
|
|
4419
|
+
newOkText: "--dsh-update-new-ok-text",
|
|
4420
|
+
fontSans: "--dsh-update-font-sans",
|
|
4421
|
+
fontSerif: "--dsh-update-font-serif",
|
|
4422
|
+
fontMono: "--dsh-update-font-mono",
|
|
4423
|
+
shadow: "--dsh-update-shadow",
|
|
4424
|
+
radiusPanel: "--dsh-update-radius-panel",
|
|
4425
|
+
radiusButton: "--dsh-update-radius-button",
|
|
4426
|
+
radiusBadge: "--dsh-update-radius-badge",
|
|
4427
|
+
entryFontSize: "--dsh-update-entry-font-size",
|
|
4428
|
+
entryPadding: "--dsh-update-entry-padding",
|
|
4429
|
+
entryBorderRadius: "--dsh-update-entry-border-radius",
|
|
4430
|
+
entryScale: "--dsh-update-entry-scale",
|
|
4431
|
+
panelFontSize: "--dsh-update-panel-font-size",
|
|
4432
|
+
panelChapterFontSize: "--dsh-update-panel-chapter-font-size",
|
|
4433
|
+
panelBannerTitleFontSize: "--dsh-update-panel-banner-title-font-size",
|
|
4434
|
+
panelLogFontSize: "--dsh-update-panel-log-font-size",
|
|
4435
|
+
panelSmallFontSize: "--dsh-update-panel-small-font-size"
|
|
4436
|
+
};
|
|
4437
|
+
const THEME_TOKEN_COLOR_KEYS = /* @__PURE__ */ new Set([
|
|
4438
|
+
"text",
|
|
4439
|
+
"textMuted",
|
|
4440
|
+
"bg",
|
|
4441
|
+
"bgSoft",
|
|
4442
|
+
"border",
|
|
4443
|
+
"borderStrong",
|
|
4444
|
+
"buttonBg",
|
|
4445
|
+
"primary",
|
|
4446
|
+
"primaryDeep",
|
|
4447
|
+
"focus",
|
|
4448
|
+
"okBg",
|
|
4449
|
+
"okBorder",
|
|
4450
|
+
"okText",
|
|
4451
|
+
"warnBg",
|
|
4452
|
+
"warnBorder",
|
|
4453
|
+
"warnText",
|
|
4454
|
+
"badBg",
|
|
4455
|
+
"badBorder",
|
|
4456
|
+
"badText",
|
|
4457
|
+
"busyBg",
|
|
4458
|
+
"busyBorder",
|
|
4459
|
+
"busyText",
|
|
4460
|
+
"newText",
|
|
4461
|
+
"newOkText"
|
|
4462
|
+
]);
|
|
4463
|
+
function themeTokensError(raw) {
|
|
4464
|
+
return /* @__PURE__ */ new Error(`[dsh-plugin-update] \u4E3B\u9898\u53C2\u6570 themeTokens \u975E\u6CD5\uFF1A\u53EA\u6536\u5DF2\u77E5 token \u952E\uFF08\u989C\u8272\u7528 hex \u6216\u82F1\u6587\u540D\uFF0C\u5B57\u4F53/\u5706\u89D2/\u9634\u5F71/\u5C3A\u5BF8\u4E3A\u5B89\u5168 CSS \u503C\uFF0CentryScale \u4E3A\u5927\u4E8E 0 \u7684\u6709\u9650\u6570\uFF09\uFF08\u6536\u5230 ${JSON.stringify(raw ?? null)})`);
|
|
4465
|
+
}
|
|
4466
|
+
function isSafeThemeCssValue(value) {
|
|
4467
|
+
const v = value.trim();
|
|
4468
|
+
if (!v || v.length > 200) return false;
|
|
4469
|
+
if (/[;"'<>\`{}!&]/.test(v)) return false;
|
|
4470
|
+
if (/url\s*\(/i.test(v)) return false;
|
|
4471
|
+
if (/expression\s*\(/i.test(v)) return false;
|
|
4472
|
+
if (/javascript\s*:/i.test(v)) return false;
|
|
4473
|
+
return true;
|
|
4474
|
+
}
|
|
4475
|
+
function isThemeColorValue(value) {
|
|
4476
|
+
const v = value.trim();
|
|
4477
|
+
if (!v || v.length > 100) return false;
|
|
4478
|
+
return /^(?:#[0-9a-fA-F]{3}|#[0-9a-fA-F]{6}|#[0-9a-fA-F]{8}|[a-zA-Z]+)$/.test(v);
|
|
4479
|
+
}
|
|
4480
|
+
function themeTokensStyleFor(tokens) {
|
|
4481
|
+
if (tokens === void 0 || tokens === null) return "";
|
|
4482
|
+
if (typeof tokens !== "object" || Array.isArray(tokens)) throw themeTokensError(tokens);
|
|
4483
|
+
for (const key of Object.keys(tokens)) if (!Object.prototype.hasOwnProperty.call(THEME_TOKEN_VARS, key)) throw themeTokensError(tokens);
|
|
4484
|
+
const parts = [];
|
|
4485
|
+
for (const key of Object.keys(THEME_TOKEN_VARS)) {
|
|
4486
|
+
const value = tokens[key];
|
|
4487
|
+
if (value === void 0) continue;
|
|
4488
|
+
if (key === "entryScale") {
|
|
4489
|
+
if (typeof value !== "number" || !Number.isFinite(value) || value <= 0) throw themeTokensError(tokens);
|
|
4490
|
+
parts.push(THEME_TOKEN_VARS[key] + ":" + String(value));
|
|
4491
|
+
continue;
|
|
4492
|
+
}
|
|
4493
|
+
if (typeof value !== "string") throw themeTokensError(tokens);
|
|
4494
|
+
const text = value.trim();
|
|
4495
|
+
if (THEME_TOKEN_COLOR_KEYS.has(key)) {
|
|
4496
|
+
if (!isThemeColorValue(text)) throw themeTokensError(tokens);
|
|
4497
|
+
} else if (!isSafeThemeCssValue(text)) throw themeTokensError(tokens);
|
|
4498
|
+
parts.push(THEME_TOKEN_VARS[key] + ":" + text);
|
|
4499
|
+
}
|
|
4500
|
+
return parts.join(";");
|
|
4501
|
+
}
|
|
4326
4502
|
const PANEL_SKIPPED_MAX = 50;
|
|
4327
4503
|
function panelSkipKey(pluginId) {
|
|
4328
4504
|
return `dsh-upd-skipped/${String(pluginId)}`;
|
|
@@ -4572,7 +4748,8 @@ ${note}${blocks.join("\n")}
|
|
|
4572
4748
|
} catch {
|
|
4573
4749
|
staleFailure = false;
|
|
4574
4750
|
}
|
|
4575
|
-
|
|
4751
|
+
const gated = !(typeof errorKind === "string" && errorKind.trim()) && !lastError ? checkPrejudgeOfView(input.checkPrejudge, snapshot) : null;
|
|
4752
|
+
if (!staleFailure && !gated && (failedCode || jobState === "failed" || jobState === "interrupted")) {
|
|
4576
4753
|
const code = failedCode || "install-failed";
|
|
4577
4754
|
const copy = failureCopy(code, l);
|
|
4578
4755
|
const checkDetail = copy?.zh ?? code;
|
|
@@ -4625,6 +4802,25 @@ ${note}${blocks.join("\n")}
|
|
|
4625
4802
|
}
|
|
4626
4803
|
if (snapshot.canInstall && snapshot.latestVersion) {
|
|
4627
4804
|
const running = snapshot.installed === false ? copyText("panel.banner.not-installed", l) : snapshot.runningVersion;
|
|
4805
|
+
if (gated) {
|
|
4806
|
+
const unlock = formatUnlockAt(gated.unlockAtMs, l) ?? "";
|
|
4807
|
+
return {
|
|
4808
|
+
banner: {
|
|
4809
|
+
kind: "update",
|
|
4810
|
+
title: copyText("panel.banner.update-gated-title", l, {
|
|
4811
|
+
latest: snapshot.latestVersion,
|
|
4812
|
+
unlock
|
|
4813
|
+
}),
|
|
4814
|
+
action: copyText("panel.banner.update-action", l)
|
|
4815
|
+
},
|
|
4816
|
+
installEnabled: false,
|
|
4817
|
+
installLabel: copyText("panel.action.install-version", l, { latest: snapshot.latestVersion }),
|
|
4818
|
+
skippedLatest: false,
|
|
4819
|
+
showManual: manual ? true : false,
|
|
4820
|
+
showReset: false,
|
|
4821
|
+
queueNote
|
|
4822
|
+
};
|
|
4823
|
+
}
|
|
4628
4824
|
return {
|
|
4629
4825
|
banner: {
|
|
4630
4826
|
kind: "update",
|
|
@@ -4960,6 +5156,99 @@ ${note}${blocks.join("\n")}
|
|
|
4960
5156
|
const l = normalizeLangTag(lang ?? "zh");
|
|
4961
5157
|
return copyText(CHAPTER_KEYS[index - 1], l);
|
|
4962
5158
|
}
|
|
5159
|
+
function checkPrejudgeOfView(pre, snapshot) {
|
|
5160
|
+
try {
|
|
5161
|
+
if (!pre || !snapshot?.canInstall) return null;
|
|
5162
|
+
const latest = typeof snapshot.latestVersion === "string" ? snapshot.latestVersion.trim() : "";
|
|
5163
|
+
const target = typeof pre.targetVersion === "string" ? pre.targetVersion.trim() : "";
|
|
5164
|
+
if (!latest || !target || latest !== target) return null;
|
|
5165
|
+
if (typeof pre.unlockAtMs !== "number" || !Number.isFinite(pre.unlockAtMs)) return null;
|
|
5166
|
+
if (typeof pre.nowMs !== "number" || !Number.isFinite(pre.nowMs) || pre.nowMs >= pre.unlockAtMs) return null;
|
|
5167
|
+
return {
|
|
5168
|
+
targetVersion: target,
|
|
5169
|
+
unlockAtMs: pre.unlockAtMs
|
|
5170
|
+
};
|
|
5171
|
+
} catch {
|
|
5172
|
+
return null;
|
|
5173
|
+
}
|
|
5174
|
+
}
|
|
5175
|
+
function fallbackBlockedVersionOf(failure, pluginId) {
|
|
5176
|
+
try {
|
|
5177
|
+
return vetFailureRef(failure, pluginId);
|
|
5178
|
+
} catch {
|
|
5179
|
+
return null;
|
|
5180
|
+
}
|
|
5181
|
+
}
|
|
5182
|
+
function vetFailureRef(failure, pluginId) {
|
|
5183
|
+
const kind = typeof failure?.causeKind === "string" ? failure.causeKind.trim() : "";
|
|
5184
|
+
if (!kind || !CAUSE_KINDS.includes(kind)) return null;
|
|
5185
|
+
const spec = typeof failure?.causePackage === "string" ? failure.causePackage.trim() : "";
|
|
5186
|
+
if (!spec) return null;
|
|
5187
|
+
const target = typeof failure?.causeTarget === "string" && failure.causeTarget.trim() ? failure.causeTarget.trim() : typeof pluginId === "string" && pluginId.trim() ? pluginId.trim() : "";
|
|
5188
|
+
if (!target) return null;
|
|
5189
|
+
if (blameCausePackage(spec, target) !== "target") return null;
|
|
5190
|
+
const direct = typeof failure?.targetVersion === "string" ? failure.targetVersion.trim() : "";
|
|
5191
|
+
if (direct) return direct;
|
|
5192
|
+
const at = spec.lastIndexOf("@");
|
|
5193
|
+
return (at > 0 ? spec.slice(at + 1).trim() : "") || null;
|
|
5194
|
+
}
|
|
5195
|
+
function fallbackCauseFromDetail(detail, errorCode, pluginId) {
|
|
5196
|
+
try {
|
|
5197
|
+
const facts = interpretInstallCause({
|
|
5198
|
+
errorCode: typeof errorCode === "string" && errorCode ? errorCode : "install-failed",
|
|
5199
|
+
detail,
|
|
5200
|
+
targetPackageName: typeof pluginId === "string" ? pluginId : void 0
|
|
5201
|
+
});
|
|
5202
|
+
if (!facts || facts.kind !== "minimum-release-age" || facts.blame !== "target") return null;
|
|
5203
|
+
const targetVersion = typeof facts.packageVersion === "string" && facts.packageVersion.trim() ? facts.packageVersion.trim() : null;
|
|
5204
|
+
if (!targetVersion) return null;
|
|
5205
|
+
let windowMs = null;
|
|
5206
|
+
let windowSource = "unknown";
|
|
5207
|
+
if (typeof facts.windowMinutes === "number" && Number.isFinite(facts.windowMinutes) && facts.windowMinutes > 0) {
|
|
5208
|
+
windowMs = facts.windowMinutes * 6e4;
|
|
5209
|
+
windowSource = "message";
|
|
5210
|
+
} else if (typeof facts.cutoffMs === "number" && typeof facts.publishedAtMs === "number" && facts.cutoffMs > facts.publishedAtMs) windowMs = facts.cutoffMs - facts.publishedAtMs;
|
|
5211
|
+
return {
|
|
5212
|
+
kind: facts.kind,
|
|
5213
|
+
packageName: facts.packageName,
|
|
5214
|
+
targetVersion,
|
|
5215
|
+
windowMs,
|
|
5216
|
+
windowSource,
|
|
5217
|
+
publishedAtMs: typeof facts.publishedAtMs === "number" ? facts.publishedAtMs : null
|
|
5218
|
+
};
|
|
5219
|
+
} catch {
|
|
5220
|
+
return null;
|
|
5221
|
+
}
|
|
5222
|
+
}
|
|
5223
|
+
function fallbackCauseFromDiag(diag, detail, errorCode, preferredTargetVersion) {
|
|
5224
|
+
try {
|
|
5225
|
+
const d = diag && typeof diag === "object" && !Array.isArray(diag) ? diag : null;
|
|
5226
|
+
if (!d) return null;
|
|
5227
|
+
const dKind = typeof d["causeKind"] === "string" ? d["causeKind"].trim() : "";
|
|
5228
|
+
const dSpec = typeof d["causePackage"] === "string" ? d["causePackage"].trim() : "";
|
|
5229
|
+
const dTarget = typeof d["targetPackageName"] === "string" ? d["targetPackageName"].trim() : "";
|
|
5230
|
+
if (!dKind || !CAUSE_KINDS.includes(dKind) || !dSpec || !dTarget) return null;
|
|
5231
|
+
if (blameCausePackage(dSpec, dTarget) !== "target") return null;
|
|
5232
|
+
const timed = fallbackCauseFromDetail(detail, errorCode, dTarget);
|
|
5233
|
+
const preferred = typeof preferredTargetVersion === "string" ? preferredTargetVersion.trim() : "";
|
|
5234
|
+
const at = dSpec.lastIndexOf("@");
|
|
5235
|
+
const specVer = at > 0 ? dSpec.slice(at + 1).trim() : "";
|
|
5236
|
+
const targetVersion = preferred || timed?.targetVersion || specVer;
|
|
5237
|
+
if (!targetVersion) return null;
|
|
5238
|
+
return {
|
|
5239
|
+
kind: dKind,
|
|
5240
|
+
spec: dSpec,
|
|
5241
|
+
target: dTarget,
|
|
5242
|
+
packageName: at > 0 && dSpec.slice(0, at).trim() ? dSpec.slice(0, at).trim() : dTarget,
|
|
5243
|
+
targetVersion,
|
|
5244
|
+
windowMs: timed?.windowMs ?? null,
|
|
5245
|
+
windowSource: timed?.windowSource ?? "unknown",
|
|
5246
|
+
publishedAtMs: timed?.publishedAtMs ?? null
|
|
5247
|
+
};
|
|
5248
|
+
} catch {
|
|
5249
|
+
return null;
|
|
5250
|
+
}
|
|
5251
|
+
}
|
|
4963
5252
|
function formatLatchTime(atMs, lang) {
|
|
4964
5253
|
if (typeof atMs !== "number" || !Number.isFinite(atMs) || atMs <= 0) return null;
|
|
4965
5254
|
const raw = typeof lang === "string" ? lang.trim().replace(/_/g, "-") : "";
|
|
@@ -5022,15 +5311,30 @@ ${note}${blocks.join("\n")}
|
|
|
5022
5311
|
const busyAct = input.busyAct;
|
|
5023
5312
|
const checkBusy = busyAct === "check";
|
|
5024
5313
|
const installBusy = busyAct === "install";
|
|
5314
|
+
const fallbackBusy = busyAct === "fallback";
|
|
5025
5315
|
const jobState = snapshot?.job?.state;
|
|
5026
|
-
const macroBusy = busyAct === "check" || busyAct === "install" || jobState === "installing" || jobState === "verifying";
|
|
5316
|
+
const macroBusy = busyAct === "check" || busyAct === "install" || fallbackBusy || jobState === "installing" || jobState === "verifying";
|
|
5317
|
+
const gatePrejudge = b.kind === "update" ? checkPrejudgeOfView(input.checkPrejudge ?? null, snapshot) : null;
|
|
5318
|
+
const gateOfferRaw = input.fallbackOffer ?? null;
|
|
5319
|
+
const gateCandidate = gatePrejudge && typeof gateOfferRaw?.candidate === "string" && gateOfferRaw.candidate.trim() && typeof gateOfferRaw?.targetVersion === "string" && gateOfferRaw.targetVersion.trim() === gatePrejudge.targetVersion ? gateOfferRaw.candidate.trim() : null;
|
|
5027
5320
|
actions.push("<div class=\"dsh-upd-actions\">");
|
|
5028
|
-
actions.push((checkBusy ? `<button type="button" data-action="check" disabled aria-busy="true" title="${escapeHtml$3(copyText("panel.action.checking-busy-title", l))}">${escapeHtml$3(copyText("panel.action.checking-busy", l))}</button>` : `<button type="button" data-action="check" title="${escapeHtml$3(copyText("panel.action.check-title", l))}"${macroBusy ? " disabled" : ""}>${escapeHtml$3(copyText("panel.action.check", l))}</button>`) + (installBusy ? `<button type="button" data-action="install" data-primary="1" disabled aria-busy="true" title="${escapeHtml$3(copyText("panel.action.installing-busy-title", l))}">${escapeHtml$3(copyText("panel.action.installing-busy", l))}</button>` : `<button type="button" data-action="install" data-primary="1" title="${escapeHtml$3(copyText("panel.action.install-title", l
|
|
5321
|
+
actions.push((checkBusy ? `<button type="button" data-action="check" disabled aria-busy="true" title="${escapeHtml$3(copyText("panel.action.checking-busy-title", l))}">${escapeHtml$3(copyText("panel.action.checking-busy", l))}</button>` : `<button type="button" data-action="check" title="${escapeHtml$3(copyText("panel.action.check-title", l))}"${macroBusy ? " disabled" : ""}>${escapeHtml$3(copyText("panel.action.check", l))}</button>`) + (installBusy ? `<button type="button" data-action="install" data-primary="1" disabled aria-busy="true" title="${escapeHtml$3(copyText("panel.action.installing-busy-title", l))}">${escapeHtml$3(copyText("panel.action.installing-busy", l))}</button>` : `<button type="button" data-action="install" data-primary="1" title="${escapeHtml$3(gatePrejudge ? copyText("panel.action.install-gated-title", l, {
|
|
5322
|
+
latest: snapshot?.latestVersion ?? "",
|
|
5323
|
+
unlock: formatUnlockAt(gatePrejudge.unlockAtMs, l) ?? ""
|
|
5324
|
+
}) : copyText("panel.action.install-title", l))}"${macroBusy || !view.installEnabled ? " disabled" : ""}>${escapeHtml$3(view.installLabel)}</button>`));
|
|
5029
5325
|
if (snapshot?.latestVersion && !view.skippedLatest && view.banner.kind === "update") actions.push(`<button type="button" data-action="skip" title="${escapeHtml$3(copyText("panel.action.skip-title", l))}">${escapeHtml$3(copyText("panel.action.skip", l))}</button>`);
|
|
5326
|
+
if (gatePrejudge) actions.push(gateCandidate ? `<button type="button" data-action="install-fallback-confirm" data-primary="1" title="${escapeHtml$3(copyText("panel.action.install-fallback-confirm-title", l))}"${macroBusy || fallbackBusy ? " disabled" : ""}>${escapeHtml$3(copyText("panel.action.install-fallback-confirm", l, { version: gateCandidate }))}</button>` : fallbackBusy ? `<button type="button" data-action="install-fallback" data-primary="1" disabled aria-busy="true" title="${escapeHtml$3(copyText("panel.action.install-fallback-title", l))}">${escapeHtml$3(copyText("panel.action.install-fallback", l))}</button>` : `<button type="button" data-action="install-fallback" data-primary="1" title="${escapeHtml$3(copyText("panel.action.install-fallback-title", l))}"${macroBusy ? " disabled" : ""}>${escapeHtml$3(copyText("panel.action.install-fallback", l))}</button>`);
|
|
5030
5327
|
if (view.showReset && snapshot?.latestVersion) actions.push(`<button type="button" data-action="reset-skip" title="${escapeHtml$3(copyText("panel.action.unskip-title", l))}">${escapeHtml$3(copyText("panel.action.unskip", l, { version: snapshot.latestVersion }))}</button>`);
|
|
5031
5328
|
if (view.showManual && manual) actions.push(`<button type="button" data-action="copy-manual" title="${escapeHtml$3(copyText("panel.action.copy-manual-title", l))}">${escapeHtml$3(copyText("panel.action.copy-manual", l))}</button>`);
|
|
5032
5329
|
if (b.kind === "restart") actions.push(`<button type="button" data-action="restart-hint" title="${escapeHtml$3(copyText("panel.action.restart-host-title", l))}">${escapeHtml$3(copyText("panel.action.restart-host", l))}</button>`);
|
|
5033
|
-
|
|
5330
|
+
const failureForFallback = input.failure ?? null;
|
|
5331
|
+
const fallbackBlocked = b.kind === "failed" ? fallbackBlockedVersionOf(failureForFallback, pluginId) : null;
|
|
5332
|
+
const fallbackOfferRaw = input.fallbackOffer ?? null;
|
|
5333
|
+
const fallbackCandidate = fallbackBlocked && typeof fallbackOfferRaw?.candidate === "string" && fallbackOfferRaw.candidate.trim() ? fallbackOfferRaw.candidate.trim() : null;
|
|
5334
|
+
if (fallbackBlocked) {
|
|
5335
|
+
actions.push(fallbackCandidate ? `<button type="button" data-action="install-fallback-confirm" data-primary="1" title="${escapeHtml$3(copyText("panel.action.install-fallback-confirm-title", l))}"${macroBusy || fallbackBusy ? " disabled" : ""}>${escapeHtml$3(copyText("panel.action.install-fallback-confirm", l, { version: fallbackCandidate }))}</button>` : fallbackBusy ? `<button type="button" data-action="install-fallback" data-primary="1" disabled aria-busy="true" title="${escapeHtml$3(copyText("panel.action.install-fallback-title", l))}">${escapeHtml$3(copyText("panel.action.install-fallback", l))}</button>` : `<button type="button" data-action="install-fallback" data-primary="1" title="${escapeHtml$3(copyText("panel.action.install-fallback-title", l))}"${macroBusy ? " disabled" : ""}>${escapeHtml$3(copyText("panel.action.install-fallback", l))}</button>`);
|
|
5336
|
+
actions.push(`<button type="button" data-action="wait-latest" title="${escapeHtml$3(copyText("panel.action.wait-latest-title", l))}"${macroBusy || fallbackBusy ? " disabled" : ""}>${escapeHtml$3(copyText("panel.action.wait-latest", l))}</button>`);
|
|
5337
|
+
} else if (b.kind === "failed") actions.push(`<button type="button" data-action="dismiss-failure" title="${escapeHtml$3(copyText("panel.action.dismiss-title", l))}">${escapeHtml$3(copyText("panel.action.dismiss", l))}</button>`);
|
|
5034
5338
|
const failureRef = input.failure;
|
|
5035
5339
|
if (snapshot || b.kind === "failed" || !!failureRef) actions.push(`<button type="button" data-action="copy-diag" title="${escapeHtml$3(copyText("panel.action.copy-diag-title", l))}">${escapeHtml$3(copyText("panel.action.copy-diag", l))}</button>`);
|
|
5036
5340
|
actions.push("</div>");
|
|
@@ -5174,7 +5478,7 @@ ${UPDATE_PANEL_ARCHIVE_CSS}` : UPDATE_PANEL_CSS}</style>
|
|
|
5174
5478
|
${body}`;
|
|
5175
5479
|
}
|
|
5176
5480
|
//#endregion
|
|
5177
|
-
//#region ../../node_modules/.pnpm/dsh-plugin-update@0.18.
|
|
5481
|
+
//#region ../../node_modules/.pnpm/dsh-plugin-update@0.18.7/node_modules/dsh-plugin-update/dist/entry.js
|
|
5178
5482
|
const UPDATE_ENTRY_CSS = [
|
|
5179
5483
|
".dsh-upd-entry{display:inline-flex;align-items:center;gap:8px;font:13px/1.6 var(--dsh-update-font-sans,system-ui,\"Microsoft YaHei\",sans-serif);font-size:var(--dsh-update-entry-font-size,13px);color:var(--dsh-update-text,#1f2937)}",
|
|
5180
5484
|
".dsh-upd-entry-btn{font:inherit;border:1px solid var(--dsh-update-border,#d1d5db);border-radius:var(--dsh-update-entry-border-radius,6px);",
|
|
@@ -5288,7 +5592,7 @@ ${body}`;
|
|
|
5288
5592
|
}
|
|
5289
5593
|
}
|
|
5290
5594
|
//#endregion
|
|
5291
|
-
//#region ../../node_modules/.pnpm/dsh-plugin-update@0.18.
|
|
5595
|
+
//#region ../../node_modules/.pnpm/dsh-plugin-update@0.18.7/node_modules/dsh-plugin-update/dist/panel-batch.js
|
|
5292
5596
|
const BATCH_PANEL_POLL = {
|
|
5293
5597
|
defaultMs: 1500,
|
|
5294
5598
|
minMs: 250
|
|
@@ -5305,7 +5609,7 @@ ${body}`;
|
|
|
5305
5609
|
prefsSave: p + ".batchPrefsSave"
|
|
5306
5610
|
};
|
|
5307
5611
|
}
|
|
5308
|
-
function batchLedgerCounts(rows, inventory, session) {
|
|
5612
|
+
function batchLedgerCounts(rows, inventory, session, compliantDone) {
|
|
5309
5613
|
const counts = {
|
|
5310
5614
|
updatable: 0,
|
|
5311
5615
|
installing: 0,
|
|
@@ -5317,9 +5621,15 @@ ${body}`;
|
|
|
5317
5621
|
};
|
|
5318
5622
|
for (const row of rows) {
|
|
5319
5623
|
const phase = asBatchPhase(row.phase);
|
|
5320
|
-
|
|
5321
|
-
|
|
5322
|
-
|
|
5624
|
+
const doneRestart = phase === "failed" ? compliantDone?.get(row.key) : void 0;
|
|
5625
|
+
if (doneRestart !== void 0) {
|
|
5626
|
+
if (doneRestart) counts.restart += 1;
|
|
5627
|
+
else counts.settled += 1;
|
|
5628
|
+
} else if (isQueueBusyRow(row)) counts.updatable += 1;
|
|
5629
|
+
else if (phase === "failed") {
|
|
5630
|
+
if (row.error === "pending-restart") counts.restart += 1;
|
|
5631
|
+
else counts.failed += 1;
|
|
5632
|
+
} else if (phase === "installing") counts.installing += 1;
|
|
5323
5633
|
else if (phase === "ready") counts.updatable += 1;
|
|
5324
5634
|
else if (phase === "pending") counts[isInUnfinishedRound(session, row.key) ? "pending" : ledgerKnowledgeBucket(knowledgeEntryOf(inventory, row.key))] += 1;
|
|
5325
5635
|
else if (phase === "checking") counts.pending += 1;
|
|
@@ -5541,7 +5851,14 @@ ${body}`;
|
|
|
5541
5851
|
const expandedKey = typeof input.expandedKey === "string" && input.expandedKey ? input.expandedKey : null;
|
|
5542
5852
|
const lastError = typeof input.lastError === "string" && input.lastError ? input.lastError : null;
|
|
5543
5853
|
const loaded = input.loaded === void 0 ? rows.length > 0 : input.loaded === true;
|
|
5544
|
-
const
|
|
5854
|
+
const compliantFacts = /* @__PURE__ */ new Map();
|
|
5855
|
+
for (const row of rows) {
|
|
5856
|
+
const fact = compliantInstalledOf(row);
|
|
5857
|
+
if (fact) compliantFacts.set(row.key, fact);
|
|
5858
|
+
}
|
|
5859
|
+
const compliantDone = /* @__PURE__ */ new Map();
|
|
5860
|
+
for (const [key, fact] of compliantFacts) compliantDone.set(key, fact.needsRestart);
|
|
5861
|
+
const counts = batchLedgerCounts(rows, input.inventory, input.session, compliantDone);
|
|
5545
5862
|
const installing = counts.installing > 0;
|
|
5546
5863
|
const macroBusy = input.inFlight === true || installing;
|
|
5547
5864
|
const total = rows.length;
|
|
@@ -5564,8 +5881,32 @@ ${body}`;
|
|
|
5564
5881
|
lang,
|
|
5565
5882
|
knowledge: null,
|
|
5566
5883
|
inRound: false,
|
|
5567
|
-
worldLatest: null
|
|
5884
|
+
worldLatest: null,
|
|
5885
|
+
fallbackCandidate: null,
|
|
5886
|
+
fallbackBusy: false,
|
|
5887
|
+
fallbackWaiting: false
|
|
5568
5888
|
};
|
|
5889
|
+
const fallbackOffers = input.fallbackOffers && typeof input.fallbackOffers === "object" ? input.fallbackOffers : {};
|
|
5890
|
+
const fallbackBusyKey = typeof input.fallbackBusyKey === "string" && input.fallbackBusyKey ? input.fallbackBusyKey : null;
|
|
5891
|
+
const compliantInput = isObject$2(input.compliant) ? input.compliant : null;
|
|
5892
|
+
const compliantWaitInput = compliantInput && isObject$2(compliantInput["wait"]) ? compliantInput["wait"] : null;
|
|
5893
|
+
const waitKeys = [];
|
|
5894
|
+
if (compliantWaitInput && Array.isArray(compliantWaitInput["keys"])) {
|
|
5895
|
+
for (const key of compliantWaitInput["keys"]) if (typeof key === "string" && key) waitKeys.push(key);
|
|
5896
|
+
}
|
|
5897
|
+
const waitUnlockAtMs = compliantWaitInput && typeof compliantWaitInput["unlockAtMs"] === "number" ? compliantWaitInput["unlockAtMs"] : null;
|
|
5898
|
+
const compliantUnlocksInput = compliantInput && isObject$2(compliantInput["unlocks"]) ? compliantInput["unlocks"] : null;
|
|
5899
|
+
const compliant = compliantInput && typeof compliantInput["gated"] === "number" ? {
|
|
5900
|
+
gated: compliantInput["gated"],
|
|
5901
|
+
confirmList: typeof compliantInput["confirmList"] === "string" && compliantInput["confirmList"] ? compliantInput["confirmList"] : null,
|
|
5902
|
+
confirmCount: typeof compliantInput["confirmCount"] === "number" ? compliantInput["confirmCount"] : 0,
|
|
5903
|
+
busy: compliantInput["busy"] === true,
|
|
5904
|
+
wait: waitKeys.length > 0 ? {
|
|
5905
|
+
keys: waitKeys,
|
|
5906
|
+
unlockAtMs: waitUnlockAtMs
|
|
5907
|
+
} : null,
|
|
5908
|
+
unlocks: compliantUnlocksInput ? compliantUnlocksInput : null
|
|
5909
|
+
} : null;
|
|
5569
5910
|
const parts = [];
|
|
5570
5911
|
parts.push("<div class=\"dsh-upd-batch-head\">");
|
|
5571
5912
|
parts.push("<div class=\"dsh-upd-batch-title\">" + escapeHtml$2(batchText("batch.header.title", lang)) + " · <i>" + escapeHtml$2(batchText("batch.seal.ledger", lang)) + "</i></div>");
|
|
@@ -5577,7 +5918,7 @@ ${body}`;
|
|
|
5577
5918
|
parts.push("</div>");
|
|
5578
5919
|
const summary = loaded ? batchSummaryText(counts, rows, total, installing, lastError !== null, lang) : batchText("batch.banner.loading", lang);
|
|
5579
5920
|
parts.push("<div class=\"dsh-upd-batch-sum\" role=\"status\" aria-live=\"polite\">" + escapeHtml$2(summary) + "</div>");
|
|
5580
|
-
parts.push(bannersHTML(rows, titles, lastError, lang));
|
|
5921
|
+
parts.push(bannersHTML(rows, titles, lastError, lang, compliant, compliantFacts));
|
|
5581
5922
|
const session = isObject$2(input.session) ? input.session : null;
|
|
5582
5923
|
const unfinished = unfinishedCount(rows, session ?? void 0);
|
|
5583
5924
|
const showControls = total > 0 && hasUnfinishedRows(rows, session ?? void 0);
|
|
@@ -5590,6 +5931,10 @@ ${body}`;
|
|
|
5590
5931
|
const expanded = row.key === expandedKey;
|
|
5591
5932
|
const inRound = isInUnfinishedRound(input.session, row.key);
|
|
5592
5933
|
const knowledge = !inRound ? knowledgeEntryOf(input.inventory, row.key) : null;
|
|
5934
|
+
const offerRaw = fallbackOffers[row.key];
|
|
5935
|
+
const offerCand = isObject$2(offerRaw) && typeof offerRaw["candidate"] === "string" && offerRaw["candidate"].trim() ? offerRaw["candidate"].trim() : null;
|
|
5936
|
+
const offerTarget = isObject$2(offerRaw) && typeof offerRaw["targetVersion"] === "string" ? offerRaw["targetVersion"] : null;
|
|
5937
|
+
const latest = latestVersionOf(row);
|
|
5593
5938
|
parts.push(rowSetHTML(row, {
|
|
5594
5939
|
...ctx,
|
|
5595
5940
|
expanded,
|
|
@@ -5599,7 +5944,10 @@ ${body}`;
|
|
|
5599
5944
|
lang,
|
|
5600
5945
|
knowledge,
|
|
5601
5946
|
inRound,
|
|
5602
|
-
worldLatest: worldUpdateVersion(row, knowledge, sessionUpdatedAtOf(input.session, row.key))
|
|
5947
|
+
worldLatest: worldUpdateVersion(row, knowledge, sessionUpdatedAtOf(input.session, row.key)),
|
|
5948
|
+
fallbackCandidate: offerCand && offerTarget === latest ? offerCand : null,
|
|
5949
|
+
fallbackBusy: fallbackBusyKey === row.key,
|
|
5950
|
+
fallbackWaiting: waitKeys.includes(row.key)
|
|
5603
5951
|
}));
|
|
5604
5952
|
}
|
|
5605
5953
|
parts.push("</div>");
|
|
@@ -5630,12 +5978,18 @@ ${body}`;
|
|
|
5630
5978
|
if (target !== null) {
|
|
5631
5979
|
const rawSkipped = skippedVersions[target.key];
|
|
5632
5980
|
const skippedForDialog = typeof rawSkipped === "string" && rawSkipped ? rawSkipped : null;
|
|
5981
|
+
const offerRaw = fallbackOffers[target.key];
|
|
5982
|
+
const offerCand = isObject$2(offerRaw) && typeof offerRaw["candidate"] === "string" && offerRaw["candidate"].trim() ? offerRaw["candidate"].trim() : null;
|
|
5983
|
+
const offerTarget = isObject$2(offerRaw) && typeof offerRaw["targetVersion"] === "string" ? offerRaw["targetVersion"] : null;
|
|
5633
5984
|
detailDialog = detailDialogHTML(target, {
|
|
5634
5985
|
...ctx,
|
|
5635
5986
|
expanded: true,
|
|
5636
5987
|
skipped: skippedForDialog,
|
|
5637
5988
|
notice: target.key === detailNoticeKey ? notice : null,
|
|
5638
|
-
changelogMarkdown: typeof changelogs[target.key] === "string" ? changelogs[target.key] : null
|
|
5989
|
+
changelogMarkdown: typeof changelogs[target.key] === "string" ? changelogs[target.key] : null,
|
|
5990
|
+
fallbackCandidate: offerCand && offerTarget === latestVersionOf(target) ? offerCand : null,
|
|
5991
|
+
fallbackBusy: fallbackBusyKey === target.key,
|
|
5992
|
+
fallbackWaiting: waitKeys.includes(target.key)
|
|
5639
5993
|
});
|
|
5640
5994
|
}
|
|
5641
5995
|
}
|
|
@@ -5682,8 +6036,33 @@ ${body}`;
|
|
|
5682
6036
|
tone: "ink"
|
|
5683
6037
|
};
|
|
5684
6038
|
}
|
|
5685
|
-
function bannersHTML(rows, titles, lastError, lang) {
|
|
6039
|
+
function bannersHTML(rows, titles, lastError, lang, compliant = null, facts) {
|
|
5686
6040
|
const l = langOf(lang);
|
|
6041
|
+
const unlocks = compliant?.unlocks ?? null;
|
|
6042
|
+
const done = new Map(facts ?? []);
|
|
6043
|
+
if (!facts) for (const row of rows) {
|
|
6044
|
+
const fact = compliantInstalledOf(row);
|
|
6045
|
+
if (fact) done.set(row.key, fact);
|
|
6046
|
+
}
|
|
6047
|
+
const doneLineOf = (row, fact) => {
|
|
6048
|
+
const raw = unlocks && typeof unlocks[row.key] === "number" ? unlocks[row.key] : null;
|
|
6049
|
+
const time = raw !== null ? formatUnlockAt(raw, l) : null;
|
|
6050
|
+
const vars = {
|
|
6051
|
+
title: titleOf(row, titles),
|
|
6052
|
+
version: fact.version,
|
|
6053
|
+
target: fact.target
|
|
6054
|
+
};
|
|
6055
|
+
return time ? escapeHtml$2(batchText("batch.banner.compliant-done-gated", l, {
|
|
6056
|
+
...vars,
|
|
6057
|
+
time
|
|
6058
|
+
})) : escapeHtml$2(batchText("batch.banner.compliant-done", l, vars));
|
|
6059
|
+
};
|
|
6060
|
+
const gatedCandidates = rows.filter((row) => batchFallbackCauseOf(row) !== null && singleFallbackPhoneOf(row) !== null && !done.has(row.key));
|
|
6061
|
+
const gated = typeof compliant?.gated === "number" ? compliant.gated : gatedCandidates.length;
|
|
6062
|
+
const confirmList = typeof compliant?.confirmList === "string" && compliant.confirmList ? compliant.confirmList : null;
|
|
6063
|
+
const confirmCount = typeof compliant?.confirmCount === "number" ? compliant.confirmCount : 0;
|
|
6064
|
+
const compliantBusy = compliant?.busy === true;
|
|
6065
|
+
const waitKeys = compliant?.wait && Array.isArray(compliant.wait.keys) ? compliant.wait.keys : [];
|
|
5687
6066
|
const parts = [];
|
|
5688
6067
|
if (lastError) {
|
|
5689
6068
|
const copy = failureCopy(lastError, l);
|
|
@@ -5695,7 +6074,8 @@ ${body}`;
|
|
|
5695
6074
|
})) + "</strong></div></div>");
|
|
5696
6075
|
if (act) parts.push("<div class=\"dsh-upd-banner-sub\">" + escapeHtml$2(act) + "</div>");
|
|
5697
6076
|
}
|
|
5698
|
-
const
|
|
6077
|
+
const pendingRestartRow = (row) => asBatchPhase(row.phase) === "failed" && row.error === "pending-restart";
|
|
6078
|
+
const failed = rows.filter((row) => asBatchPhase(row.phase) === "failed" && !isQueueBusyRow(row) && !pendingRestartRow(row) && !done.has(row.key));
|
|
5699
6079
|
if (failed.length > 0) {
|
|
5700
6080
|
const lines = failed.map((row) => {
|
|
5701
6081
|
const code = row.error || "install-failed";
|
|
@@ -5706,7 +6086,22 @@ ${body}`;
|
|
|
5706
6086
|
parts.push("<div class=\"dsh-upd-banner\" data-kind=\"failed\" data-mini=\"阻\" role=\"status\"><div><span class=\"dsh-upd-sealmini\" aria-hidden=\"true\">阻</span><strong>" + escapeHtml$2(batchText("batch.banner.failed-title", l, { n: String(failed.length) })) + "</strong></div><div class=\"dsh-upd-blist\">" + lines + "</div></div>");
|
|
5707
6087
|
if (failedAct) parts.push("<div class=\"dsh-upd-banner-sub\">" + escapeHtml$2(failedAct) + "</div>");
|
|
5708
6088
|
}
|
|
5709
|
-
|
|
6089
|
+
if (confirmList) parts.push("<div class=\"dsh-upd-banner\" data-kind=\"update\" role=\"status\"><div><strong>" + escapeHtml$2(batchText("batch.banner.compliant-confirm", l, { list: confirmList })) + "</strong></div><div class=\"dsh-upd-browline\"><span class=\"dsh-upd-blist\">" + escapeHtml$2(confirmList) + "</span><button type=\"button\" data-act=\"batch-fallback-confirm\" data-primary=\"1\"" + (compliantBusy ? " disabled" : "") + ">" + escapeHtml$2(batchText("batch.action.install-compliant-confirm", l, { n: String(confirmCount) })) + "</button></div></div>");
|
|
6090
|
+
if (waitKeys.length > 0) {
|
|
6091
|
+
const rawUnlock = compliant?.wait ? compliant.wait.unlockAtMs : null;
|
|
6092
|
+
const unlockAtMs = typeof rawUnlock === "number" ? rawUnlock : null;
|
|
6093
|
+
const time = unlockAtMs !== null ? formatUnlockAt(unlockAtMs, l) : null;
|
|
6094
|
+
const waitTitles = rows.filter((row) => waitKeys.includes(row.key)).map((row) => titleOf(row, titles)).join("、");
|
|
6095
|
+
parts.push("<div class=\"dsh-upd-banner\" data-kind=\"update\" role=\"status\"><div><strong>" + escapeHtml$2(time ? batchText("batch.banner.gated-wait", l, {
|
|
6096
|
+
n: String(waitKeys.length),
|
|
6097
|
+
time
|
|
6098
|
+
}) : batchText("batch.banner.age-gated", l, { n: String(waitKeys.length) })) + "</strong></div><div class=\"dsh-upd-browline\"><span class=\"dsh-upd-blist\">" + escapeHtml$2(waitTitles) + "</span></div></div>");
|
|
6099
|
+
} else if (gated > 0 && confirmList === null) parts.push("<div class=\"dsh-upd-banner\" data-kind=\"update\" role=\"status\"><div><strong>" + escapeHtml$2(batchText("batch.banner.age-gated", l, { n: String(gated) })) + "</strong></div><div class=\"dsh-upd-browline\"><span class=\"dsh-upd-blist\">" + escapeHtml$2(gatedCandidates.map((row) => titleOf(row, titles)).join("、")) + "</span><button type=\"button\" data-act=\"batch-fallback-scan\"" + (compliantBusy ? " disabled" : "") + " title=\"" + escapeHtml$2(copyText("panel.action.install-fallback-title", l)) + "\">" + escapeHtml$2(copyText("panel.action.install-fallback", l)) + "</button></div></div>");
|
|
6100
|
+
if (done.size > 0) {
|
|
6101
|
+
const lines = rows.filter((row) => done.has(row.key)).map((row) => "<div>" + doneLineOf(row, done.get(row.key)) + "</div>").join("");
|
|
6102
|
+
parts.push("<div class=\"dsh-upd-banner\" data-kind=\"update\" role=\"status\"><div><strong>" + escapeHtml$2(batchText("batch.banner.compliant-done-title", l, { n: String(done.size) })) + "</strong></div><div class=\"dsh-upd-blist\">" + lines + "</div></div>");
|
|
6103
|
+
}
|
|
6104
|
+
const restart = rows.filter((row) => row.restartRequired === true || pendingRestartRow(row) || done.get(row.key)?.needsRestart === true);
|
|
5710
6105
|
if (restart.length > 0) {
|
|
5711
6106
|
const restartAct = batchText("batch.banner.restart-action", l);
|
|
5712
6107
|
parts.push("<div class=\"dsh-upd-banner\" data-kind=\"restart\" role=\"status\"><div><strong>" + escapeHtml$2(batchText("batch.banner.restart-title", l, { n: String(restart.length) })) + "</strong></div><div class=\"dsh-upd-browline\"><span class=\"dsh-upd-blist\">" + restart.map((row) => escapeHtml$2(titleOf(row, titles))).join("、") + "</span><button type=\"button\" data-act=\"restart\">" + escapeHtml$2(batchText("batch.banner.restart-button", l)) + "</button></div></div>");
|
|
@@ -5714,14 +6109,29 @@ ${body}`;
|
|
|
5714
6109
|
}
|
|
5715
6110
|
return parts.join("");
|
|
5716
6111
|
}
|
|
6112
|
+
function rowFallbackButtonHTML(row, ctx) {
|
|
6113
|
+
try {
|
|
6114
|
+
if (ctx.fallbackWaiting) return "";
|
|
6115
|
+
const keyAttr = escapeHtml$2(row.key);
|
|
6116
|
+
const busy = ctx.fallbackBusy || ctx.inFlight ? " disabled aria-busy=\"true\"" : "";
|
|
6117
|
+
const off = ctx.inFlight && !ctx.fallbackBusy ? " disabled" : "";
|
|
6118
|
+
if (typeof ctx.fallbackCandidate === "string" && ctx.fallbackCandidate) return "<button type=\"button\" data-act=\"row-fallback-confirm\" data-key=\"" + keyAttr + "\" data-primary=\"1\" title=\"" + escapeHtml$2(copyText("panel.action.install-fallback-confirm-title", ctx.lang)) + "\"" + busy + ">" + escapeHtml$2(copyText("panel.action.install-fallback-confirm", ctx.lang, { version: ctx.fallbackCandidate })) + "</button>";
|
|
6119
|
+
if (singleFallbackPhoneOf(row) === null) return "";
|
|
6120
|
+
if (!batchFallbackCauseOf(row)) return "";
|
|
6121
|
+
return "<button type=\"button\" data-act=\"row-fallback\" data-key=\"" + keyAttr + "\" data-primary=\"1\" title=\"" + escapeHtml$2(copyText("panel.action.install-fallback-title", ctx.lang)) + "\"" + (ctx.fallbackBusy ? busy : off) + ">" + escapeHtml$2(copyText("panel.action.install-fallback", ctx.lang)) + "</button>";
|
|
6122
|
+
} catch {
|
|
6123
|
+
return "";
|
|
6124
|
+
}
|
|
6125
|
+
}
|
|
5717
6126
|
function rowSetHTML(row, ctx) {
|
|
5718
6127
|
const phase = asBatchPhase(row.phase);
|
|
5719
6128
|
const keyAttr = escapeHtml$2(row.key);
|
|
5720
6129
|
const skipped = ctx.skipped;
|
|
5721
6130
|
const queued = isQueuedRow(row);
|
|
5722
6131
|
const position = queued ? queuePositionOf(row) : null;
|
|
6132
|
+
const rowDone = phase === "failed" && !queued ? compliantInstalledOf(row) : null;
|
|
5723
6133
|
const versionHTML = batchRowVersionHTML(row, ctx.knowledge, ctx.lang);
|
|
5724
|
-
const rowStatusText = queued ? batchQueuedStatus(position, ctx.lang) : ctx.worldLatest !== null ? batchText("batch.row.update", ctx.lang, { version: ctx.worldLatest }) : ctx.inRound ? batchRowKnowledgeText(row, ctx.knowledge, ctx.lang) ?? batchRowStatus(row, skipped, ctx.lang) : batchRowPendingStatus(row, ctx.knowledge, ctx.lang) ?? batchRowStatus(row, skipped, ctx.lang);
|
|
6134
|
+
const rowStatusText = rowDone !== null ? rowDone.needsRestart ? batchText("batch.row.done-restart", ctx.lang) : batchText("batch.row.done", ctx.lang) : queued ? batchQueuedStatus(position, ctx.lang) : ctx.worldLatest !== null ? batchText("batch.row.update", ctx.lang, { version: ctx.worldLatest }) : ctx.inRound ? batchRowKnowledgeText(row, ctx.knowledge, ctx.lang) ?? batchRowStatus(row, skipped, ctx.lang) : batchRowPendingStatus(row, ctx.knowledge, ctx.lang) ?? batchRowStatus(row, skipped, ctx.lang);
|
|
5725
6135
|
const actions = [];
|
|
5726
6136
|
const off = ctx.inFlight ? " disabled" : "";
|
|
5727
6137
|
if (phase === "installing") actions.push("<button type=\"button\" data-act=\"row-install\" data-key=\"" + keyAttr + "\" disabled>" + escapeHtml$2(batchText("batch.row-action.installing", ctx.lang)) + "</button>");
|
|
@@ -5729,10 +6139,19 @@ ${body}`;
|
|
|
5729
6139
|
if (cancelQueuePhoneOf(row) !== null && queuedRequestIdOf(row) !== null) actions.push("<button type=\"button\" data-act=\"row-cancel-queue\" data-key=\"" + keyAttr + "\"" + off + ">" + escapeHtml$2(batchText("batch.row-action.cancel-queue", ctx.lang)) + "</button>");
|
|
5730
6140
|
} else if (phase === "ready" && skipped === null) actions.push("<button type=\"button\" data-act=\"row-install\" data-key=\"" + keyAttr + "\" data-primary=\"1\"" + off + ">" + escapeHtml$2(ctx.busy ? batchText("batch.row-action.queue", ctx.lang) : batchText("batch.row-action.install-row", ctx.lang)) + "</button>");
|
|
5731
6141
|
else if (phase === "ready" && skipped !== null) actions.push("<button type=\"button\" data-act=\"row-resume-skip\" data-key=\"" + keyAttr + "\"" + off + ">" + escapeHtml$2(batchText("batch.row-action.unskip", ctx.lang, { version: skipped })) + "</button>");
|
|
5732
|
-
else if (phase === "failed")
|
|
6142
|
+
else if (phase === "failed") {
|
|
6143
|
+
actions.push("<button type=\"button\" data-act=\"row-install\" data-key=\"" + keyAttr + "\"" + off + ">" + escapeHtml$2(ctx.busy ? batchText("batch.row-action.queue", ctx.lang) : batchText("batch.row-action.retry", ctx.lang)) + "</button>");
|
|
6144
|
+
if (!queued && rowDone === null) actions.push(rowFallbackButtonHTML(row, ctx));
|
|
6145
|
+
}
|
|
5733
6146
|
if (row.restartRequired === true) actions.push("<button type=\"button\" data-act=\"restart\" data-key=\"" + keyAttr + "\">" + escapeHtml$2(batchText("batch.row-action.restart", ctx.lang)) + "</button>");
|
|
5734
6147
|
actions.push("<button type=\"button\" data-act=\"toggle-details\" data-key=\"" + keyAttr + "\">" + escapeHtml$2(ctx.expanded ? batchText("batch.row-action.hide-detail", ctx.lang) : batchText("batch.row-action.show-detail", ctx.lang)) + "</button>");
|
|
5735
|
-
const failLine = phase === "failed" && !queued ? (() => {
|
|
6148
|
+
const failLine = phase === "failed" && !queued ? rowDone !== null ? (() => {
|
|
6149
|
+
const vars = {
|
|
6150
|
+
version: rowDone.version,
|
|
6151
|
+
target: rowDone.target
|
|
6152
|
+
};
|
|
6153
|
+
return "<span class=\"dsh-upd-bfail dsh-upd-bdone\">" + escapeHtml$2(batchText("batch.row.compliant-done", ctx.lang, vars)) + "</span>";
|
|
6154
|
+
})() : (() => {
|
|
5736
6155
|
const failCode = row.error || "install-failed";
|
|
5737
6156
|
const failDetail = isCheckSideFailureCode(jobFailureOf(row)?.code ?? (typeof row.error === "string" && row.error ? row.error : null)) ? batchText("batch.row.failed", ctx.lang) : failureCopy(failCode, ctx.lang)?.zh ?? failureCopy("unknown", ctx.lang)?.zh ?? "";
|
|
5738
6157
|
const escaped = escapeHtml$2(batchText("batch.row.error-label", ctx.lang, {
|
|
@@ -5742,7 +6161,7 @@ ${body}`;
|
|
|
5742
6161
|
const codeEsc = escapeHtml$2(failCode);
|
|
5743
6162
|
return "<span class=\"dsh-upd-bfail\">" + (escaped.includes(codeEsc) ? escaped.replace(codeEsc, "<code>" + codeEsc + "</code>") : escaped) + "</span>";
|
|
5744
6163
|
})() : "";
|
|
5745
|
-
const main = "<button type=\"button\" class=\"dsh-upd-brow-main\" data-act=\"toggle-details\" data-key=\"" + keyAttr + "\" aria-expanded=\"" + (ctx.expanded ? "true" : "false") + "\"><span class=\"dsh-upd-updot\" data-tone=\"" + dotToneOf(row, phase, skipped, queued, ctx.worldLatest) + "\"></span><span class=\"dsh-upd-bname\">" + escapeHtml$2(titleOf(row, ctx.titles)) + "</span>" + versionHTML + "<span class=\"dsh-upd-bstat\">" + escapeHtml$2(rowStatusText) + (ctx.inRound && !queued ? "(" + escapeHtml$2(batchText("batch.row.unfinished-tag", ctx.lang)) + ")" : "") + "</span>" + failLine + "</button>";
|
|
6164
|
+
const main = "<button type=\"button\" class=\"dsh-upd-brow-main\" data-act=\"toggle-details\" data-key=\"" + keyAttr + "\" aria-expanded=\"" + (ctx.expanded ? "true" : "false") + "\"><span class=\"dsh-upd-updot\" data-tone=\"" + dotToneOf(row, phase, skipped, queued, ctx.worldLatest, rowDone === null ? null : rowDone.needsRestart) + "\"></span><span class=\"dsh-upd-bname\">" + escapeHtml$2(titleOf(row, ctx.titles)) + "</span>" + versionHTML + "<span class=\"dsh-upd-bstat\">" + escapeHtml$2(rowStatusText) + (ctx.inRound && !queued ? "(" + escapeHtml$2(batchText("batch.row.unfinished-tag", ctx.lang)) + ")" : "") + "</span>" + failLine + "</button>";
|
|
5746
6165
|
return "<div class=\"dsh-upd-brow-set\" data-key=\"" + keyAttr + "\"><div class=\"dsh-upd-brow\" data-phase=\"" + escapeHtml$2(phase) + "\" data-key=\"" + keyAttr + "\"" + (queued ? " data-queued=\"1\"" : "") + ">" + main + "<span class=\"dsh-upd-brow-actions\">" + actions.join("") + "</span></div></div>";
|
|
5747
6166
|
}
|
|
5748
6167
|
function detailActionsHTML(row, ctx) {
|
|
@@ -5755,8 +6174,13 @@ ${body}`;
|
|
|
5755
6174
|
if (phase === "installing") buttons.push("<button type=\"button\" data-act=\"row-install\" data-key=\"" + keyAttr + "\" disabled>" + escapeHtml$2(batchText("batch.row-action.installing", ctx.lang)) + "</button>");
|
|
5756
6175
|
else if (queued) {
|
|
5757
6176
|
if (cancelQueuePhoneOf(row) !== null && queuedRequestIdOf(row) !== null) buttons.push("<button type=\"button\" data-act=\"row-cancel-queue\" data-key=\"" + keyAttr + "\"" + off + ">" + escapeHtml$2(batchText("batch.row-action.cancel-queue", ctx.lang)) + "</button>");
|
|
5758
|
-
} else if (phase === "failed")
|
|
5759
|
-
|
|
6177
|
+
} else if (phase === "failed") {
|
|
6178
|
+
buttons.push("<button type=\"button\" data-act=\"row-install\" data-key=\"" + keyAttr + "\"" + off + ">" + escapeHtml$2(ctx.busy ? batchText("batch.row-action.queue", ctx.lang) : batchText("batch.row-action.retry", ctx.lang)) + "</button>");
|
|
6179
|
+
if (!queued) {
|
|
6180
|
+
const fallback = rowFallbackButtonHTML(row, ctx);
|
|
6181
|
+
if (fallback) buttons.push(fallback);
|
|
6182
|
+
}
|
|
6183
|
+
} else if (phase === "ready" && ctx.skipped === null) buttons.push("<button type=\"button\" data-act=\"row-install\" data-key=\"" + keyAttr + "\" data-primary=\"1\"" + off + ">" + escapeHtml$2(ctx.busy ? batchText("batch.row-action.queue", ctx.lang) : version !== null ? batchText("batch.row-action.install-version", ctx.lang, { version }) : batchText("batch.row-action.install-generic", ctx.lang)) + "</button>");
|
|
5760
6184
|
if (phase !== "installing" && singleCheckPhoneOf(row) !== null) buttons.push("<button type=\"button\" data-act=\"row-check\" data-key=\"" + keyAttr + "\"" + off + ">" + escapeHtml$2(batchText("batch.action.check", ctx.lang)) + "</button>");
|
|
5761
6185
|
if (!queued && phase === "ready" && ctx.skipped === null && version !== null) buttons.push("<button type=\"button\" data-act=\"row-skip\" data-key=\"" + keyAttr + "\"" + off + ">" + escapeHtml$2(batchText("batch.row-action.skip", ctx.lang)) + "</button>");
|
|
5762
6186
|
if (ctx.skipped !== null) buttons.push("<button type=\"button\" data-act=\"row-resume-skip\" data-key=\"" + keyAttr + "\"" + off + ">" + escapeHtml$2(batchText("batch.row-action.unskip", ctx.lang, { version: ctx.skipped })) + "</button>");
|
|
@@ -5798,7 +6222,9 @@ ${body}`;
|
|
|
5798
6222
|
if (at < 0) return withBar + footer;
|
|
5799
6223
|
return withBar.slice(0, at) + footer + withBar.slice(at);
|
|
5800
6224
|
}
|
|
5801
|
-
function dotToneOf(row, phase, skipped, queued, worldLatest = null) {
|
|
6225
|
+
function dotToneOf(row, phase, skipped, queued, worldLatest = null, compliantRestart = null) {
|
|
6226
|
+
if (compliantRestart === true) return "warn";
|
|
6227
|
+
if (compliantRestart === false) return "ok";
|
|
5802
6228
|
if (phase === "failed" && !queued) return "bad";
|
|
5803
6229
|
if (phase === "installing" || phase === "checking") return "busy";
|
|
5804
6230
|
if (queued) return "warn";
|
|
@@ -5838,6 +6264,8 @@ ${body}`;
|
|
|
5838
6264
|
".dsh-upd-bver-new-ok{color:var(--dsh-update-new-ok-text,#047857);font-weight:700}",
|
|
5839
6265
|
".dsh-upd-bstat{font-size:var(--dsh-update-panel-small-font-size,12.5px);opacity:.9;min-width:0;overflow-wrap:anywhere}",
|
|
5840
6266
|
".dsh-upd-bfail{grid-column:1/-1;display:block;font-size:var(--dsh-update-panel-small-font-size,12.5px);color:var(--dsh-update-bad-border,#dc2626)}",
|
|
6267
|
+
"/* #156 finishing fact: ledger phase failed but the newest installable build did get installed — green, not red. */",
|
|
6268
|
+
".dsh-upd-bdone{color:var(--dsh-update-ok-border,#059669)}",
|
|
5841
6269
|
".dsh-upd-batch{--dsh-update-new-text:#dc2626}",
|
|
5842
6270
|
".dsh-upd-batch{--dsh-update-new-ok-text:#047857}",
|
|
5843
6271
|
"@media (prefers-color-scheme: dark){.dsh-upd-batch{--dsh-update-new-text:#f87171}}",
|
|
@@ -5950,6 +6378,78 @@ ${body}`;
|
|
|
5950
6378
|
const install = phones["updateInstall"];
|
|
5951
6379
|
return typeof install === "string" && install ? install : null;
|
|
5952
6380
|
}
|
|
6381
|
+
function singleFallbackPhoneOf(row) {
|
|
6382
|
+
const phones = isObject$2(row.phoneNames) ? row.phoneNames : null;
|
|
6383
|
+
if (!phones) return null;
|
|
6384
|
+
const name = phones["updateCheckFallback"];
|
|
6385
|
+
return typeof name === "string" && name ? name : null;
|
|
6386
|
+
}
|
|
6387
|
+
function singleInstallPhoneOf(row) {
|
|
6388
|
+
const phones = isObject$2(row.phoneNames) ? row.phoneNames : null;
|
|
6389
|
+
if (!phones) return null;
|
|
6390
|
+
const name = phones["updateInstall"];
|
|
6391
|
+
return typeof name === "string" && name ? name : null;
|
|
6392
|
+
}
|
|
6393
|
+
function fallbackOutcomeOf(reply) {
|
|
6394
|
+
if (!isObject$2(reply) || reply["ok"] === false) return {
|
|
6395
|
+
kind: "",
|
|
6396
|
+
candidate: "",
|
|
6397
|
+
checkId: "",
|
|
6398
|
+
unlockAtMs: null
|
|
6399
|
+
};
|
|
6400
|
+
const snap = isObject$2(reply["snapshot"]) ? reply["snapshot"] : null;
|
|
6401
|
+
const verdict = snap && isObject$2(snap["verdict"]) ? snap["verdict"] : null;
|
|
6402
|
+
const kind = verdict && typeof verdict["kind"] === "string" ? verdict["kind"] : "";
|
|
6403
|
+
const version = verdict && typeof verdict["version"] === "string" ? verdict["version"].trim() : "";
|
|
6404
|
+
const snapCandidate = snap && typeof snap["candidate"] === "string" ? snap["candidate"].trim() : "";
|
|
6405
|
+
const rec = isObject$2(reply["receipt"]) ? reply["receipt"] : null;
|
|
6406
|
+
const checkId = rec && typeof rec["checkId"] === "string" ? rec["checkId"] : "";
|
|
6407
|
+
const unlockAtMs = verdict && typeof verdict["unlockAtMs"] === "number" ? verdict["unlockAtMs"] : null;
|
|
6408
|
+
const candidate = snapCandidate || (kind === "ok-now" ? version : "");
|
|
6409
|
+
const usable = (kind === "downgrade-available" || kind === "ok-now") && candidate !== "" && checkId !== "";
|
|
6410
|
+
return {
|
|
6411
|
+
kind,
|
|
6412
|
+
candidate: usable ? candidate : "",
|
|
6413
|
+
checkId: usable ? checkId : "",
|
|
6414
|
+
unlockAtMs
|
|
6415
|
+
};
|
|
6416
|
+
}
|
|
6417
|
+
function batchFallbackCauseOf(row) {
|
|
6418
|
+
try {
|
|
6419
|
+
if (asBatchPhase(row.phase) !== "failed") return null;
|
|
6420
|
+
const fail = jobFailureOf(row);
|
|
6421
|
+
if (!fail) return null;
|
|
6422
|
+
const rowDiag = row.diag;
|
|
6423
|
+
const cause = fallbackCauseFromDiag(rowDiag, fail.detail, fail.code, latestVersionOf(row)) ?? fallbackCauseFromDetail(fail.detail, fail.code, pluginIdOf(row));
|
|
6424
|
+
if (!cause) return null;
|
|
6425
|
+
if (cause.targetVersion !== latestVersionOf(row)) return null;
|
|
6426
|
+
return cause;
|
|
6427
|
+
} catch {
|
|
6428
|
+
return null;
|
|
6429
|
+
}
|
|
6430
|
+
}
|
|
6431
|
+
function compliantInstalledOf(row) {
|
|
6432
|
+
try {
|
|
6433
|
+
if (!isObject$2(row.snapshot)) return null;
|
|
6434
|
+
const snapshot = row.snapshot;
|
|
6435
|
+
if (!isObject$2(snapshot["job"])) return null;
|
|
6436
|
+
const job = snapshot["job"];
|
|
6437
|
+
const state = typeof job["state"] === "string" ? job["state"] : "";
|
|
6438
|
+
if (state !== "restart-required" && state !== "completed") return null;
|
|
6439
|
+
const version = typeof job["targetVersion"] === "string" ? job["targetVersion"].trim() : "";
|
|
6440
|
+
if (!version) return null;
|
|
6441
|
+
if ((typeof snapshot["installedVersion"] === "string" ? snapshot["installedVersion"].trim() : "") !== version) return null;
|
|
6442
|
+
const target = latestVersionOf(row);
|
|
6443
|
+
if (!target || target === version) return null;
|
|
6444
|
+
return {
|
|
6445
|
+
version,
|
|
6446
|
+
target,
|
|
6447
|
+
needsRestart: state === "restart-required"
|
|
6448
|
+
};
|
|
6449
|
+
} catch {
|
|
6450
|
+
return null;
|
|
6451
|
+
}
|
|
6452
|
+
}
|
|
5953
6453
|
function asBatchPhase(value) {
|
|
5954
6454
|
return typeof value === "string" && BATCH_PHASES.includes(value) ? value : "pending";
|
|
5955
6455
|
}
|
|
@@ -6142,9 +6642,10 @@ ${body}`;
|
|
|
6142
6642
|
const titles = options.titles && typeof options.titles === "object" ? options.titles : {};
|
|
6143
6643
|
const onRestartRequested = options.onRestartRequested;
|
|
6144
6644
|
const onCloseRequested = typeof options.onCloseRequested === "function" ? options.onCloseRequested : null;
|
|
6145
|
-
const copyText = options.copyText ?? defaultCopyText$1;
|
|
6645
|
+
const copyText$1 = options.copyText ?? defaultCopyText$1;
|
|
6146
6646
|
const skipStores = /* @__PURE__ */ new Map();
|
|
6147
6647
|
const autoChangelogEnabled = options.autoChangelog !== false;
|
|
6648
|
+
const autoPlanEnabled = options.autoCompliant !== false;
|
|
6148
6649
|
const rowChangelog = /* @__PURE__ */ new Map();
|
|
6149
6650
|
const rowInflight = /* @__PURE__ */ new Set();
|
|
6150
6651
|
const rowFailedAt = /* @__PURE__ */ new Map();
|
|
@@ -6172,6 +6673,9 @@ ${body}`;
|
|
|
6172
6673
|
let lastCheckedAt = 0;
|
|
6173
6674
|
let autoCheckDone = false;
|
|
6174
6675
|
let autoResumeDone = false;
|
|
6676
|
+
const rowFallbackOffers = /* @__PURE__ */ new Map();
|
|
6677
|
+
let fallbackBusyKey = null;
|
|
6678
|
+
let batchCompliantKeys = [];
|
|
6175
6679
|
function changelogView() {
|
|
6176
6680
|
const out = {};
|
|
6177
6681
|
for (const row of rows) {
|
|
@@ -6313,6 +6817,13 @@ ${body}`;
|
|
|
6313
6817
|
let lastHTML = "";
|
|
6314
6818
|
function render() {
|
|
6315
6819
|
if (!mounted) return;
|
|
6820
|
+
const offers = {};
|
|
6821
|
+
for (const [k, v] of rowFallbackOffers) offers[k] = {
|
|
6822
|
+
candidate: v.candidate,
|
|
6823
|
+
targetVersion: v.targetVersion
|
|
6824
|
+
};
|
|
6825
|
+
const confirmKeys = batchCompliantKeys.filter((k) => rowFallbackOffers.has(k));
|
|
6826
|
+
const wait = waitingOf();
|
|
6316
6827
|
const nextHTML = renderBatchPanelHTML({
|
|
6317
6828
|
rows,
|
|
6318
6829
|
theme,
|
|
@@ -6331,13 +6842,163 @@ ${body}`;
|
|
|
6331
6842
|
session: lastSession,
|
|
6332
6843
|
inventory: lastInventory,
|
|
6333
6844
|
prefs: lastPrefs,
|
|
6334
|
-
lang: currentLang()
|
|
6845
|
+
lang: currentLang(),
|
|
6846
|
+
fallbackOffers: offers,
|
|
6847
|
+
fallbackBusyKey,
|
|
6848
|
+
compliant: {
|
|
6849
|
+
gated: rows.filter((row) => needsAutoResolve(row)).length,
|
|
6850
|
+
confirmList: confirmKeys.length > 0 ? compliantListText(confirmKeys) : null,
|
|
6851
|
+
confirmCount: confirmKeys.length,
|
|
6852
|
+
busy: inFlight,
|
|
6853
|
+
wait: wait.keys.length > 0 ? wait : null,
|
|
6854
|
+
unlocks: unlockTimesOf()
|
|
6855
|
+
}
|
|
6335
6856
|
});
|
|
6336
6857
|
if (nextHTML !== lastHTML) {
|
|
6337
6858
|
lastHTML = nextHTML;
|
|
6338
6859
|
setStableHTML(container, nextHTML);
|
|
6339
6860
|
}
|
|
6340
6861
|
}
|
|
6862
|
+
function pruneFallbackOffers() {
|
|
6863
|
+
try {
|
|
6864
|
+
for (const [k, v] of [...rowFallbackOffers]) {
|
|
6865
|
+
const row = rowOfKey(k);
|
|
6866
|
+
if (!row || asBatchPhase(row.phase) !== "failed" || v.targetVersion !== latestVersionOf(row)) rowFallbackOffers.delete(k);
|
|
6867
|
+
}
|
|
6868
|
+
if (batchCompliantKeys.length > 0) batchCompliantKeys = batchCompliantKeys.filter((k) => rowFallbackOffers.has(k));
|
|
6869
|
+
} catch {}
|
|
6870
|
+
}
|
|
6871
|
+
function compliantListText(keys) {
|
|
6872
|
+
const sep = currentLang() === "en" ? ", " : "、";
|
|
6873
|
+
return keys.map((k) => {
|
|
6874
|
+
const row = rowOfKey(k);
|
|
6875
|
+
const offer = rowFallbackOffers.get(k);
|
|
6876
|
+
return row && offer ? titleOf(row, titles) + " " + offer.candidate : "";
|
|
6877
|
+
}).filter((text) => text !== "").join(sep);
|
|
6878
|
+
}
|
|
6879
|
+
const gatedOutcomes = /* @__PURE__ */ new Map();
|
|
6880
|
+
let autoPlanSignature = "";
|
|
6881
|
+
let autoPlanRunning = false;
|
|
6882
|
+
function needsAutoResolve(row) {
|
|
6883
|
+
try {
|
|
6884
|
+
if (batchFallbackCauseOf(row) === null || singleFallbackPhoneOf(row) === null) return false;
|
|
6885
|
+
if (compliantInstalledOf(row) !== null) return false;
|
|
6886
|
+
if (rowFallbackOffers.has(row.key)) return false;
|
|
6887
|
+
const seen = gatedOutcomes.get(row.key);
|
|
6888
|
+
if (seen) {
|
|
6889
|
+
if (seen.kind === "installed") return false;
|
|
6890
|
+
if (seen.kind === "wait-until") {
|
|
6891
|
+
if (seen.unlockAtMs === null) return false;
|
|
6892
|
+
if (nowMs() < seen.unlockAtMs) return false;
|
|
6893
|
+
}
|
|
6894
|
+
}
|
|
6895
|
+
return true;
|
|
6896
|
+
} catch {
|
|
6897
|
+
return false;
|
|
6898
|
+
}
|
|
6899
|
+
}
|
|
6900
|
+
async function resolveGated(row) {
|
|
6901
|
+
const cause = batchFallbackCauseOf(row);
|
|
6902
|
+
const phoneName = singleFallbackPhoneOf(row);
|
|
6903
|
+
if (!cause || phoneName === null) return {
|
|
6904
|
+
kind: "",
|
|
6905
|
+
candidate: "",
|
|
6906
|
+
checkId: "",
|
|
6907
|
+
unlockAtMs: null
|
|
6908
|
+
};
|
|
6909
|
+
let reply = null;
|
|
6910
|
+
try {
|
|
6911
|
+
reply = await call(phoneName, {
|
|
6912
|
+
kind: cause.kind,
|
|
6913
|
+
blame: "target",
|
|
6914
|
+
targetVersion: cause.targetVersion,
|
|
6915
|
+
...typeof cause.windowMs === "number" ? { windowMs: cause.windowMs } : {},
|
|
6916
|
+
windowSource: cause.windowSource,
|
|
6917
|
+
...typeof cause.publishedAtMs === "number" ? { publishedAtMs: cause.publishedAtMs } : {}
|
|
6918
|
+
});
|
|
6919
|
+
} catch {
|
|
6920
|
+
reply = null;
|
|
6921
|
+
}
|
|
6922
|
+
const outcome = fallbackOutcomeOf(reply);
|
|
6923
|
+
gatedOutcomes.set(row.key, {
|
|
6924
|
+
kind: outcome.kind,
|
|
6925
|
+
unlockAtMs: outcome.unlockAtMs
|
|
6926
|
+
});
|
|
6927
|
+
if (outcome.candidate) rowFallbackOffers.set(row.key, {
|
|
6928
|
+
candidate: outcome.candidate,
|
|
6929
|
+
checkId: outcome.checkId,
|
|
6930
|
+
targetVersion: cause.targetVersion
|
|
6931
|
+
});
|
|
6932
|
+
return outcome;
|
|
6933
|
+
}
|
|
6934
|
+
function maybeAutoPlanCompliant() {
|
|
6935
|
+
if (!autoPlanEnabled || !mounted || inFlight || autoPlanRunning) return;
|
|
6936
|
+
let signature = "";
|
|
6937
|
+
const targets = [];
|
|
6938
|
+
try {
|
|
6939
|
+
for (const row of rows) {
|
|
6940
|
+
if (!needsAutoResolve(row)) continue;
|
|
6941
|
+
targets.push(row);
|
|
6942
|
+
signature += row.key + "@" + (latestVersionOf(row) ?? "") + ";";
|
|
6943
|
+
}
|
|
6944
|
+
} catch {
|
|
6945
|
+
return;
|
|
6946
|
+
}
|
|
6947
|
+
if (targets.length === 0 || signature === autoPlanSignature) return;
|
|
6948
|
+
autoPlanSignature = signature;
|
|
6949
|
+
autoPlanRunning = true;
|
|
6950
|
+
inFlight = true;
|
|
6951
|
+
render();
|
|
6952
|
+
(async () => {
|
|
6953
|
+
try {
|
|
6954
|
+
for (const row of targets) {
|
|
6955
|
+
if (!mounted) return;
|
|
6956
|
+
if (!needsAutoResolve(row)) continue;
|
|
6957
|
+
await resolveGated(row);
|
|
6958
|
+
}
|
|
6959
|
+
} finally {
|
|
6960
|
+
autoPlanRunning = false;
|
|
6961
|
+
inFlight = false;
|
|
6962
|
+
}
|
|
6963
|
+
if (!mounted) return;
|
|
6964
|
+
const merged = [...batchCompliantKeys];
|
|
6965
|
+
for (const row of targets) if (rowFallbackOffers.has(row.key) && !merged.includes(row.key)) merged.push(row.key);
|
|
6966
|
+
batchCompliantKeys = merged.filter((k) => rowFallbackOffers.has(k));
|
|
6967
|
+
if (batchCompliantKeys.length > 0) clearNotice();
|
|
6968
|
+
render();
|
|
6969
|
+
maybeAutoRowChangelog(expandedKey);
|
|
6970
|
+
})();
|
|
6971
|
+
}
|
|
6972
|
+
function waitingOf() {
|
|
6973
|
+
const keys = [];
|
|
6974
|
+
let earliest = null;
|
|
6975
|
+
try {
|
|
6976
|
+
for (const row of rows) {
|
|
6977
|
+
const seen = gatedOutcomes.get(row.key);
|
|
6978
|
+
if (!seen || seen.kind !== "wait-until") continue;
|
|
6979
|
+
if (compliantInstalledOf(row) !== null) continue;
|
|
6980
|
+
if (batchFallbackCauseOf(row) === null || singleFallbackPhoneOf(row) === null) continue;
|
|
6981
|
+
keys.push(row.key);
|
|
6982
|
+
if (typeof seen.unlockAtMs === "number" && (earliest === null || seen.unlockAtMs < earliest)) earliest = seen.unlockAtMs;
|
|
6983
|
+
}
|
|
6984
|
+
} catch {
|
|
6985
|
+
return {
|
|
6986
|
+
keys: [],
|
|
6987
|
+
unlockAtMs: null
|
|
6988
|
+
};
|
|
6989
|
+
}
|
|
6990
|
+
return {
|
|
6991
|
+
keys,
|
|
6992
|
+
unlockAtMs: earliest
|
|
6993
|
+
};
|
|
6994
|
+
}
|
|
6995
|
+
function unlockTimesOf() {
|
|
6996
|
+
const out = {};
|
|
6997
|
+
try {
|
|
6998
|
+
for (const [k, v] of gatedOutcomes) out[k] = v.unlockAtMs;
|
|
6999
|
+
} catch {}
|
|
7000
|
+
return out;
|
|
7001
|
+
}
|
|
6341
7002
|
function rowOfKey(key) {
|
|
6342
7003
|
return rows.find((row) => row.key === key) ?? null;
|
|
6343
7004
|
}
|
|
@@ -6374,7 +7035,7 @@ ${body}`;
|
|
|
6374
7035
|
}
|
|
6375
7036
|
async function copyWith(text, okNotice, key) {
|
|
6376
7037
|
try {
|
|
6377
|
-
await copyText(text);
|
|
7038
|
+
await copyText$1(text);
|
|
6378
7039
|
say(okNotice, key);
|
|
6379
7040
|
} catch {
|
|
6380
7041
|
say(batchText("batch.toast.copy-fail", currentLang()), key);
|
|
@@ -6413,6 +7074,7 @@ ${body}`;
|
|
|
6413
7074
|
loaded = true;
|
|
6414
7075
|
lastError = null;
|
|
6415
7076
|
if (expandedKey !== null && !rows.some((row) => row.key === expandedKey)) expandedKey = null;
|
|
7077
|
+
pruneFallbackOffers();
|
|
6416
7078
|
return;
|
|
6417
7079
|
}
|
|
6418
7080
|
const err = typeof reply["error"] === "string" ? reply["error"].trim() : "";
|
|
@@ -6433,6 +7095,7 @@ ${body}`;
|
|
|
6433
7095
|
}
|
|
6434
7096
|
render();
|
|
6435
7097
|
maybeAutoRowChangelog(expandedKey);
|
|
7098
|
+
maybeAutoPlanCompliant();
|
|
6436
7099
|
}
|
|
6437
7100
|
async function phone(name, args, busyRowKey = null) {
|
|
6438
7101
|
if (!mounted || inFlight) return null;
|
|
@@ -6461,6 +7124,7 @@ ${body}`;
|
|
|
6461
7124
|
if (mounted) render();
|
|
6462
7125
|
}
|
|
6463
7126
|
maybeAutoRowChangelog(expandedKey);
|
|
7127
|
+
maybeAutoPlanCompliant();
|
|
6464
7128
|
return out;
|
|
6465
7129
|
}
|
|
6466
7130
|
function remainingCount() {
|
|
@@ -6635,6 +7299,212 @@ ${body}`;
|
|
|
6635
7299
|
await copyWith(diagTextOf(row, currentLang()), batchText("batch.toast.copy-diag-ok", currentLang()), row.key);
|
|
6636
7300
|
return;
|
|
6637
7301
|
}
|
|
7302
|
+
case "row-fallback": {
|
|
7303
|
+
const row = typeof key === "string" && key ? rowOfKey(key) : null;
|
|
7304
|
+
if (!row) return;
|
|
7305
|
+
const cause = batchFallbackCauseOf(row);
|
|
7306
|
+
const phoneName = singleFallbackPhoneOf(row);
|
|
7307
|
+
if (!cause || phoneName === null) {
|
|
7308
|
+
say(copyText("panel.toast.fallback-unavailable", currentLang()), row.key);
|
|
7309
|
+
render();
|
|
7310
|
+
return;
|
|
7311
|
+
}
|
|
7312
|
+
if (inFlight) return;
|
|
7313
|
+
inFlight = true;
|
|
7314
|
+
fallbackBusyKey = row.key;
|
|
7315
|
+
clearNotice();
|
|
7316
|
+
render();
|
|
7317
|
+
try {
|
|
7318
|
+
let reply;
|
|
7319
|
+
try {
|
|
7320
|
+
reply = await call(phoneName, {
|
|
7321
|
+
kind: cause.kind,
|
|
7322
|
+
blame: "target",
|
|
7323
|
+
targetVersion: cause.targetVersion,
|
|
7324
|
+
...typeof cause.windowMs === "number" ? { windowMs: cause.windowMs } : {},
|
|
7325
|
+
windowSource: cause.windowSource,
|
|
7326
|
+
...typeof cause.publishedAtMs === "number" ? { publishedAtMs: cause.publishedAtMs } : {}
|
|
7327
|
+
});
|
|
7328
|
+
} catch {
|
|
7329
|
+
reply = null;
|
|
7330
|
+
}
|
|
7331
|
+
if (!mounted) return;
|
|
7332
|
+
if (!isObject$2(reply) || reply["ok"] === false) {
|
|
7333
|
+
say(copyText("panel.toast.fallback-unavailable", currentLang()), row.key);
|
|
7334
|
+
render();
|
|
7335
|
+
return;
|
|
7336
|
+
}
|
|
7337
|
+
const outcome = fallbackOutcomeOf(reply);
|
|
7338
|
+
if (outcome.candidate) {
|
|
7339
|
+
rowFallbackOffers.set(row.key, {
|
|
7340
|
+
candidate: outcome.candidate,
|
|
7341
|
+
checkId: outcome.checkId,
|
|
7342
|
+
targetVersion: cause.targetVersion
|
|
7343
|
+
});
|
|
7344
|
+
clearNotice();
|
|
7345
|
+
} else if (outcome.kind === "wait-until") {
|
|
7346
|
+
const time = typeof outcome.unlockAtMs === "number" ? formatUnlockAt(outcome.unlockAtMs, currentLang()) ?? null : null;
|
|
7347
|
+
say(time ? copyText("panel.toast.fallback-wait", currentLang(), { time }) : copyText("panel.toast.fallback-unavailable", currentLang()), row.key);
|
|
7348
|
+
} else say(copyText("panel.toast.fallback-unavailable", currentLang()), row.key);
|
|
7349
|
+
} finally {
|
|
7350
|
+
inFlight = false;
|
|
7351
|
+
fallbackBusyKey = null;
|
|
7352
|
+
}
|
|
7353
|
+
render();
|
|
7354
|
+
return;
|
|
7355
|
+
}
|
|
7356
|
+
case "batch-fallback-scan": {
|
|
7357
|
+
const targets = rows.filter((row) => batchFallbackCauseOf(row) !== null && singleFallbackPhoneOf(row) !== null);
|
|
7358
|
+
if (targets.length === 0) {
|
|
7359
|
+
say(copyText("panel.toast.fallback-unavailable", currentLang()));
|
|
7360
|
+
render();
|
|
7361
|
+
return;
|
|
7362
|
+
}
|
|
7363
|
+
if (inFlight) return;
|
|
7364
|
+
inFlight = true;
|
|
7365
|
+
clearNotice();
|
|
7366
|
+
render();
|
|
7367
|
+
const got = [];
|
|
7368
|
+
let waitTime = null;
|
|
7369
|
+
try {
|
|
7370
|
+
for (const row of targets) {
|
|
7371
|
+
if (!batchFallbackCauseOf(row) || singleFallbackPhoneOf(row) === null) continue;
|
|
7372
|
+
const outcome = await resolveGated(row);
|
|
7373
|
+
if (!mounted) return;
|
|
7374
|
+
if (outcome.candidate) got.push(row.key);
|
|
7375
|
+
else if (outcome.kind === "wait-until" && waitTime === null) waitTime = typeof outcome.unlockAtMs === "number" ? formatUnlockAt(outcome.unlockAtMs, currentLang()) ?? null : null;
|
|
7376
|
+
}
|
|
7377
|
+
} finally {
|
|
7378
|
+
inFlight = false;
|
|
7379
|
+
}
|
|
7380
|
+
if (got.length > 0) {
|
|
7381
|
+
const merged = [...batchCompliantKeys];
|
|
7382
|
+
for (const k of got) if (!merged.includes(k)) merged.push(k);
|
|
7383
|
+
batchCompliantKeys = merged.filter((k) => rowFallbackOffers.has(k));
|
|
7384
|
+
clearNotice();
|
|
7385
|
+
} else if (waitTime) say(copyText("panel.toast.fallback-wait", currentLang(), { time: waitTime }));
|
|
7386
|
+
else say(copyText("panel.toast.fallback-unavailable", currentLang()));
|
|
7387
|
+
render();
|
|
7388
|
+
return;
|
|
7389
|
+
}
|
|
7390
|
+
case "batch-fallback-confirm": {
|
|
7391
|
+
const keys = batchCompliantKeys.filter((k) => rowFallbackOffers.has(k));
|
|
7392
|
+
if (keys.length === 0) {
|
|
7393
|
+
batchCompliantKeys = [];
|
|
7394
|
+
say(copyText("panel.toast.fallback-unavailable", currentLang()));
|
|
7395
|
+
render();
|
|
7396
|
+
return;
|
|
7397
|
+
}
|
|
7398
|
+
if (inFlight) return;
|
|
7399
|
+
inFlight = true;
|
|
7400
|
+
clearNotice();
|
|
7401
|
+
render();
|
|
7402
|
+
let done = 0;
|
|
7403
|
+
let bad = 0;
|
|
7404
|
+
let busyCount = 0;
|
|
7405
|
+
try {
|
|
7406
|
+
for (const k of keys) {
|
|
7407
|
+
const row = rowOfKey(k);
|
|
7408
|
+
const offer = rowFallbackOffers.get(k) ?? null;
|
|
7409
|
+
const phoneName = row ? singleInstallPhoneOf(row) : null;
|
|
7410
|
+
if (!row || !offer || phoneName === null || offer.targetVersion !== latestVersionOf(row)) {
|
|
7411
|
+
rowFallbackOffers.delete(k);
|
|
7412
|
+
bad++;
|
|
7413
|
+
continue;
|
|
7414
|
+
}
|
|
7415
|
+
const freshRequestId = `r${Date.now().toString(36)}${Math.floor(Math.random() * 16777215).toString(36)}`.slice(0, 64);
|
|
7416
|
+
let reply = null;
|
|
7417
|
+
try {
|
|
7418
|
+
reply = await call(phoneName, {
|
|
7419
|
+
checkId: offer.checkId,
|
|
7420
|
+
requestId: freshRequestId,
|
|
7421
|
+
version: offer.candidate,
|
|
7422
|
+
from: "batch",
|
|
7423
|
+
includeEnv: true,
|
|
7424
|
+
includeQueue: true
|
|
7425
|
+
});
|
|
7426
|
+
} catch {
|
|
7427
|
+
reply = null;
|
|
7428
|
+
}
|
|
7429
|
+
const busy = isObject$2(reply) && reply["ok"] === false && (reply["error"] === "update-busy" || reply["errorKind"] === "update-busy");
|
|
7430
|
+
if (!busy) rowFallbackOffers.delete(k);
|
|
7431
|
+
if (!mounted) return;
|
|
7432
|
+
if (isObject$2(reply) && reply["ok"] !== false) {
|
|
7433
|
+
done++;
|
|
7434
|
+
const prev = gatedOutcomes.get(k);
|
|
7435
|
+
gatedOutcomes.set(k, {
|
|
7436
|
+
kind: "installed",
|
|
7437
|
+
unlockAtMs: prev ? prev.unlockAtMs : null
|
|
7438
|
+
});
|
|
7439
|
+
} else if (busy) busyCount++;
|
|
7440
|
+
else bad++;
|
|
7441
|
+
}
|
|
7442
|
+
} finally {
|
|
7443
|
+
inFlight = false;
|
|
7444
|
+
}
|
|
7445
|
+
batchCompliantKeys = keys.filter((k) => rowFallbackOffers.has(k));
|
|
7446
|
+
pruneFallbackOffers();
|
|
7447
|
+
await refresh();
|
|
7448
|
+
const parts = [];
|
|
7449
|
+
if (done > 0 || bad > 0) parts.push(batchText("batch.toast.compliant-installed", currentLang(), {
|
|
7450
|
+
a: String(done),
|
|
7451
|
+
b: String(bad)
|
|
7452
|
+
}));
|
|
7453
|
+
if (busyCount > 0) parts.push(copyText("batch.toast.queue-missed", currentLang()));
|
|
7454
|
+
if (parts.length > 0) say(parts.join(" "));
|
|
7455
|
+
render();
|
|
7456
|
+
return;
|
|
7457
|
+
}
|
|
7458
|
+
case "row-fallback-confirm": {
|
|
7459
|
+
const row = typeof key === "string" && key ? rowOfKey(key) : null;
|
|
7460
|
+
if (!row) return;
|
|
7461
|
+
const offer = rowFallbackOffers.get(row.key) ?? null;
|
|
7462
|
+
const phoneName = singleInstallPhoneOf(row);
|
|
7463
|
+
if (!offer || phoneName === null || offer.targetVersion !== latestVersionOf(row)) {
|
|
7464
|
+
rowFallbackOffers.delete(row.key);
|
|
7465
|
+
say(copyText("panel.toast.fallback-unavailable", currentLang()), row.key);
|
|
7466
|
+
render();
|
|
7467
|
+
return;
|
|
7468
|
+
}
|
|
7469
|
+
if (inFlight) return;
|
|
7470
|
+
inFlight = true;
|
|
7471
|
+
clearNotice();
|
|
7472
|
+
render();
|
|
7473
|
+
try {
|
|
7474
|
+
const freshRequestId = `r${Date.now().toString(36)}${Math.floor(Math.random() * 16777215).toString(36)}`.slice(0, 64);
|
|
7475
|
+
let reply;
|
|
7476
|
+
try {
|
|
7477
|
+
reply = await call(phoneName, {
|
|
7478
|
+
checkId: offer.checkId,
|
|
7479
|
+
requestId: freshRequestId,
|
|
7480
|
+
version: offer.candidate,
|
|
7481
|
+
from: "batch",
|
|
7482
|
+
includeEnv: true,
|
|
7483
|
+
includeQueue: true
|
|
7484
|
+
});
|
|
7485
|
+
} catch {
|
|
7486
|
+
reply = null;
|
|
7487
|
+
}
|
|
7488
|
+
if (!mounted) return;
|
|
7489
|
+
if (isObject$2(reply) && reply["ok"] === false && (reply["error"] === "update-busy" || reply["errorKind"] === "update-busy")) say(copyText("batch.toast.queue-missed", currentLang()), row.key);
|
|
7490
|
+
else {
|
|
7491
|
+
rowFallbackOffers.delete(row.key);
|
|
7492
|
+
if (!isObject$2(reply) || reply["ok"] === false) say(copyText("panel.toast.fallback-unavailable", currentLang()), row.key);
|
|
7493
|
+
else {
|
|
7494
|
+
const prev = gatedOutcomes.get(row.key);
|
|
7495
|
+
gatedOutcomes.set(row.key, {
|
|
7496
|
+
kind: "installed",
|
|
7497
|
+
unlockAtMs: prev ? prev.unlockAtMs : null
|
|
7498
|
+
});
|
|
7499
|
+
}
|
|
7500
|
+
}
|
|
7501
|
+
} finally {
|
|
7502
|
+
inFlight = false;
|
|
7503
|
+
}
|
|
7504
|
+
pruneFallbackOffers();
|
|
7505
|
+
await refresh();
|
|
7506
|
+
return;
|
|
7507
|
+
}
|
|
6638
7508
|
case "toggle-details":
|
|
6639
7509
|
if (typeof key !== "string" || !key) return;
|
|
6640
7510
|
expandedKey = expandedKey === key ? null : key;
|
|
@@ -6814,7 +7684,7 @@ ${body}`;
|
|
|
6814
7684
|
};
|
|
6815
7685
|
}
|
|
6816
7686
|
//#endregion
|
|
6817
|
-
//#region ../../node_modules/.pnpm/dsh-plugin-update@0.18.
|
|
7687
|
+
//#region ../../node_modules/.pnpm/dsh-plugin-update@0.18.7/node_modules/dsh-plugin-update/dist/entry-batch.js
|
|
6818
7688
|
function isObject$1(value) {
|
|
6819
7689
|
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
6820
7690
|
}
|
|
@@ -6825,11 +7695,20 @@ ${body}`;
|
|
|
6825
7695
|
function escapeHtml$1(value) {
|
|
6826
7696
|
return String(value).replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """);
|
|
6827
7697
|
}
|
|
7698
|
+
function compliantEntryDone(rows) {
|
|
7699
|
+
const done = /* @__PURE__ */ new Map();
|
|
7700
|
+
if (!Array.isArray(rows)) return done;
|
|
7701
|
+
for (const row of rows) try {
|
|
7702
|
+
const fact = compliantInstalledOf(row);
|
|
7703
|
+
if (fact) done.set(row.key, fact.needsRestart);
|
|
7704
|
+
} catch {}
|
|
7705
|
+
return done;
|
|
7706
|
+
}
|
|
6828
7707
|
function batchEntrySummary(state, lang) {
|
|
6829
7708
|
const rows = state?.rows ?? null;
|
|
6830
7709
|
const inventory = state?.inventory ?? void 0;
|
|
6831
7710
|
const session = state?.session;
|
|
6832
|
-
const counts = batchLedgerCounts(Array.isArray(rows) ? rows : [], inventory, session);
|
|
7711
|
+
const counts = batchLedgerCounts(Array.isArray(rows) ? rows : [], inventory, session, compliantEntryDone(rows));
|
|
6833
7712
|
const total = Array.isArray(rows) ? rows.length : 0;
|
|
6834
7713
|
let kind;
|
|
6835
7714
|
if (!Array.isArray(rows) || rows.length === 0) kind = state?.error ? "failed" : "idle";
|
|
@@ -7250,6 +8129,29 @@ ${body}`;
|
|
|
7250
8129
|
}
|
|
7251
8130
|
} catch {}
|
|
7252
8131
|
}
|
|
8132
|
+
function installButtonFallbackOf(input, bannerKind) {
|
|
8133
|
+
try {
|
|
8134
|
+
if (bannerKind !== "failed") return null;
|
|
8135
|
+
if (input.busyAct === "check" || input.busyAct === "install") return null;
|
|
8136
|
+
const code = typeof input.lastError === "string" && input.lastError ? input.lastError : "install-failed";
|
|
8137
|
+
const cause = fallbackCauseFromDiag(input.errorDiag, input.errorDetail ?? null, code, input.snapshot?.job?.targetVersion) ?? fallbackCauseFromDetail(input.errorDetail ?? null, code, input.pluginId ?? null);
|
|
8138
|
+
if (!cause) return null;
|
|
8139
|
+
const latest = input.snapshot?.latestVersion ?? null;
|
|
8140
|
+
if (typeof latest !== "string" || !latest || cause.targetVersion !== latest) return null;
|
|
8141
|
+
const offered = typeof input.fallbackOffer?.candidate === "string" ? input.fallbackOffer.candidate.trim() : "";
|
|
8142
|
+
const offerTarget = typeof input.fallbackOffer?.targetVersion === "string" ? input.fallbackOffer.targetVersion.trim() : "";
|
|
8143
|
+
if (offered && offerTarget === cause.targetVersion) return {
|
|
8144
|
+
stage: "confirm",
|
|
8145
|
+
candidate: offered
|
|
8146
|
+
};
|
|
8147
|
+
return {
|
|
8148
|
+
stage: "offer",
|
|
8149
|
+
candidate: null
|
|
8150
|
+
};
|
|
8151
|
+
} catch {
|
|
8152
|
+
return null;
|
|
8153
|
+
}
|
|
8154
|
+
}
|
|
7253
8155
|
function installButtonViewModel(input) {
|
|
7254
8156
|
const l = normalizeLangTag(input.lang ?? "zh");
|
|
7255
8157
|
const view = panelViewModel({
|
|
@@ -7262,6 +8164,8 @@ ${body}`;
|
|
|
7262
8164
|
}, l);
|
|
7263
8165
|
const jobState = (input.snapshot?.job ?? null)?.state ?? null;
|
|
7264
8166
|
const jobActive = jobState === "installing" || jobState === "verifying";
|
|
8167
|
+
const fallback = installButtonFallbackOf(input, view.banner.kind);
|
|
8168
|
+
const fallbackBusy = input.busyAct === "fallback";
|
|
7265
8169
|
if (input.pollCapped === true && jobActive && !input.busyAct) return {
|
|
7266
8170
|
role: "check",
|
|
7267
8171
|
buttonLabel: copyText("panel.action.check", l),
|
|
@@ -7272,9 +8176,12 @@ ${body}`;
|
|
|
7272
8176
|
statusAction: view.banner.action,
|
|
7273
8177
|
showManual: view.showManual,
|
|
7274
8178
|
queueNote: view.queueNote,
|
|
7275
|
-
bannerKind: view.banner.kind
|
|
8179
|
+
bannerKind: view.banner.kind,
|
|
8180
|
+
fallbackStage: null,
|
|
8181
|
+
fallbackCandidate: null,
|
|
8182
|
+
fallbackBusy: false
|
|
7276
8183
|
};
|
|
7277
|
-
if (input.busyAct === "check" || input.busyAct === "install" || jobActive) return {
|
|
8184
|
+
if (input.busyAct === "check" || input.busyAct === "install" || input.busyAct === "fallback" || jobActive) return {
|
|
7278
8185
|
role: "none",
|
|
7279
8186
|
buttonLabel: input.busyAct === "check" ? copyText("panel.action.checking-busy", l) : input.busyAct === "install" ? copyText("panel.action.installing-busy", l) : view.installLabel,
|
|
7280
8187
|
buttonEnabled: false,
|
|
@@ -7284,7 +8191,10 @@ ${body}`;
|
|
|
7284
8191
|
statusAction: view.banner.action,
|
|
7285
8192
|
showManual: view.showManual,
|
|
7286
8193
|
queueNote: view.queueNote,
|
|
7287
|
-
bannerKind: view.banner.kind
|
|
8194
|
+
bannerKind: view.banner.kind,
|
|
8195
|
+
fallbackStage: fallback?.stage ?? null,
|
|
8196
|
+
fallbackCandidate: fallback?.candidate ?? null,
|
|
8197
|
+
fallbackBusy
|
|
7288
8198
|
};
|
|
7289
8199
|
if (view.installEnabled) return {
|
|
7290
8200
|
role: "install",
|
|
@@ -7296,7 +8206,10 @@ ${body}`;
|
|
|
7296
8206
|
statusAction: view.banner.action,
|
|
7297
8207
|
showManual: view.showManual,
|
|
7298
8208
|
queueNote: view.queueNote,
|
|
7299
|
-
bannerKind: view.banner.kind
|
|
8209
|
+
bannerKind: view.banner.kind,
|
|
8210
|
+
fallbackStage: fallback?.stage ?? null,
|
|
8211
|
+
fallbackCandidate: fallback?.candidate ?? null,
|
|
8212
|
+
fallbackBusy
|
|
7300
8213
|
};
|
|
7301
8214
|
if (!input.snapshot || !input.snapshot.latestVersion) return {
|
|
7302
8215
|
role: "check",
|
|
@@ -7308,7 +8221,10 @@ ${body}`;
|
|
|
7308
8221
|
statusAction: view.banner.action,
|
|
7309
8222
|
showManual: view.showManual,
|
|
7310
8223
|
queueNote: view.queueNote,
|
|
7311
|
-
bannerKind: view.banner.kind
|
|
8224
|
+
bannerKind: view.banner.kind,
|
|
8225
|
+
fallbackStage: null,
|
|
8226
|
+
fallbackCandidate: null,
|
|
8227
|
+
fallbackBusy: false
|
|
7312
8228
|
};
|
|
7313
8229
|
if (input.lastError && isCheckSideFailureCode(input.lastError)) return {
|
|
7314
8230
|
role: "check",
|
|
@@ -7320,7 +8236,10 @@ ${body}`;
|
|
|
7320
8236
|
statusAction: view.banner.action,
|
|
7321
8237
|
showManual: view.showManual,
|
|
7322
8238
|
queueNote: view.queueNote,
|
|
7323
|
-
bannerKind: view.banner.kind
|
|
8239
|
+
bannerKind: view.banner.kind,
|
|
8240
|
+
fallbackStage: null,
|
|
8241
|
+
fallbackCandidate: null,
|
|
8242
|
+
fallbackBusy: false
|
|
7324
8243
|
};
|
|
7325
8244
|
const done = view.banner.kind === "done";
|
|
7326
8245
|
return {
|
|
@@ -7333,7 +8252,10 @@ ${body}`;
|
|
|
7333
8252
|
statusAction: view.banner.action,
|
|
7334
8253
|
showManual: view.showManual,
|
|
7335
8254
|
queueNote: view.queueNote,
|
|
7336
|
-
bannerKind: view.banner.kind
|
|
8255
|
+
bannerKind: view.banner.kind,
|
|
8256
|
+
fallbackStage: fallback?.stage ?? null,
|
|
8257
|
+
fallbackCandidate: fallback?.candidate ?? null,
|
|
8258
|
+
fallbackBusy
|
|
7337
8259
|
};
|
|
7338
8260
|
}
|
|
7339
8261
|
function renderInstallButtonHTML(view, opts) {
|
|
@@ -7350,6 +8272,13 @@ ${body}`;
|
|
|
7350
8272
|
const busy = view.buttonBusy ? " aria-busy=\"true\"" : "";
|
|
7351
8273
|
parts.push("<div class=\"dsh-upd-ib-row\"><button type=\"button\"" + actionAttr + " data-primary=\"1\"" + disabled + busy + ">" + escapeHtml(view.buttonLabel) + "</button></div>");
|
|
7352
8274
|
}
|
|
8275
|
+
if (view.fallbackStage === "confirm" && view.fallbackCandidate) {
|
|
8276
|
+
const busy = view.fallbackBusy || view.buttonBusy ? " disabled aria-busy=\"true\"" : "";
|
|
8277
|
+
parts.push("<div class=\"dsh-upd-ib-row\"><button type=\"button\" data-action=\"install-fallback-confirm\" data-primary=\"1\" title=\"" + escapeHtml(copyText("panel.action.install-fallback-confirm-title", l)) + "\"" + busy + ">" + escapeHtml(copyText("panel.action.install-fallback-confirm", l, { version: view.fallbackCandidate })) + "</button><button type=\"button\" data-action=\"wait-latest\" title=\"" + escapeHtml(copyText("panel.action.wait-latest-title", l)) + "\"" + (view.fallbackBusy || view.buttonBusy ? " disabled" : "") + ">" + escapeHtml(copyText("panel.action.wait-latest", l)) + "</button></div>");
|
|
8278
|
+
} else if (view.fallbackStage === "offer") {
|
|
8279
|
+
const busy = view.fallbackBusy || view.buttonBusy ? " disabled aria-busy=\"true\"" : "";
|
|
8280
|
+
parts.push("<div class=\"dsh-upd-ib-row\"><button type=\"button\" data-action=\"install-fallback\" data-primary=\"1\" title=\"" + escapeHtml(copyText("panel.action.install-fallback-title", l)) + "\"" + busy + ">" + escapeHtml(copyText("panel.action.install-fallback", l)) + "</button><button type=\"button\" data-action=\"wait-latest\" title=\"" + escapeHtml(copyText("panel.action.wait-latest-title", l)) + "\"" + (view.fallbackBusy || view.buttonBusy ? " disabled" : "") + ">" + escapeHtml(copyText("panel.action.wait-latest", l)) + "</button></div>");
|
|
8281
|
+
}
|
|
7353
8282
|
if (view.bannerKind === "failed") parts.push("<div class=\"dsh-upd-ib-row\"><button type=\"button\" data-action=\"copy-diag\" title=\"" + escapeHtml(copyText("panel.action.copy-diag-title", l)) + "\">" + escapeHtml(copyText("panel.action.copy-diag", l)) + "</button></div>");
|
|
7354
8283
|
if (view.showManual && opts.manual) parts.push("<details class=\"dsh-upd-ib-manual\"><summary>" + escapeHtml(copyText("panel.chapter.manual", l)) + "</summary><code>" + escapeHtml(opts.manual) + "</code><button type=\"button\" data-action=\"copy-manual\" title=\"" + escapeHtml(copyText("panel.action.copy-manual-title", l)) + "\">" + escapeHtml(copyText("panel.action.copy-manual", l)) + "</button></details>");
|
|
7355
8284
|
if (opts.notice) parts.push("<div class=\"dsh-upd-ib-notice\" role=\"status\">" + escapeHtml(opts.notice) + "</div>");
|
|
@@ -7455,6 +8384,7 @@ ${body}`;
|
|
|
7455
8384
|
let requestId = null;
|
|
7456
8385
|
let latch = null;
|
|
7457
8386
|
let busyAct = null;
|
|
8387
|
+
let fallbackOffer = null;
|
|
7458
8388
|
let ensuring = false;
|
|
7459
8389
|
let pollCount = 0;
|
|
7460
8390
|
let pollCapped = false;
|
|
@@ -7504,9 +8434,11 @@ ${body}`;
|
|
|
7504
8434
|
}
|
|
7505
8435
|
function setLatch(next) {
|
|
7506
8436
|
latch = next;
|
|
8437
|
+
fallbackOffer = null;
|
|
7507
8438
|
}
|
|
7508
8439
|
function clearLatch() {
|
|
7509
8440
|
latch = null;
|
|
8441
|
+
fallbackOffer = null;
|
|
7510
8442
|
}
|
|
7511
8443
|
function latchFromReply(reply, source) {
|
|
7512
8444
|
const env = currentEnvPair();
|
|
@@ -7531,7 +8463,7 @@ ${body}`;
|
|
|
7531
8463
|
atMs: latchNow()
|
|
7532
8464
|
};
|
|
7533
8465
|
}
|
|
7534
|
-
function latchFromJob(job, snap) {
|
|
8466
|
+
function latchFromJob(job, snap, replyDiag) {
|
|
7535
8467
|
const env = currentEnvPair();
|
|
7536
8468
|
const message = typeof job.message === "string" ? job.message : null;
|
|
7537
8469
|
const detail = message && message.includes(":") ? message.slice(message.indexOf(":") + 1).trim() || null : message;
|
|
@@ -7539,7 +8471,7 @@ ${body}`;
|
|
|
7539
8471
|
code: messageCodeOf(message) || "install-failed",
|
|
7540
8472
|
kind: null,
|
|
7541
8473
|
detail,
|
|
7542
|
-
diag: latch?.diag ?? null,
|
|
8474
|
+
diag: latch?.diag ?? replyDiag ?? null,
|
|
7543
8475
|
requestId: job.requestId ?? latch?.requestId ?? requestId,
|
|
7544
8476
|
checkId: receipt?.checkId ?? latch?.checkId ?? null,
|
|
7545
8477
|
runningVersion: snap?.runningVersion ?? snapshot?.runningVersion ?? null,
|
|
@@ -7593,7 +8525,7 @@ ${body}`;
|
|
|
7593
8525
|
if (jobState === "installing" || jobState === "verifying") clearLatch();
|
|
7594
8526
|
else if (jobState === "completed" || jobState === "restart-required") clearLatch();
|
|
7595
8527
|
else if ((jobState === "failed" || jobState === "interrupted") && snapshot?.job) {
|
|
7596
|
-
const next = latchFromJob(snapshot.job, snapshot);
|
|
8528
|
+
const next = latchFromJob(snapshot.job, snapshot, isObject(reply["diag"]) ? reply["diag"] : null);
|
|
7597
8529
|
if (!latch || latch.volatile || latch.code !== next.code || latch.targetVersion !== next.targetVersion || latch.latestVersion !== next.latestVersion) setLatch(next);
|
|
7598
8530
|
} else if (via === "install") clearLatch();
|
|
7599
8531
|
else if (via === "check" && latch?.source === "check") clearLatch();
|
|
@@ -7632,6 +8564,13 @@ ${body}`;
|
|
|
7632
8564
|
queue,
|
|
7633
8565
|
lastError: latch?.code ?? null,
|
|
7634
8566
|
errorKind: latch?.kind ?? null,
|
|
8567
|
+
errorDetail: latch?.detail ?? null,
|
|
8568
|
+
errorDiag: latch?.diag ?? null,
|
|
8569
|
+
pluginId,
|
|
8570
|
+
fallbackOffer: fallbackOffer ? {
|
|
8571
|
+
candidate: fallbackOffer.candidate,
|
|
8572
|
+
targetVersion: fallbackOffer.targetVersion
|
|
8573
|
+
} : null,
|
|
7635
8574
|
busyAct,
|
|
7636
8575
|
pollCapped,
|
|
7637
8576
|
lang: currentLang()
|
|
@@ -7658,9 +8597,9 @@ ${body}`;
|
|
|
7658
8597
|
logClient("error", "update.panel.render.fail", { kind: "unknown" });
|
|
7659
8598
|
}
|
|
7660
8599
|
}
|
|
7661
|
-
function sayCopyKey(key) {
|
|
8600
|
+
function sayCopyKey(key, params) {
|
|
7662
8601
|
try {
|
|
7663
|
-
copyNotice = copyText(key, currentLang());
|
|
8602
|
+
copyNotice = copyText(key, currentLang(), params);
|
|
7664
8603
|
noticeExpiresAt = Date.now() + 5e3;
|
|
7665
8604
|
} catch {
|
|
7666
8605
|
copyNotice = null;
|
|
@@ -7858,6 +8797,124 @@ ${body}`;
|
|
|
7858
8797
|
});
|
|
7859
8798
|
}
|
|
7860
8799
|
}
|
|
8800
|
+
async function doFallbackResolve() {
|
|
8801
|
+
if (!latch) {
|
|
8802
|
+
sayCopyKey("panel.toast.fallback-unavailable");
|
|
8803
|
+
paint();
|
|
8804
|
+
return;
|
|
8805
|
+
}
|
|
8806
|
+
const cause = fallbackCauseFromDetail(latch.detail, latch.code, pluginId);
|
|
8807
|
+
if (!cause || cause.targetVersion !== (latch.latestVersion ?? snapshot?.latestVersion ?? null)) {
|
|
8808
|
+
sayCopyKey("panel.toast.fallback-unavailable");
|
|
8809
|
+
paint();
|
|
8810
|
+
return;
|
|
8811
|
+
}
|
|
8812
|
+
busyAct = "fallback";
|
|
8813
|
+
paint();
|
|
8814
|
+
try {
|
|
8815
|
+
let reply;
|
|
8816
|
+
try {
|
|
8817
|
+
reply = await call(phoneNames.updateCheckFallback, {
|
|
8818
|
+
kind: cause.kind,
|
|
8819
|
+
blame: "target",
|
|
8820
|
+
targetVersion: cause.targetVersion,
|
|
8821
|
+
...typeof cause.windowMs === "number" ? { windowMs: cause.windowMs } : {},
|
|
8822
|
+
windowSource: cause.windowSource,
|
|
8823
|
+
...typeof cause.publishedAtMs === "number" ? { publishedAtMs: cause.publishedAtMs } : {}
|
|
8824
|
+
});
|
|
8825
|
+
} catch {
|
|
8826
|
+
reply = null;
|
|
8827
|
+
}
|
|
8828
|
+
if (!mounted) return;
|
|
8829
|
+
if (!isObject(reply) || reply["ok"] === false) {
|
|
8830
|
+
sayCopyKey("panel.toast.fallback-unavailable");
|
|
8831
|
+
paint();
|
|
8832
|
+
return;
|
|
8833
|
+
}
|
|
8834
|
+
const snap = isObject(reply["snapshot"]) ? reply["snapshot"] : null;
|
|
8835
|
+
const verdict = snap && isObject(snap["verdict"]) ? snap["verdict"] : null;
|
|
8836
|
+
const vKind = verdict && typeof verdict["kind"] === "string" ? verdict["kind"] : "";
|
|
8837
|
+
const vVersion = verdict && typeof verdict["version"] === "string" ? verdict["version"].trim() : "";
|
|
8838
|
+
const snapCandidate = snap && typeof snap["candidate"] === "string" ? snap["candidate"].trim() : "";
|
|
8839
|
+
const rec = isObject(reply["receipt"]) ? reply["receipt"] : null;
|
|
8840
|
+
const gotCheckId = rec && typeof rec["checkId"] === "string" ? rec["checkId"] : "";
|
|
8841
|
+
const candidate = snapCandidate || (vKind === "ok-now" ? vVersion : "");
|
|
8842
|
+
if ((vKind === "downgrade-available" || vKind === "ok-now") && candidate && gotCheckId) fallbackOffer = {
|
|
8843
|
+
candidate,
|
|
8844
|
+
checkId: gotCheckId,
|
|
8845
|
+
targetVersion: cause.targetVersion
|
|
8846
|
+
};
|
|
8847
|
+
else if (vKind === "wait-until") {
|
|
8848
|
+
const unlockAt = verdict && typeof verdict["unlockAtMs"] === "number" ? verdict["unlockAtMs"] : null;
|
|
8849
|
+
const time = typeof unlockAt === "number" ? formatUnlockAt(unlockAt, currentLang()) ?? null : null;
|
|
8850
|
+
if (time) sayCopyKey("panel.toast.fallback-wait", { time });
|
|
8851
|
+
else sayCopyKey("panel.toast.fallback-unavailable");
|
|
8852
|
+
} else sayCopyKey("panel.toast.fallback-unavailable");
|
|
8853
|
+
} finally {
|
|
8854
|
+
busyAct = null;
|
|
8855
|
+
}
|
|
8856
|
+
paint();
|
|
8857
|
+
}
|
|
8858
|
+
async function doFallbackConfirm() {
|
|
8859
|
+
if (!fallbackOffer) return;
|
|
8860
|
+
const offer = fallbackOffer;
|
|
8861
|
+
busyAct = "install";
|
|
8862
|
+
copyNotice = copyText("panel.toast.installing", currentLang());
|
|
8863
|
+
paint();
|
|
8864
|
+
try {
|
|
8865
|
+
requestId = randomRequestId();
|
|
8866
|
+
pollCount = 0;
|
|
8867
|
+
pollCapped = false;
|
|
8868
|
+
let reply;
|
|
8869
|
+
try {
|
|
8870
|
+
reply = await call(phoneNames.updateInstall, {
|
|
8871
|
+
checkId: offer.checkId,
|
|
8872
|
+
requestId,
|
|
8873
|
+
version: offer.candidate,
|
|
8874
|
+
...queueArgs()
|
|
8875
|
+
});
|
|
8876
|
+
} catch (err) {
|
|
8877
|
+
if (!mounted) return;
|
|
8878
|
+
fallbackOffer = null;
|
|
8879
|
+
if (thrownIsCheckExpired(err)) {
|
|
8880
|
+
sayCopyKey("panel.toast.fallback-unavailable");
|
|
8881
|
+
paint();
|
|
8882
|
+
return;
|
|
8883
|
+
}
|
|
8884
|
+
const env = currentEnvPair();
|
|
8885
|
+
setLatch({
|
|
8886
|
+
code: "install-failed",
|
|
8887
|
+
kind: null,
|
|
8888
|
+
detail: thrownDetail(err),
|
|
8889
|
+
diag: null,
|
|
8890
|
+
requestId,
|
|
8891
|
+
checkId: offer.checkId,
|
|
8892
|
+
runningVersion: snapshot?.runningVersion ?? null,
|
|
8893
|
+
installedVersion: snapshot?.installedVersion ?? null,
|
|
8894
|
+
latestVersion: snapshot?.latestVersion ?? null,
|
|
8895
|
+
targetVersion: null,
|
|
8896
|
+
hostKind: env.hostKind,
|
|
8897
|
+
profileName: env.profileName,
|
|
8898
|
+
source: "install",
|
|
8899
|
+
volatile: false,
|
|
8900
|
+
atMs: latchNow()
|
|
8901
|
+
});
|
|
8902
|
+
paint();
|
|
8903
|
+
return;
|
|
8904
|
+
}
|
|
8905
|
+
if (!mounted) return;
|
|
8906
|
+
fallbackOffer = null;
|
|
8907
|
+
if (replyIsCheckExpired(reply)) {
|
|
8908
|
+
sayCopyKey("panel.toast.fallback-unavailable");
|
|
8909
|
+
paint();
|
|
8910
|
+
return;
|
|
8911
|
+
}
|
|
8912
|
+
applyStatusReply(reply, "install");
|
|
8913
|
+
} finally {
|
|
8914
|
+
busyAct = null;
|
|
8915
|
+
}
|
|
8916
|
+
paint();
|
|
8917
|
+
}
|
|
7861
8918
|
async function runAction(kind) {
|
|
7862
8919
|
copyNotice = null;
|
|
7863
8920
|
switch (kind) {
|
|
@@ -7909,6 +8966,20 @@ ${body}`;
|
|
|
7909
8966
|
paint();
|
|
7910
8967
|
return;
|
|
7911
8968
|
}
|
|
8969
|
+
case "install-fallback":
|
|
8970
|
+
if (busyAct) return;
|
|
8971
|
+
await doFallbackResolve();
|
|
8972
|
+
return;
|
|
8973
|
+
case "install-fallback-confirm":
|
|
8974
|
+
if (busyAct || !fallbackOffer) return;
|
|
8975
|
+
await doFallbackConfirm();
|
|
8976
|
+
return;
|
|
8977
|
+
case "wait-latest":
|
|
8978
|
+
fallbackOffer = null;
|
|
8979
|
+
clearLatch();
|
|
8980
|
+
sayCopyKey("panel.toast.failure-dismissed");
|
|
8981
|
+
paint();
|
|
8982
|
+
return;
|
|
7912
8983
|
}
|
|
7913
8984
|
}
|
|
7914
8985
|
function onClick(ev) {
|
|
@@ -7916,7 +8987,7 @@ ${body}`;
|
|
|
7916
8987
|
const t = ev;
|
|
7917
8988
|
const btn = t?.target && typeof t.target.closest === "function" ? t.target.closest("[data-action]") : null;
|
|
7918
8989
|
const kind = btn?.getAttribute ? btn.getAttribute("data-action") : null;
|
|
7919
|
-
if (kind !== "install" && kind !== "check" && kind !== "copy-manual" && kind !== "copy-diag") return;
|
|
8990
|
+
if (kind !== "install" && kind !== "check" && kind !== "copy-manual" && kind !== "copy-diag" && kind !== "install-fallback" && kind !== "install-fallback-confirm" && kind !== "wait-latest") return;
|
|
7920
8991
|
act(kind);
|
|
7921
8992
|
} catch {}
|
|
7922
8993
|
}
|
|
@@ -10773,7 +11844,7 @@ ${body}`;
|
|
|
10773
11844
|
}, react.createElement("span", { style: S.morePkg }, row.pkg), react.createElement("span", { style: S.moreDesc }, row.desc), react.createElement("span", { style: S.moreIcon }, react.createElement(ExternalIcon, null)))));
|
|
10774
11845
|
}
|
|
10775
11846
|
/** 版本胶囊那一行字:只在这里拼一次,屏上与用例读的是同一串。 */
|
|
10776
|
-
const MANAGER_VERSION_TEXT = "dsh-life-pack · 0.3.
|
|
11847
|
+
const MANAGER_VERSION_TEXT = "dsh-life-pack · 0.3.67";
|
|
10777
11848
|
/** 右下角那本书离面板两沿的距离:用户口径「一直处于面板右下角、不随列表滑动消失」
|
|
10778
11849
|
* ⇒ sticky 吸附(面板相对,视口多大都落在面板角上);INSET=右沿,BOTTOM=底沿。 */
|
|
10779
11850
|
const MANUAL_ENTRY_INSET = 16;
|
|
@@ -10974,7 +12045,40 @@ ${body}`;
|
|
|
10974
12045
|
});
|
|
10975
12046
|
} catch {}
|
|
10976
12047
|
}, [active]);
|
|
10977
|
-
|
|
12048
|
+
/** 面板宽度不许跟着宿主滚动条变:宿主承载本面板的滚动体一出现滚动条,
|
|
12049
|
+
* 内容盒就窄 5px(主题里 `--dsh-scrollbar-width:5px`),标题行右对齐的按钮组便跟着左右挪;
|
|
12050
|
+
* 而滚动条出不出,取决于**当前页签**的内容高——装了的那家有配置卡,必然要滚,缺席页签不必。
|
|
12051
|
+
*
|
|
12052
|
+
* 这里不动面板高度、也不改宿主样式表,只给**最近的可滚动祖先**钉一条内联
|
|
12053
|
+
* `scrollbar-gutter: stable`:槽位恒定预留,滚动条本身仍按需出现/消失,内容盒宽度因此恒定。
|
|
12054
|
+
* 卸载时还原(宿主本来就有 stable 时压根不写),改动不留在宿主上。
|
|
12055
|
+
* 替身渲染台(test/helpers/panel-render.mjs)里 ref 拿不到元素 ⇒ 这里天然空过,不碰 window。 */
|
|
12056
|
+
const rootRef = react.useRef(null);
|
|
12057
|
+
react.useEffect(() => {
|
|
12058
|
+
const root = rootRef.current;
|
|
12059
|
+
if (root === null || typeof window === "undefined") return;
|
|
12060
|
+
let node = root.parentElement;
|
|
12061
|
+
while (node !== null) {
|
|
12062
|
+
const overflowY = window.getComputedStyle(node).overflowY;
|
|
12063
|
+
if (overflowY === "auto" || overflowY === "scroll") break;
|
|
12064
|
+
node = node.parentElement;
|
|
12065
|
+
}
|
|
12066
|
+
const scroller = node;
|
|
12067
|
+
if (scroller === null) return;
|
|
12068
|
+
if (window.getComputedStyle(scroller).getPropertyValue("scrollbar-gutter").trim() === "stable") return;
|
|
12069
|
+
const previous = scroller.style.getPropertyValue("scrollbar-gutter");
|
|
12070
|
+
scroller.style.setProperty("scrollbar-gutter", "stable");
|
|
12071
|
+
return () => {
|
|
12072
|
+
if (previous.length > 0) scroller.style.setProperty("scrollbar-gutter", previous);
|
|
12073
|
+
else scroller.style.removeProperty("scrollbar-gutter");
|
|
12074
|
+
};
|
|
12075
|
+
}, []);
|
|
12076
|
+
return react.createElement("div", {
|
|
12077
|
+
style: { position: "relative" },
|
|
12078
|
+
ref: (element) => {
|
|
12079
|
+
rootRef.current = element;
|
|
12080
|
+
}
|
|
12081
|
+
}, react.createElement("div", { style: S.headRow }, react.createElement("div", { style: S.head }, "爱生活"), react.createElement("span", {
|
|
10978
12082
|
style: S.versionCapsule,
|
|
10979
12083
|
"data-ilife-version": "capsule"
|
|
10980
12084
|
}, MANAGER_VERSION_TEXT), react.createElement("div", { style: S.headActions }, react.createElement("button", {
|