dsh-life-pack 0.3.66 → 0.3.68
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 +1270 -230
- 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.11/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) + ")");
|
|
@@ -493,71 +493,7 @@ window.__ModuleLoader__.load({
|
|
|
493
493
|
return buildPhoneNames(prefix).logAppend;
|
|
494
494
|
}
|
|
495
495
|
//#endregion
|
|
496
|
-
//#region ../../node_modules/.pnpm/dsh-plugin-update@0.18.
|
|
497
|
-
const COPY_BUDGET_CHARS = 1500;
|
|
498
|
-
const REDACTED_PATH = "<路径>";
|
|
499
|
-
const REDACTED_SECRET = "<脱敏>";
|
|
500
|
-
const ABSOLUTE_PATH_RE = /[A-Za-z]:\\[^\s"']*|\\\\[^\s"'()\[\];]+|(^|[\s"'(\[=,])\/\/[^\s"'()\[\];]+|(^|[\s"'(\[=:,])\/(?!\/)[^\s"'()\[\];]+/g;
|
|
501
|
-
const URL_USERINFO_RE = /[A-Za-z][A-Za-z0-9+.-]*:\/\/[^\s/]*@/;
|
|
502
|
-
const NPM_TOKEN_RE = /\bnpm_[A-Za-z0-9_-]{8,}/g;
|
|
503
|
-
const GITHUB_TOKEN_RE = /\b(?:gh[pousr]_[A-Za-z0-9]{8,}|github_pat_[A-Za-z0-9_]{10,})/g;
|
|
504
|
-
const SK_TOKEN_RE = /\bsk-[A-Za-z0-9_-]{6,}/g;
|
|
505
|
-
const BEARER_TOKEN_RE = /(\bbearer\s+)[A-Za-z0-9._~+/-=]{6,}/gi;
|
|
506
|
-
const CRED_PAIR_RE = /(\b(?:token|password|passwd|pwd|api[_-]?key|access[_-]?key|auth[_-]?token|secret|cookie)\s*[:=]\s*)("[^"]+"|'[^']+'|[^\s'";,)\]]+)/gi;
|
|
507
|
-
const EMAIL_RE = /\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}/g;
|
|
508
|
-
function flattenWhitespace(text) {
|
|
509
|
-
return String(text ?? "").replace(/\s+/g, " ").trim();
|
|
510
|
-
}
|
|
511
|
-
function applyPathRule(text) {
|
|
512
|
-
ABSOLUTE_PATH_RE.lastIndex = 0;
|
|
513
|
-
return text.replace(ABSOLUTE_PATH_RE, (_whole, g1, g2) => {
|
|
514
|
-
return `${g1 ?? g2 ?? ""}${REDACTED_PATH}`;
|
|
515
|
-
});
|
|
516
|
-
}
|
|
517
|
-
function applyTokenRule(text) {
|
|
518
|
-
NPM_TOKEN_RE.lastIndex = 0;
|
|
519
|
-
GITHUB_TOKEN_RE.lastIndex = 0;
|
|
520
|
-
SK_TOKEN_RE.lastIndex = 0;
|
|
521
|
-
BEARER_TOKEN_RE.lastIndex = 0;
|
|
522
|
-
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}`);
|
|
523
|
-
}
|
|
524
|
-
function applyCredPairRule(text) {
|
|
525
|
-
CRED_PAIR_RE.lastIndex = 0;
|
|
526
|
-
return text.replace(CRED_PAIR_RE, (_whole, head) => `${head}${REDACTED_SECRET}`);
|
|
527
|
-
}
|
|
528
|
-
function applyEmailRule(text) {
|
|
529
|
-
EMAIL_RE.lastIndex = 0;
|
|
530
|
-
return text.replace(EMAIL_RE, REDACTED_SECRET);
|
|
531
|
-
}
|
|
532
|
-
function hasUserinfo(text) {
|
|
533
|
-
URL_USERINFO_RE.lastIndex = 0;
|
|
534
|
-
return URL_USERINFO_RE.test(text);
|
|
535
|
-
}
|
|
536
|
-
function truncateToWordBoundary(text, max) {
|
|
537
|
-
const input = String(text ?? "");
|
|
538
|
-
if (input.length <= max) return input;
|
|
539
|
-
const slice = input.slice(0, max);
|
|
540
|
-
const lastSpace = slice.lastIndexOf(" ");
|
|
541
|
-
let cut = lastSpace > 0 ? slice.slice(0, lastSpace) : slice;
|
|
542
|
-
const lastOpen = cut.lastIndexOf("<");
|
|
543
|
-
if (lastOpen > cut.lastIndexOf(">")) cut = cut.slice(0, lastOpen).trimEnd();
|
|
544
|
-
if (!cut) cut = slice;
|
|
545
|
-
return `${cut}\u2026`;
|
|
546
|
-
}
|
|
547
|
-
function truncateForCopy(text) {
|
|
548
|
-
return truncateToWordBoundary(text, COPY_BUDGET_CHARS);
|
|
549
|
-
}
|
|
550
|
-
function scrubWithoutBudget(text) {
|
|
551
|
-
return applyEmailRule(applyCredPairRule(applyTokenRule(applyPathRule(text))));
|
|
552
|
-
}
|
|
553
|
-
function sanitizeForCopy(text) {
|
|
554
|
-
const flat = flattenWhitespace(String(text ?? ""));
|
|
555
|
-
if (!flat) return "";
|
|
556
|
-
if (hasUserinfo(flat)) return "";
|
|
557
|
-
return truncateForCopy(scrubWithoutBudget(flat));
|
|
558
|
-
}
|
|
559
|
-
//#endregion
|
|
560
|
-
//#region ../../node_modules/.pnpm/dsh-plugin-update@0.18.6/node_modules/dsh-plugin-update/dist/service.js
|
|
496
|
+
//#region ../../node_modules/.pnpm/dsh-plugin-update@0.18.11/node_modules/dsh-plugin-update/dist/version-judgment.js
|
|
561
497
|
function updateError(code) {
|
|
562
498
|
return Object.assign(new Error(code), { code });
|
|
563
499
|
}
|
|
@@ -644,7 +580,7 @@ window.__ModuleLoader__.load({
|
|
|
644
580
|
return 0;
|
|
645
581
|
}
|
|
646
582
|
//#endregion
|
|
647
|
-
//#region ../../node_modules/.pnpm/dsh-plugin-update@0.18.
|
|
583
|
+
//#region ../../node_modules/.pnpm/dsh-plugin-update@0.18.11/node_modules/dsh-plugin-update/dist/lang.js
|
|
648
584
|
function normalizeLangTag(tag) {
|
|
649
585
|
if (typeof tag !== "string") return "zh";
|
|
650
586
|
const s = tag.trim().toLowerCase().replace(/_/g, "-");
|
|
@@ -786,7 +722,7 @@ window.__ModuleLoader__.load({
|
|
|
786
722
|
};
|
|
787
723
|
}
|
|
788
724
|
//#endregion
|
|
789
|
-
//#region ../../node_modules/.pnpm/dsh-plugin-update@0.18.
|
|
725
|
+
//#region ../../node_modules/.pnpm/dsh-plugin-update@0.18.11/node_modules/dsh-plugin-update/dist/bilingual.js
|
|
790
726
|
const BILINGUAL_STRINGS = {
|
|
791
727
|
"entry.label.idle": {
|
|
792
728
|
en: "Check for updates",
|
|
@@ -2088,6 +2024,41 @@ window.__ModuleLoader__.load({
|
|
|
2088
2024
|
zh: "请重试一次;若持续,请提交诊断信息至插件作者。",
|
|
2089
2025
|
draft: true
|
|
2090
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
|
+
},
|
|
2091
2062
|
"batch.banner.failed-title": {
|
|
2092
2063
|
en: "{n} failed to install.",
|
|
2093
2064
|
zh: "{n} 个插件安装失败。",
|
|
@@ -2253,6 +2224,11 @@ window.__ModuleLoader__.load({
|
|
|
2253
2224
|
zh: "失败 {code}:{detail}",
|
|
2254
2225
|
draft: true
|
|
2255
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
|
+
},
|
|
2256
2232
|
"batch.diag.source-job": {
|
|
2257
2233
|
en: "(Source: background job record)",
|
|
2258
2234
|
zh: "(来源:后台任务执行记录)",
|
|
@@ -2288,6 +2264,11 @@ window.__ModuleLoader__.load({
|
|
|
2288
2264
|
zh: "此行缺少取消排队所需的信息,暂无法取消;请待下次刷新后重试。",
|
|
2289
2265
|
draft: true
|
|
2290
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
|
+
},
|
|
2291
2272
|
"batch.toast.cancel-ok": {
|
|
2292
2273
|
en: "Queue cancelled: this plugin will not wait.",
|
|
2293
2274
|
zh: "已取消排队:此插件将不再等待。",
|
|
@@ -2308,6 +2289,16 @@ window.__ModuleLoader__.load({
|
|
|
2308
2289
|
zh: "诊断信息已复制,请提交至插件作者(已脱敏)。",
|
|
2309
2290
|
draft: true
|
|
2310
2291
|
},
|
|
2292
|
+
"batch.toast.copy-all-diag-ok": {
|
|
2293
|
+
en: "Diagnostics for {n} plugin(s) copied; paste them to the plugin author (already redacted).",
|
|
2294
|
+
zh: "已复制 {n} 家插件的诊断,请提交至插件作者(已脱敏)。",
|
|
2295
|
+
draft: true
|
|
2296
|
+
},
|
|
2297
|
+
"batch.toast.copy-all-manual-ok": {
|
|
2298
|
+
en: "{n} manual command(s) copied (plugins without a command are marked as # comments); paste them into the terminal line by line.",
|
|
2299
|
+
zh: "已复制 {n} 条手工命令(无命令的插件已用 # 注释标注),请粘贴至终端逐行执行。",
|
|
2300
|
+
draft: true
|
|
2301
|
+
},
|
|
2311
2302
|
"batch.toast.restart-delegated": {
|
|
2312
2303
|
en: "Handled by the caller’s restart flow; the new version takes effect after restart.",
|
|
2313
2304
|
zh: "已按调用方重启流程处理;重启后新版本生效。",
|
|
@@ -2518,7 +2509,7 @@ window.__ModuleLoader__.load({
|
|
|
2518
2509
|
}
|
|
2519
2510
|
const BILINGUAL_CSS = [".dsh-upd-bi{display:inline;overflow-wrap:anywhere}", ".dsh-upd-bi [lang]{overflow-wrap:anywhere}"].join("\n");
|
|
2520
2511
|
//#endregion
|
|
2521
|
-
//#region ../../node_modules/.pnpm/dsh-plugin-update@0.18.
|
|
2512
|
+
//#region ../../node_modules/.pnpm/dsh-plugin-update@0.18.11/node_modules/dsh-plugin-update/dist/changelog.js
|
|
2522
2513
|
const CHANGELOG_MAX_CHARS = 65536;
|
|
2523
2514
|
const CHANGELOG_ALL_CATEGORIES = [
|
|
2524
2515
|
"Added",
|
|
@@ -3626,7 +3617,7 @@ ${note}${blocks.join("\n")}
|
|
|
3626
3617
|
}
|
|
3627
3618
|
}
|
|
3628
3619
|
//#endregion
|
|
3629
|
-
//#region ../../node_modules/.pnpm/dsh-plugin-update@0.18.
|
|
3620
|
+
//#region ../../node_modules/.pnpm/dsh-plugin-update@0.18.11/node_modules/dsh-plugin-update/dist/log-events.js
|
|
3630
3621
|
const LOG_EVENT_CALL = "host.call";
|
|
3631
3622
|
const LOG_EVENT_CALL_FAIL = "host.call.fail";
|
|
3632
3623
|
const LOG_EVENT_INSTALL_EXEC = "update.install.exec";
|
|
@@ -3877,7 +3868,7 @@ ${note}${blocks.join("\n")}
|
|
|
3877
3868
|
};
|
|
3878
3869
|
}
|
|
3879
3870
|
//#endregion
|
|
3880
|
-
//#region ../../node_modules/.pnpm/dsh-plugin-update@0.18.
|
|
3871
|
+
//#region ../../node_modules/.pnpm/dsh-plugin-update@0.18.11/node_modules/dsh-plugin-update/dist/codes.js
|
|
3881
3872
|
const BLOCKED_REASONS = [
|
|
3882
3873
|
"unknown-profile",
|
|
3883
3874
|
"channel-mismatch",
|
|
@@ -3912,8 +3903,25 @@ ${note}${blocks.join("\n")}
|
|
|
3912
3903
|
return typeof code === "string" && isOneOf(CHECK_SIDE_FAILURE_CODES, code.trim());
|
|
3913
3904
|
}
|
|
3914
3905
|
//#endregion
|
|
3915
|
-
//#region ../../node_modules/.pnpm/dsh-plugin-update@0.18.
|
|
3906
|
+
//#region ../../node_modules/.pnpm/dsh-plugin-update@0.18.11/node_modules/dsh-plugin-update/dist/install-cause.js
|
|
3916
3907
|
const CAUSE_KINDS = ["minimum-release-age"];
|
|
3908
|
+
const CAUSE_SIGNATURES = [{
|
|
3909
|
+
kind: "minimum-release-age",
|
|
3910
|
+
codes: ["install-failed"],
|
|
3911
|
+
stages: ["exec"],
|
|
3912
|
+
token: "[ERR_PNPM_MINIMUM_RELEASE_AGE_VIOLATION]",
|
|
3913
|
+
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?)/
|
|
3914
|
+
}];
|
|
3915
|
+
function toMs(value) {
|
|
3916
|
+
try {
|
|
3917
|
+
if (typeof value === "number" && Number.isFinite(value) && value > 0) return value;
|
|
3918
|
+
if (typeof value === "string" && value.trim()) {
|
|
3919
|
+
const ms = Date.parse(value.trim());
|
|
3920
|
+
if (Number.isFinite(ms) && ms > 0) return ms;
|
|
3921
|
+
}
|
|
3922
|
+
} catch {}
|
|
3923
|
+
return null;
|
|
3924
|
+
}
|
|
3917
3925
|
function causePackageNameOf(spec) {
|
|
3918
3926
|
try {
|
|
3919
3927
|
const s = String(spec ?? "").trim();
|
|
@@ -3953,118 +3961,133 @@ ${note}${blocks.join("\n")}
|
|
|
3953
3961
|
return null;
|
|
3954
3962
|
}
|
|
3955
3963
|
}
|
|
3964
|
+
const WINDOW_PATTERN = /less than (?<windowMinutes>[0-9]{1,7}) minutes? ago/;
|
|
3965
|
+
const WINDOW_MINUTES_MAX = 5256e3;
|
|
3966
|
+
function parseWindowMinutes(detail) {
|
|
3967
|
+
try {
|
|
3968
|
+
const matched = WINDOW_PATTERN.exec(detail);
|
|
3969
|
+
if (!matched?.groups) return null;
|
|
3970
|
+
const n = Number(matched.groups["windowMinutes"]);
|
|
3971
|
+
if (!Number.isInteger(n) || n <= 0 || n > WINDOW_MINUTES_MAX) return null;
|
|
3972
|
+
return n;
|
|
3973
|
+
} catch {
|
|
3974
|
+
return null;
|
|
3975
|
+
}
|
|
3976
|
+
}
|
|
3977
|
+
function interpretInstallCause(input) {
|
|
3978
|
+
try {
|
|
3979
|
+
const errorCode = String(input?.errorCode ?? "");
|
|
3980
|
+
const detail = input?.detail;
|
|
3981
|
+
if (!errorCode || typeof detail !== "string" || !detail.trim()) return null;
|
|
3982
|
+
const nowMs = toMs(input?.nowMs) ?? Date.now();
|
|
3983
|
+
for (const sig of CAUSE_SIGNATURES) {
|
|
3984
|
+
const codes = sig.codes;
|
|
3985
|
+
const stages = sig.stages;
|
|
3986
|
+
if (!codes.includes(errorCode)) continue;
|
|
3987
|
+
if (stages.length > 0 && typeof input?.stage === "string" && input.stage) {
|
|
3988
|
+
if (!stages.includes(input.stage)) continue;
|
|
3989
|
+
}
|
|
3990
|
+
if (!detail.includes(sig.token)) continue;
|
|
3991
|
+
const matched = sig.pattern.exec(detail);
|
|
3992
|
+
if (!matched || !matched.groups) continue;
|
|
3993
|
+
const spec = String(matched.groups["spec"] ?? "").trim();
|
|
3994
|
+
if (!spec) continue;
|
|
3995
|
+
const publishedAtMs = matched.groups["published"] ? toMs(matched.groups["published"]) : null;
|
|
3996
|
+
const cutoffMs = matched.groups["cutoff"] ? toMs(matched.groups["cutoff"]) : null;
|
|
3997
|
+
const windowMinutes = parseWindowMinutes(detail);
|
|
3998
|
+
let unlockAtMs;
|
|
3999
|
+
if (publishedAtMs !== null && windowMinutes !== null) {
|
|
4000
|
+
const unlock = publishedAtMs + windowMinutes * 6e4;
|
|
4001
|
+
if (unlock > nowMs) unlockAtMs = unlock;
|
|
4002
|
+
} else if (publishedAtMs !== null && cutoffMs !== null) {
|
|
4003
|
+
const windowMs = nowMs - cutoffMs;
|
|
4004
|
+
const unlock = publishedAtMs + windowMs;
|
|
4005
|
+
if (windowMs > 0 && unlock > nowMs) unlockAtMs = unlock;
|
|
4006
|
+
}
|
|
4007
|
+
const at = spec.lastIndexOf("@");
|
|
4008
|
+
return {
|
|
4009
|
+
kind: sig.kind,
|
|
4010
|
+
spec,
|
|
4011
|
+
packageName: causePackageNameOf(spec),
|
|
4012
|
+
packageVersion: at > 0 ? spec.slice(at + 1) || null : null,
|
|
4013
|
+
publishedAtMs,
|
|
4014
|
+
cutoffMs,
|
|
4015
|
+
windowMinutes,
|
|
4016
|
+
...unlockAtMs !== void 0 ? { unlockAtMs } : {},
|
|
4017
|
+
blame: blameCausePackage(spec, input?.targetPackageName)
|
|
4018
|
+
};
|
|
4019
|
+
}
|
|
4020
|
+
return null;
|
|
4021
|
+
} catch {
|
|
4022
|
+
return null;
|
|
4023
|
+
}
|
|
4024
|
+
}
|
|
3956
4025
|
//#endregion
|
|
3957
|
-
//#region ../../node_modules/.pnpm/dsh-plugin-update@0.18.
|
|
3958
|
-
|
|
3959
|
-
|
|
4026
|
+
//#region ../../node_modules/.pnpm/dsh-plugin-update@0.18.11/node_modules/dsh-plugin-update/dist/redaction.js
|
|
4027
|
+
const COPY_BUDGET_CHARS = 1500;
|
|
4028
|
+
const REDACTED_PATH = "<路径>";
|
|
4029
|
+
const REDACTED_SECRET = "<脱敏>";
|
|
4030
|
+
const ABSOLUTE_PATH_RE = /[A-Za-z]:\\[^\s"']*|\\\\[^\s"'()\[\];]+|(^|[\s"'(\[=,])\/\/[^\s"'()\[\];]+|(^|[\s"'(\[=:,])\/(?!\/)[^\s"'()\[\];]+/g;
|
|
4031
|
+
const URL_USERINFO_RE = /[A-Za-z][A-Za-z0-9+.-]*:\/\/[^\s/]*@/;
|
|
4032
|
+
const NPM_TOKEN_RE = /\bnpm_[A-Za-z0-9_-]{8,}/g;
|
|
4033
|
+
const GITHUB_TOKEN_RE = /\b(?:gh[pousr]_[A-Za-z0-9]{8,}|github_pat_[A-Za-z0-9_]{10,})/g;
|
|
4034
|
+
const SK_TOKEN_RE = /\bsk-[A-Za-z0-9_-]{6,}/g;
|
|
4035
|
+
const BEARER_TOKEN_RE = /(\bbearer\s+)[A-Za-z0-9._~+/-=]{6,}/gi;
|
|
4036
|
+
const CRED_PAIR_RE = /(\b(?:token|password|passwd|pwd|api[_-]?key|access[_-]?key|auth[_-]?token|secret|cookie)\s*[:=]\s*)("[^"]+"|'[^']+'|[^\s'";,)\]]+)/gi;
|
|
4037
|
+
const EMAIL_RE = /\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}/g;
|
|
4038
|
+
function flattenWhitespace(text) {
|
|
4039
|
+
return String(text ?? "").replace(/\s+/g, " ").trim();
|
|
3960
4040
|
}
|
|
3961
|
-
|
|
3962
|
-
|
|
3963
|
-
|
|
3964
|
-
|
|
3965
|
-
|
|
3966
|
-
border: "--dsh-update-border",
|
|
3967
|
-
borderStrong: "--dsh-update-border-strong",
|
|
3968
|
-
buttonBg: "--dsh-update-button-bg",
|
|
3969
|
-
primary: "--dsh-update-primary",
|
|
3970
|
-
primaryDeep: "--dsh-update-primary-deep",
|
|
3971
|
-
focus: "--dsh-update-focus",
|
|
3972
|
-
okBg: "--dsh-update-ok-bg",
|
|
3973
|
-
okBorder: "--dsh-update-ok-border",
|
|
3974
|
-
okText: "--dsh-update-ok-text",
|
|
3975
|
-
warnBg: "--dsh-update-warn-bg",
|
|
3976
|
-
warnBorder: "--dsh-update-warn-border",
|
|
3977
|
-
warnText: "--dsh-update-warn-text",
|
|
3978
|
-
badBg: "--dsh-update-bad-bg",
|
|
3979
|
-
badBorder: "--dsh-update-bad-border",
|
|
3980
|
-
badText: "--dsh-update-bad-text",
|
|
3981
|
-
busyBg: "--dsh-update-busy-bg",
|
|
3982
|
-
busyBorder: "--dsh-update-busy-border",
|
|
3983
|
-
busyText: "--dsh-update-busy-text",
|
|
3984
|
-
newText: "--dsh-update-new-text",
|
|
3985
|
-
newOkText: "--dsh-update-new-ok-text",
|
|
3986
|
-
fontSans: "--dsh-update-font-sans",
|
|
3987
|
-
fontSerif: "--dsh-update-font-serif",
|
|
3988
|
-
fontMono: "--dsh-update-font-mono",
|
|
3989
|
-
shadow: "--dsh-update-shadow",
|
|
3990
|
-
radiusPanel: "--dsh-update-radius-panel",
|
|
3991
|
-
radiusButton: "--dsh-update-radius-button",
|
|
3992
|
-
radiusBadge: "--dsh-update-radius-badge",
|
|
3993
|
-
entryFontSize: "--dsh-update-entry-font-size",
|
|
3994
|
-
entryPadding: "--dsh-update-entry-padding",
|
|
3995
|
-
entryBorderRadius: "--dsh-update-entry-border-radius",
|
|
3996
|
-
entryScale: "--dsh-update-entry-scale",
|
|
3997
|
-
panelFontSize: "--dsh-update-panel-font-size",
|
|
3998
|
-
panelChapterFontSize: "--dsh-update-panel-chapter-font-size",
|
|
3999
|
-
panelBannerTitleFontSize: "--dsh-update-panel-banner-title-font-size",
|
|
4000
|
-
panelLogFontSize: "--dsh-update-panel-log-font-size",
|
|
4001
|
-
panelSmallFontSize: "--dsh-update-panel-small-font-size"
|
|
4002
|
-
};
|
|
4003
|
-
const THEME_TOKEN_COLOR_KEYS = /* @__PURE__ */ new Set([
|
|
4004
|
-
"text",
|
|
4005
|
-
"textMuted",
|
|
4006
|
-
"bg",
|
|
4007
|
-
"bgSoft",
|
|
4008
|
-
"border",
|
|
4009
|
-
"borderStrong",
|
|
4010
|
-
"buttonBg",
|
|
4011
|
-
"primary",
|
|
4012
|
-
"primaryDeep",
|
|
4013
|
-
"focus",
|
|
4014
|
-
"okBg",
|
|
4015
|
-
"okBorder",
|
|
4016
|
-
"okText",
|
|
4017
|
-
"warnBg",
|
|
4018
|
-
"warnBorder",
|
|
4019
|
-
"warnText",
|
|
4020
|
-
"badBg",
|
|
4021
|
-
"badBorder",
|
|
4022
|
-
"badText",
|
|
4023
|
-
"busyBg",
|
|
4024
|
-
"busyBorder",
|
|
4025
|
-
"busyText",
|
|
4026
|
-
"newText",
|
|
4027
|
-
"newOkText"
|
|
4028
|
-
]);
|
|
4029
|
-
function themeTokensError(raw) {
|
|
4030
|
-
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)})`);
|
|
4041
|
+
function applyPathRule(text) {
|
|
4042
|
+
ABSOLUTE_PATH_RE.lastIndex = 0;
|
|
4043
|
+
return text.replace(ABSOLUTE_PATH_RE, (_whole, g1, g2) => {
|
|
4044
|
+
return `${g1 ?? g2 ?? ""}${REDACTED_PATH}`;
|
|
4045
|
+
});
|
|
4031
4046
|
}
|
|
4032
|
-
function
|
|
4033
|
-
|
|
4034
|
-
|
|
4035
|
-
|
|
4036
|
-
|
|
4037
|
-
|
|
4038
|
-
if (/javascript\s*:/i.test(v)) return false;
|
|
4039
|
-
return true;
|
|
4047
|
+
function applyTokenRule(text) {
|
|
4048
|
+
NPM_TOKEN_RE.lastIndex = 0;
|
|
4049
|
+
GITHUB_TOKEN_RE.lastIndex = 0;
|
|
4050
|
+
SK_TOKEN_RE.lastIndex = 0;
|
|
4051
|
+
BEARER_TOKEN_RE.lastIndex = 0;
|
|
4052
|
+
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}`);
|
|
4040
4053
|
}
|
|
4041
|
-
function
|
|
4042
|
-
|
|
4043
|
-
|
|
4044
|
-
return /^(?:#[0-9a-fA-F]{3}|#[0-9a-fA-F]{6}|#[0-9a-fA-F]{8}|[a-zA-Z]+)$/.test(v);
|
|
4054
|
+
function applyCredPairRule(text) {
|
|
4055
|
+
CRED_PAIR_RE.lastIndex = 0;
|
|
4056
|
+
return text.replace(CRED_PAIR_RE, (_whole, head) => `${head}${REDACTED_SECRET}`);
|
|
4045
4057
|
}
|
|
4046
|
-
function
|
|
4047
|
-
|
|
4048
|
-
|
|
4049
|
-
|
|
4050
|
-
|
|
4051
|
-
|
|
4052
|
-
|
|
4053
|
-
if (value === void 0) continue;
|
|
4054
|
-
if (key === "entryScale") {
|
|
4055
|
-
if (typeof value !== "number" || !Number.isFinite(value) || value <= 0) throw themeTokensError(tokens);
|
|
4056
|
-
parts.push(THEME_TOKEN_VARS[key] + ":" + String(value));
|
|
4057
|
-
continue;
|
|
4058
|
-
}
|
|
4059
|
-
if (typeof value !== "string") throw themeTokensError(tokens);
|
|
4060
|
-
const text = value.trim();
|
|
4061
|
-
if (THEME_TOKEN_COLOR_KEYS.has(key)) {
|
|
4062
|
-
if (!isThemeColorValue(text)) throw themeTokensError(tokens);
|
|
4063
|
-
} else if (!isSafeThemeCssValue(text)) throw themeTokensError(tokens);
|
|
4064
|
-
parts.push(THEME_TOKEN_VARS[key] + ":" + text);
|
|
4065
|
-
}
|
|
4066
|
-
return parts.join(";");
|
|
4058
|
+
function applyEmailRule(text) {
|
|
4059
|
+
EMAIL_RE.lastIndex = 0;
|
|
4060
|
+
return text.replace(EMAIL_RE, REDACTED_SECRET);
|
|
4061
|
+
}
|
|
4062
|
+
function hasUserinfo(text) {
|
|
4063
|
+
URL_USERINFO_RE.lastIndex = 0;
|
|
4064
|
+
return URL_USERINFO_RE.test(text);
|
|
4067
4065
|
}
|
|
4066
|
+
function truncateToWordBoundary(text, max) {
|
|
4067
|
+
const input = String(text ?? "");
|
|
4068
|
+
if (input.length <= max) return input;
|
|
4069
|
+
const slice = input.slice(0, max);
|
|
4070
|
+
const lastSpace = slice.lastIndexOf(" ");
|
|
4071
|
+
let cut = lastSpace > 0 ? slice.slice(0, lastSpace) : slice;
|
|
4072
|
+
const lastOpen = cut.lastIndexOf("<");
|
|
4073
|
+
if (lastOpen > cut.lastIndexOf(">")) cut = cut.slice(0, lastOpen).trimEnd();
|
|
4074
|
+
if (!cut) cut = slice;
|
|
4075
|
+
return `${cut}\u2026`;
|
|
4076
|
+
}
|
|
4077
|
+
function truncateForCopy(text) {
|
|
4078
|
+
return truncateToWordBoundary(text, COPY_BUDGET_CHARS);
|
|
4079
|
+
}
|
|
4080
|
+
function scrubWithoutBudget(text) {
|
|
4081
|
+
return applyEmailRule(applyCredPairRule(applyTokenRule(applyPathRule(text))));
|
|
4082
|
+
}
|
|
4083
|
+
function sanitizeForCopy(text) {
|
|
4084
|
+
const flat = flattenWhitespace(String(text ?? ""));
|
|
4085
|
+
if (!flat) return "";
|
|
4086
|
+
if (hasUserinfo(flat)) return "";
|
|
4087
|
+
return truncateForCopy(scrubWithoutBudget(flat));
|
|
4088
|
+
}
|
|
4089
|
+
//#endregion
|
|
4090
|
+
//#region ../../node_modules/.pnpm/dsh-plugin-update@0.18.11/node_modules/dsh-plugin-update/dist/panel-copy.js
|
|
4068
4091
|
const BLOCKED_KEYS = {
|
|
4069
4092
|
"unknown-profile": {
|
|
4070
4093
|
title: "panel.blocked.unknown-profile.title",
|
|
@@ -4374,6 +4397,118 @@ ${note}${blocks.join("\n")}
|
|
|
4374
4397
|
` ${copyText("panel.diag.copy.block.remedy", l, { remedy })}`
|
|
4375
4398
|
].join("\n");
|
|
4376
4399
|
}
|
|
4400
|
+
//#endregion
|
|
4401
|
+
//#region ../../node_modules/.pnpm/dsh-plugin-update@0.18.11/node_modules/dsh-plugin-update/dist/panel.js
|
|
4402
|
+
function normalizePanelTheme(value) {
|
|
4403
|
+
return value === "archive" ? "archive" : "default";
|
|
4404
|
+
}
|
|
4405
|
+
const THEME_TOKEN_VARS = {
|
|
4406
|
+
text: "--dsh-update-text",
|
|
4407
|
+
textMuted: "--dsh-update-text-muted",
|
|
4408
|
+
bg: "--dsh-update-bg",
|
|
4409
|
+
bgSoft: "--dsh-update-bg-soft",
|
|
4410
|
+
border: "--dsh-update-border",
|
|
4411
|
+
borderStrong: "--dsh-update-border-strong",
|
|
4412
|
+
buttonBg: "--dsh-update-button-bg",
|
|
4413
|
+
primary: "--dsh-update-primary",
|
|
4414
|
+
primaryDeep: "--dsh-update-primary-deep",
|
|
4415
|
+
focus: "--dsh-update-focus",
|
|
4416
|
+
okBg: "--dsh-update-ok-bg",
|
|
4417
|
+
okBorder: "--dsh-update-ok-border",
|
|
4418
|
+
okText: "--dsh-update-ok-text",
|
|
4419
|
+
warnBg: "--dsh-update-warn-bg",
|
|
4420
|
+
warnBorder: "--dsh-update-warn-border",
|
|
4421
|
+
warnText: "--dsh-update-warn-text",
|
|
4422
|
+
badBg: "--dsh-update-bad-bg",
|
|
4423
|
+
badBorder: "--dsh-update-bad-border",
|
|
4424
|
+
badText: "--dsh-update-bad-text",
|
|
4425
|
+
busyBg: "--dsh-update-busy-bg",
|
|
4426
|
+
busyBorder: "--dsh-update-busy-border",
|
|
4427
|
+
busyText: "--dsh-update-busy-text",
|
|
4428
|
+
newText: "--dsh-update-new-text",
|
|
4429
|
+
newOkText: "--dsh-update-new-ok-text",
|
|
4430
|
+
fontSans: "--dsh-update-font-sans",
|
|
4431
|
+
fontSerif: "--dsh-update-font-serif",
|
|
4432
|
+
fontMono: "--dsh-update-font-mono",
|
|
4433
|
+
shadow: "--dsh-update-shadow",
|
|
4434
|
+
radiusPanel: "--dsh-update-radius-panel",
|
|
4435
|
+
radiusButton: "--dsh-update-radius-button",
|
|
4436
|
+
radiusBadge: "--dsh-update-radius-badge",
|
|
4437
|
+
entryFontSize: "--dsh-update-entry-font-size",
|
|
4438
|
+
entryPadding: "--dsh-update-entry-padding",
|
|
4439
|
+
entryBorderRadius: "--dsh-update-entry-border-radius",
|
|
4440
|
+
entryScale: "--dsh-update-entry-scale",
|
|
4441
|
+
panelFontSize: "--dsh-update-panel-font-size",
|
|
4442
|
+
panelChapterFontSize: "--dsh-update-panel-chapter-font-size",
|
|
4443
|
+
panelBannerTitleFontSize: "--dsh-update-panel-banner-title-font-size",
|
|
4444
|
+
panelLogFontSize: "--dsh-update-panel-log-font-size",
|
|
4445
|
+
panelSmallFontSize: "--dsh-update-panel-small-font-size"
|
|
4446
|
+
};
|
|
4447
|
+
const THEME_TOKEN_COLOR_KEYS = /* @__PURE__ */ new Set([
|
|
4448
|
+
"text",
|
|
4449
|
+
"textMuted",
|
|
4450
|
+
"bg",
|
|
4451
|
+
"bgSoft",
|
|
4452
|
+
"border",
|
|
4453
|
+
"borderStrong",
|
|
4454
|
+
"buttonBg",
|
|
4455
|
+
"primary",
|
|
4456
|
+
"primaryDeep",
|
|
4457
|
+
"focus",
|
|
4458
|
+
"okBg",
|
|
4459
|
+
"okBorder",
|
|
4460
|
+
"okText",
|
|
4461
|
+
"warnBg",
|
|
4462
|
+
"warnBorder",
|
|
4463
|
+
"warnText",
|
|
4464
|
+
"badBg",
|
|
4465
|
+
"badBorder",
|
|
4466
|
+
"badText",
|
|
4467
|
+
"busyBg",
|
|
4468
|
+
"busyBorder",
|
|
4469
|
+
"busyText",
|
|
4470
|
+
"newText",
|
|
4471
|
+
"newOkText"
|
|
4472
|
+
]);
|
|
4473
|
+
function themeTokensError(raw) {
|
|
4474
|
+
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)})`);
|
|
4475
|
+
}
|
|
4476
|
+
function isSafeThemeCssValue(value) {
|
|
4477
|
+
const v = value.trim();
|
|
4478
|
+
if (!v || v.length > 200) return false;
|
|
4479
|
+
if (/[;"'<>\`{}!&]/.test(v)) return false;
|
|
4480
|
+
if (/url\s*\(/i.test(v)) return false;
|
|
4481
|
+
if (/expression\s*\(/i.test(v)) return false;
|
|
4482
|
+
if (/javascript\s*:/i.test(v)) return false;
|
|
4483
|
+
return true;
|
|
4484
|
+
}
|
|
4485
|
+
function isThemeColorValue(value) {
|
|
4486
|
+
const v = value.trim();
|
|
4487
|
+
if (!v || v.length > 100) return false;
|
|
4488
|
+
return /^(?:#[0-9a-fA-F]{3}|#[0-9a-fA-F]{6}|#[0-9a-fA-F]{8}|[a-zA-Z]+)$/.test(v);
|
|
4489
|
+
}
|
|
4490
|
+
function themeTokensStyleFor(tokens) {
|
|
4491
|
+
if (tokens === void 0 || tokens === null) return "";
|
|
4492
|
+
if (typeof tokens !== "object" || Array.isArray(tokens)) throw themeTokensError(tokens);
|
|
4493
|
+
for (const key of Object.keys(tokens)) if (!Object.prototype.hasOwnProperty.call(THEME_TOKEN_VARS, key)) throw themeTokensError(tokens);
|
|
4494
|
+
const parts = [];
|
|
4495
|
+
for (const key of Object.keys(THEME_TOKEN_VARS)) {
|
|
4496
|
+
const value = tokens[key];
|
|
4497
|
+
if (value === void 0) continue;
|
|
4498
|
+
if (key === "entryScale") {
|
|
4499
|
+
if (typeof value !== "number" || !Number.isFinite(value) || value <= 0) throw themeTokensError(tokens);
|
|
4500
|
+
parts.push(THEME_TOKEN_VARS[key] + ":" + String(value));
|
|
4501
|
+
continue;
|
|
4502
|
+
}
|
|
4503
|
+
if (typeof value !== "string") throw themeTokensError(tokens);
|
|
4504
|
+
const text = value.trim();
|
|
4505
|
+
if (THEME_TOKEN_COLOR_KEYS.has(key)) {
|
|
4506
|
+
if (!isThemeColorValue(text)) throw themeTokensError(tokens);
|
|
4507
|
+
} else if (!isSafeThemeCssValue(text)) throw themeTokensError(tokens);
|
|
4508
|
+
parts.push(THEME_TOKEN_VARS[key] + ":" + text);
|
|
4509
|
+
}
|
|
4510
|
+
return parts.join(";");
|
|
4511
|
+
}
|
|
4377
4512
|
const PANEL_SKIPPED_MAX = 50;
|
|
4378
4513
|
function panelSkipKey(pluginId) {
|
|
4379
4514
|
return `dsh-upd-skipped/${String(pluginId)}`;
|
|
@@ -5067,6 +5202,63 @@ ${note}${blocks.join("\n")}
|
|
|
5067
5202
|
const at = spec.lastIndexOf("@");
|
|
5068
5203
|
return (at > 0 ? spec.slice(at + 1).trim() : "") || null;
|
|
5069
5204
|
}
|
|
5205
|
+
function fallbackCauseFromDetail(detail, errorCode, pluginId) {
|
|
5206
|
+
try {
|
|
5207
|
+
const facts = interpretInstallCause({
|
|
5208
|
+
errorCode: typeof errorCode === "string" && errorCode ? errorCode : "install-failed",
|
|
5209
|
+
detail,
|
|
5210
|
+
targetPackageName: typeof pluginId === "string" ? pluginId : void 0
|
|
5211
|
+
});
|
|
5212
|
+
if (!facts || facts.kind !== "minimum-release-age" || facts.blame !== "target") return null;
|
|
5213
|
+
const targetVersion = typeof facts.packageVersion === "string" && facts.packageVersion.trim() ? facts.packageVersion.trim() : null;
|
|
5214
|
+
if (!targetVersion) return null;
|
|
5215
|
+
let windowMs = null;
|
|
5216
|
+
let windowSource = "unknown";
|
|
5217
|
+
if (typeof facts.windowMinutes === "number" && Number.isFinite(facts.windowMinutes) && facts.windowMinutes > 0) {
|
|
5218
|
+
windowMs = facts.windowMinutes * 6e4;
|
|
5219
|
+
windowSource = "message";
|
|
5220
|
+
} else if (typeof facts.cutoffMs === "number" && typeof facts.publishedAtMs === "number" && facts.cutoffMs > facts.publishedAtMs) windowMs = facts.cutoffMs - facts.publishedAtMs;
|
|
5221
|
+
return {
|
|
5222
|
+
kind: facts.kind,
|
|
5223
|
+
packageName: facts.packageName,
|
|
5224
|
+
targetVersion,
|
|
5225
|
+
windowMs,
|
|
5226
|
+
windowSource,
|
|
5227
|
+
publishedAtMs: typeof facts.publishedAtMs === "number" ? facts.publishedAtMs : null
|
|
5228
|
+
};
|
|
5229
|
+
} catch {
|
|
5230
|
+
return null;
|
|
5231
|
+
}
|
|
5232
|
+
}
|
|
5233
|
+
function fallbackCauseFromDiag(diag, detail, errorCode, preferredTargetVersion) {
|
|
5234
|
+
try {
|
|
5235
|
+
const d = diag && typeof diag === "object" && !Array.isArray(diag) ? diag : null;
|
|
5236
|
+
if (!d) return null;
|
|
5237
|
+
const dKind = typeof d["causeKind"] === "string" ? d["causeKind"].trim() : "";
|
|
5238
|
+
const dSpec = typeof d["causePackage"] === "string" ? d["causePackage"].trim() : "";
|
|
5239
|
+
const dTarget = typeof d["targetPackageName"] === "string" ? d["targetPackageName"].trim() : "";
|
|
5240
|
+
if (!dKind || !CAUSE_KINDS.includes(dKind) || !dSpec || !dTarget) return null;
|
|
5241
|
+
if (blameCausePackage(dSpec, dTarget) !== "target") return null;
|
|
5242
|
+
const timed = fallbackCauseFromDetail(detail, errorCode, dTarget);
|
|
5243
|
+
const preferred = typeof preferredTargetVersion === "string" ? preferredTargetVersion.trim() : "";
|
|
5244
|
+
const at = dSpec.lastIndexOf("@");
|
|
5245
|
+
const specVer = at > 0 ? dSpec.slice(at + 1).trim() : "";
|
|
5246
|
+
const targetVersion = preferred || timed?.targetVersion || specVer;
|
|
5247
|
+
if (!targetVersion) return null;
|
|
5248
|
+
return {
|
|
5249
|
+
kind: dKind,
|
|
5250
|
+
spec: dSpec,
|
|
5251
|
+
target: dTarget,
|
|
5252
|
+
packageName: at > 0 && dSpec.slice(0, at).trim() ? dSpec.slice(0, at).trim() : dTarget,
|
|
5253
|
+
targetVersion,
|
|
5254
|
+
windowMs: timed?.windowMs ?? null,
|
|
5255
|
+
windowSource: timed?.windowSource ?? "unknown",
|
|
5256
|
+
publishedAtMs: timed?.publishedAtMs ?? null
|
|
5257
|
+
};
|
|
5258
|
+
} catch {
|
|
5259
|
+
return null;
|
|
5260
|
+
}
|
|
5261
|
+
}
|
|
5070
5262
|
function formatLatchTime(atMs, lang) {
|
|
5071
5263
|
if (typeof atMs !== "number" || !Number.isFinite(atMs) || atMs <= 0) return null;
|
|
5072
5264
|
const raw = typeof lang === "string" ? lang.trim().replace(/_/g, "-") : "";
|
|
@@ -5296,7 +5488,7 @@ ${UPDATE_PANEL_ARCHIVE_CSS}` : UPDATE_PANEL_CSS}</style>
|
|
|
5296
5488
|
${body}`;
|
|
5297
5489
|
}
|
|
5298
5490
|
//#endregion
|
|
5299
|
-
//#region ../../node_modules/.pnpm/dsh-plugin-update@0.18.
|
|
5491
|
+
//#region ../../node_modules/.pnpm/dsh-plugin-update@0.18.11/node_modules/dsh-plugin-update/dist/entry.js
|
|
5300
5492
|
const UPDATE_ENTRY_CSS = [
|
|
5301
5493
|
".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)}",
|
|
5302
5494
|
".dsh-upd-entry-btn{font:inherit;border:1px solid var(--dsh-update-border,#d1d5db);border-radius:var(--dsh-update-entry-border-radius,6px);",
|
|
@@ -5410,7 +5602,7 @@ ${body}`;
|
|
|
5410
5602
|
}
|
|
5411
5603
|
}
|
|
5412
5604
|
//#endregion
|
|
5413
|
-
//#region ../../node_modules/.pnpm/dsh-plugin-update@0.18.
|
|
5605
|
+
//#region ../../node_modules/.pnpm/dsh-plugin-update@0.18.11/node_modules/dsh-plugin-update/dist/panel-batch.js
|
|
5414
5606
|
const BATCH_PANEL_POLL = {
|
|
5415
5607
|
defaultMs: 1500,
|
|
5416
5608
|
minMs: 250
|
|
@@ -5427,7 +5619,7 @@ ${body}`;
|
|
|
5427
5619
|
prefsSave: p + ".batchPrefsSave"
|
|
5428
5620
|
};
|
|
5429
5621
|
}
|
|
5430
|
-
function batchLedgerCounts(rows, inventory, session) {
|
|
5622
|
+
function batchLedgerCounts(rows, inventory, session, compliantDone) {
|
|
5431
5623
|
const counts = {
|
|
5432
5624
|
updatable: 0,
|
|
5433
5625
|
installing: 0,
|
|
@@ -5439,9 +5631,15 @@ ${body}`;
|
|
|
5439
5631
|
};
|
|
5440
5632
|
for (const row of rows) {
|
|
5441
5633
|
const phase = asBatchPhase(row.phase);
|
|
5442
|
-
|
|
5443
|
-
|
|
5444
|
-
|
|
5634
|
+
const doneRestart = phase === "failed" ? compliantDone?.get(row.key) : void 0;
|
|
5635
|
+
if (doneRestart !== void 0) {
|
|
5636
|
+
if (doneRestart) counts.restart += 1;
|
|
5637
|
+
else counts.settled += 1;
|
|
5638
|
+
} else if (isQueueBusyRow(row)) counts.updatable += 1;
|
|
5639
|
+
else if (phase === "failed") {
|
|
5640
|
+
if (row.error === "pending-restart") counts.restart += 1;
|
|
5641
|
+
else counts.failed += 1;
|
|
5642
|
+
} else if (phase === "installing") counts.installing += 1;
|
|
5445
5643
|
else if (phase === "ready") counts.updatable += 1;
|
|
5446
5644
|
else if (phase === "pending") counts[isInUnfinishedRound(session, row.key) ? "pending" : ledgerKnowledgeBucket(knowledgeEntryOf(inventory, row.key))] += 1;
|
|
5447
5645
|
else if (phase === "checking") counts.pending += 1;
|
|
@@ -5663,7 +5861,14 @@ ${body}`;
|
|
|
5663
5861
|
const expandedKey = typeof input.expandedKey === "string" && input.expandedKey ? input.expandedKey : null;
|
|
5664
5862
|
const lastError = typeof input.lastError === "string" && input.lastError ? input.lastError : null;
|
|
5665
5863
|
const loaded = input.loaded === void 0 ? rows.length > 0 : input.loaded === true;
|
|
5666
|
-
const
|
|
5864
|
+
const compliantFacts = /* @__PURE__ */ new Map();
|
|
5865
|
+
for (const row of rows) {
|
|
5866
|
+
const fact = compliantInstalledOf(row);
|
|
5867
|
+
if (fact) compliantFacts.set(row.key, fact);
|
|
5868
|
+
}
|
|
5869
|
+
const compliantDone = /* @__PURE__ */ new Map();
|
|
5870
|
+
for (const [key, fact] of compliantFacts) compliantDone.set(key, fact.needsRestart);
|
|
5871
|
+
const counts = batchLedgerCounts(rows, input.inventory, input.session, compliantDone);
|
|
5667
5872
|
const installing = counts.installing > 0;
|
|
5668
5873
|
const macroBusy = input.inFlight === true || installing;
|
|
5669
5874
|
const total = rows.length;
|
|
@@ -5686,8 +5891,32 @@ ${body}`;
|
|
|
5686
5891
|
lang,
|
|
5687
5892
|
knowledge: null,
|
|
5688
5893
|
inRound: false,
|
|
5689
|
-
worldLatest: null
|
|
5894
|
+
worldLatest: null,
|
|
5895
|
+
fallbackCandidate: null,
|
|
5896
|
+
fallbackBusy: false,
|
|
5897
|
+
fallbackWaiting: false
|
|
5690
5898
|
};
|
|
5899
|
+
const fallbackOffers = input.fallbackOffers && typeof input.fallbackOffers === "object" ? input.fallbackOffers : {};
|
|
5900
|
+
const fallbackBusyKey = typeof input.fallbackBusyKey === "string" && input.fallbackBusyKey ? input.fallbackBusyKey : null;
|
|
5901
|
+
const compliantInput = isObject$2(input.compliant) ? input.compliant : null;
|
|
5902
|
+
const compliantWaitInput = compliantInput && isObject$2(compliantInput["wait"]) ? compliantInput["wait"] : null;
|
|
5903
|
+
const waitKeys = [];
|
|
5904
|
+
if (compliantWaitInput && Array.isArray(compliantWaitInput["keys"])) {
|
|
5905
|
+
for (const key of compliantWaitInput["keys"]) if (typeof key === "string" && key) waitKeys.push(key);
|
|
5906
|
+
}
|
|
5907
|
+
const waitUnlockAtMs = compliantWaitInput && typeof compliantWaitInput["unlockAtMs"] === "number" ? compliantWaitInput["unlockAtMs"] : null;
|
|
5908
|
+
const compliantUnlocksInput = compliantInput && isObject$2(compliantInput["unlocks"]) ? compliantInput["unlocks"] : null;
|
|
5909
|
+
const compliant = compliantInput && typeof compliantInput["gated"] === "number" ? {
|
|
5910
|
+
gated: compliantInput["gated"],
|
|
5911
|
+
confirmList: typeof compliantInput["confirmList"] === "string" && compliantInput["confirmList"] ? compliantInput["confirmList"] : null,
|
|
5912
|
+
confirmCount: typeof compliantInput["confirmCount"] === "number" ? compliantInput["confirmCount"] : 0,
|
|
5913
|
+
busy: compliantInput["busy"] === true,
|
|
5914
|
+
wait: waitKeys.length > 0 ? {
|
|
5915
|
+
keys: waitKeys,
|
|
5916
|
+
unlockAtMs: waitUnlockAtMs
|
|
5917
|
+
} : null,
|
|
5918
|
+
unlocks: compliantUnlocksInput ? compliantUnlocksInput : null
|
|
5919
|
+
} : null;
|
|
5691
5920
|
const parts = [];
|
|
5692
5921
|
parts.push("<div class=\"dsh-upd-batch-head\">");
|
|
5693
5922
|
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>");
|
|
@@ -5699,7 +5928,7 @@ ${body}`;
|
|
|
5699
5928
|
parts.push("</div>");
|
|
5700
5929
|
const summary = loaded ? batchSummaryText(counts, rows, total, installing, lastError !== null, lang) : batchText("batch.banner.loading", lang);
|
|
5701
5930
|
parts.push("<div class=\"dsh-upd-batch-sum\" role=\"status\" aria-live=\"polite\">" + escapeHtml$2(summary) + "</div>");
|
|
5702
|
-
parts.push(bannersHTML(rows, titles, lastError, lang));
|
|
5931
|
+
parts.push(bannersHTML(rows, titles, lastError, lang, compliant, compliantFacts));
|
|
5703
5932
|
const session = isObject$2(input.session) ? input.session : null;
|
|
5704
5933
|
const unfinished = unfinishedCount(rows, session ?? void 0);
|
|
5705
5934
|
const showControls = total > 0 && hasUnfinishedRows(rows, session ?? void 0);
|
|
@@ -5712,6 +5941,10 @@ ${body}`;
|
|
|
5712
5941
|
const expanded = row.key === expandedKey;
|
|
5713
5942
|
const inRound = isInUnfinishedRound(input.session, row.key);
|
|
5714
5943
|
const knowledge = !inRound ? knowledgeEntryOf(input.inventory, row.key) : null;
|
|
5944
|
+
const offerRaw = fallbackOffers[row.key];
|
|
5945
|
+
const offerCand = isObject$2(offerRaw) && typeof offerRaw["candidate"] === "string" && offerRaw["candidate"].trim() ? offerRaw["candidate"].trim() : null;
|
|
5946
|
+
const offerTarget = isObject$2(offerRaw) && typeof offerRaw["targetVersion"] === "string" ? offerRaw["targetVersion"] : null;
|
|
5947
|
+
const latest = latestVersionOf(row);
|
|
5715
5948
|
parts.push(rowSetHTML(row, {
|
|
5716
5949
|
...ctx,
|
|
5717
5950
|
expanded,
|
|
@@ -5721,7 +5954,10 @@ ${body}`;
|
|
|
5721
5954
|
lang,
|
|
5722
5955
|
knowledge,
|
|
5723
5956
|
inRound,
|
|
5724
|
-
worldLatest: worldUpdateVersion(row, knowledge, sessionUpdatedAtOf(input.session, row.key))
|
|
5957
|
+
worldLatest: worldUpdateVersion(row, knowledge, sessionUpdatedAtOf(input.session, row.key)),
|
|
5958
|
+
fallbackCandidate: offerCand && offerTarget === latest ? offerCand : null,
|
|
5959
|
+
fallbackBusy: fallbackBusyKey === row.key,
|
|
5960
|
+
fallbackWaiting: waitKeys.includes(row.key)
|
|
5725
5961
|
}));
|
|
5726
5962
|
}
|
|
5727
5963
|
parts.push("</div>");
|
|
@@ -5752,12 +5988,18 @@ ${body}`;
|
|
|
5752
5988
|
if (target !== null) {
|
|
5753
5989
|
const rawSkipped = skippedVersions[target.key];
|
|
5754
5990
|
const skippedForDialog = typeof rawSkipped === "string" && rawSkipped ? rawSkipped : null;
|
|
5991
|
+
const offerRaw = fallbackOffers[target.key];
|
|
5992
|
+
const offerCand = isObject$2(offerRaw) && typeof offerRaw["candidate"] === "string" && offerRaw["candidate"].trim() ? offerRaw["candidate"].trim() : null;
|
|
5993
|
+
const offerTarget = isObject$2(offerRaw) && typeof offerRaw["targetVersion"] === "string" ? offerRaw["targetVersion"] : null;
|
|
5755
5994
|
detailDialog = detailDialogHTML(target, {
|
|
5756
5995
|
...ctx,
|
|
5757
5996
|
expanded: true,
|
|
5758
5997
|
skipped: skippedForDialog,
|
|
5759
5998
|
notice: target.key === detailNoticeKey ? notice : null,
|
|
5760
|
-
changelogMarkdown: typeof changelogs[target.key] === "string" ? changelogs[target.key] : null
|
|
5999
|
+
changelogMarkdown: typeof changelogs[target.key] === "string" ? changelogs[target.key] : null,
|
|
6000
|
+
fallbackCandidate: offerCand && offerTarget === latestVersionOf(target) ? offerCand : null,
|
|
6001
|
+
fallbackBusy: fallbackBusyKey === target.key,
|
|
6002
|
+
fallbackWaiting: waitKeys.includes(target.key)
|
|
5761
6003
|
});
|
|
5762
6004
|
}
|
|
5763
6005
|
}
|
|
@@ -5804,8 +6046,33 @@ ${body}`;
|
|
|
5804
6046
|
tone: "ink"
|
|
5805
6047
|
};
|
|
5806
6048
|
}
|
|
5807
|
-
function bannersHTML(rows, titles, lastError, lang) {
|
|
6049
|
+
function bannersHTML(rows, titles, lastError, lang, compliant = null, facts) {
|
|
5808
6050
|
const l = langOf(lang);
|
|
6051
|
+
const unlocks = compliant?.unlocks ?? null;
|
|
6052
|
+
const done = new Map(facts ?? []);
|
|
6053
|
+
if (!facts) for (const row of rows) {
|
|
6054
|
+
const fact = compliantInstalledOf(row);
|
|
6055
|
+
if (fact) done.set(row.key, fact);
|
|
6056
|
+
}
|
|
6057
|
+
const doneLineOf = (row, fact) => {
|
|
6058
|
+
const raw = unlocks && typeof unlocks[row.key] === "number" ? unlocks[row.key] : null;
|
|
6059
|
+
const time = raw !== null ? formatUnlockAt(raw, l) : null;
|
|
6060
|
+
const vars = {
|
|
6061
|
+
title: titleOf(row, titles),
|
|
6062
|
+
version: fact.version,
|
|
6063
|
+
target: fact.target
|
|
6064
|
+
};
|
|
6065
|
+
return time ? escapeHtml$2(batchText("batch.banner.compliant-done-gated", l, {
|
|
6066
|
+
...vars,
|
|
6067
|
+
time
|
|
6068
|
+
})) : escapeHtml$2(batchText("batch.banner.compliant-done", l, vars));
|
|
6069
|
+
};
|
|
6070
|
+
const gatedCandidates = rows.filter((row) => batchFallbackCauseOf(row) !== null && singleFallbackPhoneOf(row) !== null && !done.has(row.key));
|
|
6071
|
+
const gated = typeof compliant?.gated === "number" ? compliant.gated : gatedCandidates.length;
|
|
6072
|
+
const confirmList = typeof compliant?.confirmList === "string" && compliant.confirmList ? compliant.confirmList : null;
|
|
6073
|
+
const confirmCount = typeof compliant?.confirmCount === "number" ? compliant.confirmCount : 0;
|
|
6074
|
+
const compliantBusy = compliant?.busy === true;
|
|
6075
|
+
const waitKeys = compliant?.wait && Array.isArray(compliant.wait.keys) ? compliant.wait.keys : [];
|
|
5809
6076
|
const parts = [];
|
|
5810
6077
|
if (lastError) {
|
|
5811
6078
|
const copy = failureCopy(lastError, l);
|
|
@@ -5817,7 +6084,8 @@ ${body}`;
|
|
|
5817
6084
|
})) + "</strong></div></div>");
|
|
5818
6085
|
if (act) parts.push("<div class=\"dsh-upd-banner-sub\">" + escapeHtml$2(act) + "</div>");
|
|
5819
6086
|
}
|
|
5820
|
-
const
|
|
6087
|
+
const pendingRestartRow = (row) => asBatchPhase(row.phase) === "failed" && row.error === "pending-restart";
|
|
6088
|
+
const failed = batchFailedRows(rows);
|
|
5821
6089
|
if (failed.length > 0) {
|
|
5822
6090
|
const lines = failed.map((row) => {
|
|
5823
6091
|
const code = row.error || "install-failed";
|
|
@@ -5825,10 +6093,26 @@ ${body}`;
|
|
|
5825
6093
|
return "<div>" + escapeHtml$2(titleOf(row, titles)) + ":<code>" + escapeHtml$2(code) + "</code> " + escapeHtml$2(copy?.zh ?? failureCopy("unknown", l)?.zh ?? "") + "</div>";
|
|
5826
6094
|
}).join("");
|
|
5827
6095
|
const failedAct = batchText("batch.banner.failed-action", l);
|
|
5828
|
-
|
|
6096
|
+
const manualAbsent = batchFailedManualText(failed, l, titles).commands === 0;
|
|
6097
|
+
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 class=\"dsh-upd-browline\"><span class=\"dsh-upd-bcopy\"><button type=\"button\" data-act=\"copy-all-diag\">" + escapeHtml$2(batchText("batch.row-action.copy-diag", l)) + "</button><button type=\"button\" data-act=\"copy-all-manual\"" + (manualAbsent ? " disabled title=\"" + escapeHtml$2(batchText("panel.manual.absent", l)) + "\"" : "") + ">" + escapeHtml$2(batchText("batch.row-action.copy-manual", l)) + "</button></span></div></div>");
|
|
5829
6098
|
if (failedAct) parts.push("<div class=\"dsh-upd-banner-sub\">" + escapeHtml$2(failedAct) + "</div>");
|
|
5830
6099
|
}
|
|
5831
|
-
|
|
6100
|
+
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>");
|
|
6101
|
+
if (waitKeys.length > 0) {
|
|
6102
|
+
const rawUnlock = compliant?.wait ? compliant.wait.unlockAtMs : null;
|
|
6103
|
+
const unlockAtMs = typeof rawUnlock === "number" ? rawUnlock : null;
|
|
6104
|
+
const time = unlockAtMs !== null ? formatUnlockAt(unlockAtMs, l) : null;
|
|
6105
|
+
const waitTitles = rows.filter((row) => waitKeys.includes(row.key)).map((row) => titleOf(row, titles)).join("、");
|
|
6106
|
+
parts.push("<div class=\"dsh-upd-banner\" data-kind=\"update\" role=\"status\"><div><strong>" + escapeHtml$2(time ? batchText("batch.banner.gated-wait", l, {
|
|
6107
|
+
n: String(waitKeys.length),
|
|
6108
|
+
time
|
|
6109
|
+
}) : 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>");
|
|
6110
|
+
} 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>");
|
|
6111
|
+
if (done.size > 0) {
|
|
6112
|
+
const lines = rows.filter((row) => done.has(row.key)).map((row) => "<div>" + doneLineOf(row, done.get(row.key)) + "</div>").join("");
|
|
6113
|
+
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>");
|
|
6114
|
+
}
|
|
6115
|
+
const restart = rows.filter((row) => row.restartRequired === true || pendingRestartRow(row) || done.get(row.key)?.needsRestart === true);
|
|
5832
6116
|
if (restart.length > 0) {
|
|
5833
6117
|
const restartAct = batchText("batch.banner.restart-action", l);
|
|
5834
6118
|
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>");
|
|
@@ -5836,14 +6120,29 @@ ${body}`;
|
|
|
5836
6120
|
}
|
|
5837
6121
|
return parts.join("");
|
|
5838
6122
|
}
|
|
6123
|
+
function rowFallbackButtonHTML(row, ctx) {
|
|
6124
|
+
try {
|
|
6125
|
+
if (ctx.fallbackWaiting) return "";
|
|
6126
|
+
const keyAttr = escapeHtml$2(row.key);
|
|
6127
|
+
const busy = ctx.fallbackBusy || ctx.inFlight ? " disabled aria-busy=\"true\"" : "";
|
|
6128
|
+
const off = ctx.inFlight && !ctx.fallbackBusy ? " disabled" : "";
|
|
6129
|
+
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>";
|
|
6130
|
+
if (singleFallbackPhoneOf(row) === null) return "";
|
|
6131
|
+
if (!batchFallbackCauseOf(row)) return "";
|
|
6132
|
+
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>";
|
|
6133
|
+
} catch {
|
|
6134
|
+
return "";
|
|
6135
|
+
}
|
|
6136
|
+
}
|
|
5839
6137
|
function rowSetHTML(row, ctx) {
|
|
5840
6138
|
const phase = asBatchPhase(row.phase);
|
|
5841
6139
|
const keyAttr = escapeHtml$2(row.key);
|
|
5842
6140
|
const skipped = ctx.skipped;
|
|
5843
6141
|
const queued = isQueuedRow(row);
|
|
5844
6142
|
const position = queued ? queuePositionOf(row) : null;
|
|
6143
|
+
const rowDone = phase === "failed" && !queued ? compliantInstalledOf(row) : null;
|
|
5845
6144
|
const versionHTML = batchRowVersionHTML(row, ctx.knowledge, ctx.lang);
|
|
5846
|
-
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);
|
|
6145
|
+
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);
|
|
5847
6146
|
const actions = [];
|
|
5848
6147
|
const off = ctx.inFlight ? " disabled" : "";
|
|
5849
6148
|
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>");
|
|
@@ -5851,10 +6150,19 @@ ${body}`;
|
|
|
5851
6150
|
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>");
|
|
5852
6151
|
} 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>");
|
|
5853
6152
|
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>");
|
|
5854
|
-
else if (phase === "failed")
|
|
6153
|
+
else if (phase === "failed") {
|
|
6154
|
+
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>");
|
|
6155
|
+
if (!queued && rowDone === null) actions.push(rowFallbackButtonHTML(row, ctx));
|
|
6156
|
+
}
|
|
5855
6157
|
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>");
|
|
5856
6158
|
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>");
|
|
5857
|
-
const failLine = phase === "failed" && !queued ? (() => {
|
|
6159
|
+
const failLine = phase === "failed" && !queued ? rowDone !== null ? (() => {
|
|
6160
|
+
const vars = {
|
|
6161
|
+
version: rowDone.version,
|
|
6162
|
+
target: rowDone.target
|
|
6163
|
+
};
|
|
6164
|
+
return "<span class=\"dsh-upd-bfail dsh-upd-bdone\">" + escapeHtml$2(batchText("batch.row.compliant-done", ctx.lang, vars)) + "</span>";
|
|
6165
|
+
})() : (() => {
|
|
5858
6166
|
const failCode = row.error || "install-failed";
|
|
5859
6167
|
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 ?? "";
|
|
5860
6168
|
const escaped = escapeHtml$2(batchText("batch.row.error-label", ctx.lang, {
|
|
@@ -5864,7 +6172,7 @@ ${body}`;
|
|
|
5864
6172
|
const codeEsc = escapeHtml$2(failCode);
|
|
5865
6173
|
return "<span class=\"dsh-upd-bfail\">" + (escaped.includes(codeEsc) ? escaped.replace(codeEsc, "<code>" + codeEsc + "</code>") : escaped) + "</span>";
|
|
5866
6174
|
})() : "";
|
|
5867
|
-
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>";
|
|
6175
|
+
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>";
|
|
5868
6176
|
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>";
|
|
5869
6177
|
}
|
|
5870
6178
|
function detailActionsHTML(row, ctx) {
|
|
@@ -5877,8 +6185,13 @@ ${body}`;
|
|
|
5877
6185
|
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>");
|
|
5878
6186
|
else if (queued) {
|
|
5879
6187
|
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>");
|
|
5880
|
-
} else if (phase === "failed")
|
|
5881
|
-
|
|
6188
|
+
} else if (phase === "failed") {
|
|
6189
|
+
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>");
|
|
6190
|
+
if (!queued) {
|
|
6191
|
+
const fallback = rowFallbackButtonHTML(row, ctx);
|
|
6192
|
+
if (fallback) buttons.push(fallback);
|
|
6193
|
+
}
|
|
6194
|
+
} 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>");
|
|
5882
6195
|
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>");
|
|
5883
6196
|
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>");
|
|
5884
6197
|
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>");
|
|
@@ -5920,7 +6233,9 @@ ${body}`;
|
|
|
5920
6233
|
if (at < 0) return withBar + footer;
|
|
5921
6234
|
return withBar.slice(0, at) + footer + withBar.slice(at);
|
|
5922
6235
|
}
|
|
5923
|
-
function dotToneOf(row, phase, skipped, queued, worldLatest = null) {
|
|
6236
|
+
function dotToneOf(row, phase, skipped, queued, worldLatest = null, compliantRestart = null) {
|
|
6237
|
+
if (compliantRestart === true) return "warn";
|
|
6238
|
+
if (compliantRestart === false) return "ok";
|
|
5924
6239
|
if (phase === "failed" && !queued) return "bad";
|
|
5925
6240
|
if (phase === "installing" || phase === "checking") return "busy";
|
|
5926
6241
|
if (queued) return "warn";
|
|
@@ -5960,6 +6275,8 @@ ${body}`;
|
|
|
5960
6275
|
".dsh-upd-bver-new-ok{color:var(--dsh-update-new-ok-text,#047857);font-weight:700}",
|
|
5961
6276
|
".dsh-upd-bstat{font-size:var(--dsh-update-panel-small-font-size,12.5px);opacity:.9;min-width:0;overflow-wrap:anywhere}",
|
|
5962
6277
|
".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)}",
|
|
6278
|
+
"/* #156 finishing fact: ledger phase failed but the newest installable build did get installed — green, not red. */",
|
|
6279
|
+
".dsh-upd-bdone{color:var(--dsh-update-ok-border,#059669)}",
|
|
5963
6280
|
".dsh-upd-batch{--dsh-update-new-text:#dc2626}",
|
|
5964
6281
|
".dsh-upd-batch{--dsh-update-new-ok-text:#047857}",
|
|
5965
6282
|
"@media (prefers-color-scheme: dark){.dsh-upd-batch{--dsh-update-new-text:#f87171}}",
|
|
@@ -5970,6 +6287,8 @@ ${body}`;
|
|
|
5970
6287
|
".dsh-upd-browline{display:flex;align-items:center;gap:10px;flex-wrap:wrap}",
|
|
5971
6288
|
".dsh-upd-browline>.dsh-upd-blist{flex:1 1 auto;min-width:0;text-align:left;margin:0}",
|
|
5972
6289
|
".dsh-upd-browline>button{flex:none;margin:0;margin-left:auto}",
|
|
6290
|
+
".dsh-upd-browline>.dsh-upd-bcopy{display:inline-flex;align-items:center;gap:10px;flex:none;margin-left:auto}",
|
|
6291
|
+
".dsh-upd-browline>.dsh-upd-bcopy>button{flex:none;margin:0}",
|
|
5973
6292
|
".dsh-upd-batch-ledger{margin:8px 0 0;font-size:var(--dsh-update-panel-log-font-size,13px);opacity:.85}",
|
|
5974
6293
|
".dsh-upd-batch-more{margin-top:6px}",
|
|
5975
6294
|
".dsh-upd-batch-more button{font-size:12px}",
|
|
@@ -6060,17 +6379,100 @@ ${body}`;
|
|
|
6060
6379
|
for (const entry of queue.waiting) if (entry && typeof entry.requestId === "string" && entry.requestId) return entry.requestId;
|
|
6061
6380
|
return null;
|
|
6062
6381
|
}
|
|
6063
|
-
function singleCheckPhoneOf(row) {
|
|
6064
|
-
const phones = isObject$2(row.phoneNames) ? row.phoneNames : null;
|
|
6065
|
-
if (!phones) return null;
|
|
6066
|
-
const check = phones["updateCheck"];
|
|
6067
|
-
return typeof check === "string" && check ? check : null;
|
|
6382
|
+
function singleCheckPhoneOf(row) {
|
|
6383
|
+
const phones = isObject$2(row.phoneNames) ? row.phoneNames : null;
|
|
6384
|
+
if (!phones) return null;
|
|
6385
|
+
const check = phones["updateCheck"];
|
|
6386
|
+
return typeof check === "string" && check ? check : null;
|
|
6387
|
+
}
|
|
6388
|
+
function cancelQueuePhoneOf(row) {
|
|
6389
|
+
const phones = isObject$2(row.phoneNames) ? row.phoneNames : null;
|
|
6390
|
+
if (!phones) return null;
|
|
6391
|
+
const install = phones["updateInstall"];
|
|
6392
|
+
return typeof install === "string" && install ? install : null;
|
|
6393
|
+
}
|
|
6394
|
+
function singleFallbackPhoneOf(row) {
|
|
6395
|
+
const phones = isObject$2(row.phoneNames) ? row.phoneNames : null;
|
|
6396
|
+
if (!phones) return null;
|
|
6397
|
+
const name = phones["updateCheckFallback"];
|
|
6398
|
+
return typeof name === "string" && name ? name : null;
|
|
6399
|
+
}
|
|
6400
|
+
function singleInstallPhoneOf(row) {
|
|
6401
|
+
const phones = isObject$2(row.phoneNames) ? row.phoneNames : null;
|
|
6402
|
+
if (!phones) return null;
|
|
6403
|
+
const name = phones["updateInstall"];
|
|
6404
|
+
return typeof name === "string" && name ? name : null;
|
|
6405
|
+
}
|
|
6406
|
+
function fallbackOutcomeOf(reply) {
|
|
6407
|
+
if (!isObject$2(reply) || reply["ok"] === false) return {
|
|
6408
|
+
kind: "",
|
|
6409
|
+
candidate: "",
|
|
6410
|
+
checkId: "",
|
|
6411
|
+
unlockAtMs: null
|
|
6412
|
+
};
|
|
6413
|
+
const snap = isObject$2(reply["snapshot"]) ? reply["snapshot"] : null;
|
|
6414
|
+
const verdict = snap && isObject$2(snap["verdict"]) ? snap["verdict"] : null;
|
|
6415
|
+
const kind = verdict && typeof verdict["kind"] === "string" ? verdict["kind"] : "";
|
|
6416
|
+
const version = verdict && typeof verdict["version"] === "string" ? verdict["version"].trim() : "";
|
|
6417
|
+
const snapCandidate = snap && typeof snap["candidate"] === "string" ? snap["candidate"].trim() : "";
|
|
6418
|
+
const rec = isObject$2(reply["receipt"]) ? reply["receipt"] : null;
|
|
6419
|
+
const checkId = rec && typeof rec["checkId"] === "string" ? rec["checkId"] : "";
|
|
6420
|
+
const unlockAtMs = verdict && typeof verdict["unlockAtMs"] === "number" ? verdict["unlockAtMs"] : null;
|
|
6421
|
+
const candidate = snapCandidate || (kind === "ok-now" ? version : "");
|
|
6422
|
+
const usable = (kind === "downgrade-available" || kind === "ok-now") && candidate !== "" && checkId !== "";
|
|
6423
|
+
return {
|
|
6424
|
+
kind,
|
|
6425
|
+
candidate: usable ? candidate : "",
|
|
6426
|
+
checkId: usable ? checkId : "",
|
|
6427
|
+
unlockAtMs
|
|
6428
|
+
};
|
|
6429
|
+
}
|
|
6430
|
+
function batchFallbackCauseOf(row) {
|
|
6431
|
+
try {
|
|
6432
|
+
if (asBatchPhase(row.phase) !== "failed") return null;
|
|
6433
|
+
const fail = jobFailureOf(row);
|
|
6434
|
+
if (!fail) return null;
|
|
6435
|
+
const rowDiag = row.diag;
|
|
6436
|
+
const cause = fallbackCauseFromDiag(rowDiag, fail.detail, fail.code, latestVersionOf(row)) ?? fallbackCauseFromDetail(fail.detail, fail.code, pluginIdOf(row));
|
|
6437
|
+
if (!cause) return null;
|
|
6438
|
+
if (cause.targetVersion !== latestVersionOf(row)) return null;
|
|
6439
|
+
return cause;
|
|
6440
|
+
} catch {
|
|
6441
|
+
return null;
|
|
6442
|
+
}
|
|
6443
|
+
}
|
|
6444
|
+
function compliantInstalledOf(row) {
|
|
6445
|
+
try {
|
|
6446
|
+
if (!isObject$2(row.snapshot)) return null;
|
|
6447
|
+
const snapshot = row.snapshot;
|
|
6448
|
+
if (!isObject$2(snapshot["job"])) return null;
|
|
6449
|
+
const job = snapshot["job"];
|
|
6450
|
+
const state = typeof job["state"] === "string" ? job["state"] : "";
|
|
6451
|
+
if (state !== "restart-required" && state !== "completed") return null;
|
|
6452
|
+
const version = typeof job["targetVersion"] === "string" ? job["targetVersion"].trim() : "";
|
|
6453
|
+
if (!version) return null;
|
|
6454
|
+
if ((typeof snapshot["installedVersion"] === "string" ? snapshot["installedVersion"].trim() : "") !== version) return null;
|
|
6455
|
+
const target = latestVersionOf(row);
|
|
6456
|
+
if (!target || target === version) return null;
|
|
6457
|
+
return {
|
|
6458
|
+
version,
|
|
6459
|
+
target,
|
|
6460
|
+
needsRestart: state === "restart-required"
|
|
6461
|
+
};
|
|
6462
|
+
} catch {
|
|
6463
|
+
return null;
|
|
6464
|
+
}
|
|
6068
6465
|
}
|
|
6069
|
-
function
|
|
6070
|
-
const
|
|
6071
|
-
|
|
6072
|
-
|
|
6073
|
-
|
|
6466
|
+
function batchFailedRows(rows) {
|
|
6467
|
+
const out = [];
|
|
6468
|
+
for (const row of rows) {
|
|
6469
|
+
if (asBatchPhase(row.phase) !== "failed") continue;
|
|
6470
|
+
if (isQueueBusyRow(row)) continue;
|
|
6471
|
+
if (row.error === "pending-restart") continue;
|
|
6472
|
+
if (compliantInstalledOf(row) !== null) continue;
|
|
6473
|
+
out.push(row);
|
|
6474
|
+
}
|
|
6475
|
+
return out;
|
|
6074
6476
|
}
|
|
6075
6477
|
function asBatchPhase(value) {
|
|
6076
6478
|
return typeof value === "string" && BATCH_PHASES.includes(value) ? value : "pending";
|
|
@@ -6184,6 +6586,27 @@ ${body}`;
|
|
|
6184
6586
|
lang: lang ?? "zh"
|
|
6185
6587
|
});
|
|
6186
6588
|
}
|
|
6589
|
+
function batchFailedDiagText(rows, lang) {
|
|
6590
|
+
return batchFailedRows(rows).map((row) => diagTextOf(row, lang)).join("\n\n");
|
|
6591
|
+
}
|
|
6592
|
+
function batchFailedManualText(rows, lang, titles = {}) {
|
|
6593
|
+
const l = langOf(lang);
|
|
6594
|
+
const lines = [];
|
|
6595
|
+
let commands = 0;
|
|
6596
|
+
for (const row of batchFailedRows(rows)) {
|
|
6597
|
+
const manual = typeof row.manual === "string" ? row.manual : "";
|
|
6598
|
+
if (manual) {
|
|
6599
|
+
lines.push(manual);
|
|
6600
|
+
commands += 1;
|
|
6601
|
+
continue;
|
|
6602
|
+
}
|
|
6603
|
+
lines.push("# " + titleOf(row, titles) + ":" + batchText("panel.manual.absent", l));
|
|
6604
|
+
}
|
|
6605
|
+
return {
|
|
6606
|
+
text: lines.join("\n"),
|
|
6607
|
+
commands
|
|
6608
|
+
};
|
|
6609
|
+
}
|
|
6187
6610
|
function isBusyReply(reply) {
|
|
6188
6611
|
if (!isObject$2(reply) || reply["ok"] === true) return false;
|
|
6189
6612
|
const kind = typeof reply["errorKind"] === "string" ? reply["errorKind"] : "";
|
|
@@ -6264,9 +6687,10 @@ ${body}`;
|
|
|
6264
6687
|
const titles = options.titles && typeof options.titles === "object" ? options.titles : {};
|
|
6265
6688
|
const onRestartRequested = options.onRestartRequested;
|
|
6266
6689
|
const onCloseRequested = typeof options.onCloseRequested === "function" ? options.onCloseRequested : null;
|
|
6267
|
-
const copyText = options.copyText ?? defaultCopyText$1;
|
|
6690
|
+
const copyText$1 = options.copyText ?? defaultCopyText$1;
|
|
6268
6691
|
const skipStores = /* @__PURE__ */ new Map();
|
|
6269
6692
|
const autoChangelogEnabled = options.autoChangelog !== false;
|
|
6693
|
+
const autoPlanEnabled = options.autoCompliant !== false;
|
|
6270
6694
|
const rowChangelog = /* @__PURE__ */ new Map();
|
|
6271
6695
|
const rowInflight = /* @__PURE__ */ new Set();
|
|
6272
6696
|
const rowFailedAt = /* @__PURE__ */ new Map();
|
|
@@ -6294,6 +6718,9 @@ ${body}`;
|
|
|
6294
6718
|
let lastCheckedAt = 0;
|
|
6295
6719
|
let autoCheckDone = false;
|
|
6296
6720
|
let autoResumeDone = false;
|
|
6721
|
+
const rowFallbackOffers = /* @__PURE__ */ new Map();
|
|
6722
|
+
let fallbackBusyKey = null;
|
|
6723
|
+
let batchCompliantKeys = [];
|
|
6297
6724
|
function changelogView() {
|
|
6298
6725
|
const out = {};
|
|
6299
6726
|
for (const row of rows) {
|
|
@@ -6435,6 +6862,13 @@ ${body}`;
|
|
|
6435
6862
|
let lastHTML = "";
|
|
6436
6863
|
function render() {
|
|
6437
6864
|
if (!mounted) return;
|
|
6865
|
+
const offers = {};
|
|
6866
|
+
for (const [k, v] of rowFallbackOffers) offers[k] = {
|
|
6867
|
+
candidate: v.candidate,
|
|
6868
|
+
targetVersion: v.targetVersion
|
|
6869
|
+
};
|
|
6870
|
+
const confirmKeys = batchCompliantKeys.filter((k) => rowFallbackOffers.has(k));
|
|
6871
|
+
const wait = waitingOf();
|
|
6438
6872
|
const nextHTML = renderBatchPanelHTML({
|
|
6439
6873
|
rows,
|
|
6440
6874
|
theme,
|
|
@@ -6453,13 +6887,163 @@ ${body}`;
|
|
|
6453
6887
|
session: lastSession,
|
|
6454
6888
|
inventory: lastInventory,
|
|
6455
6889
|
prefs: lastPrefs,
|
|
6456
|
-
lang: currentLang()
|
|
6890
|
+
lang: currentLang(),
|
|
6891
|
+
fallbackOffers: offers,
|
|
6892
|
+
fallbackBusyKey,
|
|
6893
|
+
compliant: {
|
|
6894
|
+
gated: rows.filter((row) => needsAutoResolve(row)).length,
|
|
6895
|
+
confirmList: confirmKeys.length > 0 ? compliantListText(confirmKeys) : null,
|
|
6896
|
+
confirmCount: confirmKeys.length,
|
|
6897
|
+
busy: inFlight,
|
|
6898
|
+
wait: wait.keys.length > 0 ? wait : null,
|
|
6899
|
+
unlocks: unlockTimesOf()
|
|
6900
|
+
}
|
|
6457
6901
|
});
|
|
6458
6902
|
if (nextHTML !== lastHTML) {
|
|
6459
6903
|
lastHTML = nextHTML;
|
|
6460
6904
|
setStableHTML(container, nextHTML);
|
|
6461
6905
|
}
|
|
6462
6906
|
}
|
|
6907
|
+
function pruneFallbackOffers() {
|
|
6908
|
+
try {
|
|
6909
|
+
for (const [k, v] of [...rowFallbackOffers]) {
|
|
6910
|
+
const row = rowOfKey(k);
|
|
6911
|
+
if (!row || asBatchPhase(row.phase) !== "failed" || v.targetVersion !== latestVersionOf(row)) rowFallbackOffers.delete(k);
|
|
6912
|
+
}
|
|
6913
|
+
if (batchCompliantKeys.length > 0) batchCompliantKeys = batchCompliantKeys.filter((k) => rowFallbackOffers.has(k));
|
|
6914
|
+
} catch {}
|
|
6915
|
+
}
|
|
6916
|
+
function compliantListText(keys) {
|
|
6917
|
+
const sep = currentLang() === "en" ? ", " : "、";
|
|
6918
|
+
return keys.map((k) => {
|
|
6919
|
+
const row = rowOfKey(k);
|
|
6920
|
+
const offer = rowFallbackOffers.get(k);
|
|
6921
|
+
return row && offer ? titleOf(row, titles) + " " + offer.candidate : "";
|
|
6922
|
+
}).filter((text) => text !== "").join(sep);
|
|
6923
|
+
}
|
|
6924
|
+
const gatedOutcomes = /* @__PURE__ */ new Map();
|
|
6925
|
+
let autoPlanSignature = "";
|
|
6926
|
+
let autoPlanRunning = false;
|
|
6927
|
+
function needsAutoResolve(row) {
|
|
6928
|
+
try {
|
|
6929
|
+
if (batchFallbackCauseOf(row) === null || singleFallbackPhoneOf(row) === null) return false;
|
|
6930
|
+
if (compliantInstalledOf(row) !== null) return false;
|
|
6931
|
+
if (rowFallbackOffers.has(row.key)) return false;
|
|
6932
|
+
const seen = gatedOutcomes.get(row.key);
|
|
6933
|
+
if (seen) {
|
|
6934
|
+
if (seen.kind === "installed") return false;
|
|
6935
|
+
if (seen.kind === "wait-until") {
|
|
6936
|
+
if (seen.unlockAtMs === null) return false;
|
|
6937
|
+
if (nowMs() < seen.unlockAtMs) return false;
|
|
6938
|
+
}
|
|
6939
|
+
}
|
|
6940
|
+
return true;
|
|
6941
|
+
} catch {
|
|
6942
|
+
return false;
|
|
6943
|
+
}
|
|
6944
|
+
}
|
|
6945
|
+
async function resolveGated(row) {
|
|
6946
|
+
const cause = batchFallbackCauseOf(row);
|
|
6947
|
+
const phoneName = singleFallbackPhoneOf(row);
|
|
6948
|
+
if (!cause || phoneName === null) return {
|
|
6949
|
+
kind: "",
|
|
6950
|
+
candidate: "",
|
|
6951
|
+
checkId: "",
|
|
6952
|
+
unlockAtMs: null
|
|
6953
|
+
};
|
|
6954
|
+
let reply = null;
|
|
6955
|
+
try {
|
|
6956
|
+
reply = await call(phoneName, {
|
|
6957
|
+
kind: cause.kind,
|
|
6958
|
+
blame: "target",
|
|
6959
|
+
targetVersion: cause.targetVersion,
|
|
6960
|
+
...typeof cause.windowMs === "number" ? { windowMs: cause.windowMs } : {},
|
|
6961
|
+
windowSource: cause.windowSource,
|
|
6962
|
+
...typeof cause.publishedAtMs === "number" ? { publishedAtMs: cause.publishedAtMs } : {}
|
|
6963
|
+
});
|
|
6964
|
+
} catch {
|
|
6965
|
+
reply = null;
|
|
6966
|
+
}
|
|
6967
|
+
const outcome = fallbackOutcomeOf(reply);
|
|
6968
|
+
gatedOutcomes.set(row.key, {
|
|
6969
|
+
kind: outcome.kind,
|
|
6970
|
+
unlockAtMs: outcome.unlockAtMs
|
|
6971
|
+
});
|
|
6972
|
+
if (outcome.candidate) rowFallbackOffers.set(row.key, {
|
|
6973
|
+
candidate: outcome.candidate,
|
|
6974
|
+
checkId: outcome.checkId,
|
|
6975
|
+
targetVersion: cause.targetVersion
|
|
6976
|
+
});
|
|
6977
|
+
return outcome;
|
|
6978
|
+
}
|
|
6979
|
+
function maybeAutoPlanCompliant() {
|
|
6980
|
+
if (!autoPlanEnabled || !mounted || inFlight || autoPlanRunning) return;
|
|
6981
|
+
let signature = "";
|
|
6982
|
+
const targets = [];
|
|
6983
|
+
try {
|
|
6984
|
+
for (const row of rows) {
|
|
6985
|
+
if (!needsAutoResolve(row)) continue;
|
|
6986
|
+
targets.push(row);
|
|
6987
|
+
signature += row.key + "@" + (latestVersionOf(row) ?? "") + ";";
|
|
6988
|
+
}
|
|
6989
|
+
} catch {
|
|
6990
|
+
return;
|
|
6991
|
+
}
|
|
6992
|
+
if (targets.length === 0 || signature === autoPlanSignature) return;
|
|
6993
|
+
autoPlanSignature = signature;
|
|
6994
|
+
autoPlanRunning = true;
|
|
6995
|
+
inFlight = true;
|
|
6996
|
+
render();
|
|
6997
|
+
(async () => {
|
|
6998
|
+
try {
|
|
6999
|
+
for (const row of targets) {
|
|
7000
|
+
if (!mounted) return;
|
|
7001
|
+
if (!needsAutoResolve(row)) continue;
|
|
7002
|
+
await resolveGated(row);
|
|
7003
|
+
}
|
|
7004
|
+
} finally {
|
|
7005
|
+
autoPlanRunning = false;
|
|
7006
|
+
inFlight = false;
|
|
7007
|
+
}
|
|
7008
|
+
if (!mounted) return;
|
|
7009
|
+
const merged = [...batchCompliantKeys];
|
|
7010
|
+
for (const row of targets) if (rowFallbackOffers.has(row.key) && !merged.includes(row.key)) merged.push(row.key);
|
|
7011
|
+
batchCompliantKeys = merged.filter((k) => rowFallbackOffers.has(k));
|
|
7012
|
+
if (batchCompliantKeys.length > 0) clearNotice();
|
|
7013
|
+
render();
|
|
7014
|
+
maybeAutoRowChangelog(expandedKey);
|
|
7015
|
+
})();
|
|
7016
|
+
}
|
|
7017
|
+
function waitingOf() {
|
|
7018
|
+
const keys = [];
|
|
7019
|
+
let earliest = null;
|
|
7020
|
+
try {
|
|
7021
|
+
for (const row of rows) {
|
|
7022
|
+
const seen = gatedOutcomes.get(row.key);
|
|
7023
|
+
if (!seen || seen.kind !== "wait-until") continue;
|
|
7024
|
+
if (compliantInstalledOf(row) !== null) continue;
|
|
7025
|
+
if (batchFallbackCauseOf(row) === null || singleFallbackPhoneOf(row) === null) continue;
|
|
7026
|
+
keys.push(row.key);
|
|
7027
|
+
if (typeof seen.unlockAtMs === "number" && (earliest === null || seen.unlockAtMs < earliest)) earliest = seen.unlockAtMs;
|
|
7028
|
+
}
|
|
7029
|
+
} catch {
|
|
7030
|
+
return {
|
|
7031
|
+
keys: [],
|
|
7032
|
+
unlockAtMs: null
|
|
7033
|
+
};
|
|
7034
|
+
}
|
|
7035
|
+
return {
|
|
7036
|
+
keys,
|
|
7037
|
+
unlockAtMs: earliest
|
|
7038
|
+
};
|
|
7039
|
+
}
|
|
7040
|
+
function unlockTimesOf() {
|
|
7041
|
+
const out = {};
|
|
7042
|
+
try {
|
|
7043
|
+
for (const [k, v] of gatedOutcomes) out[k] = v.unlockAtMs;
|
|
7044
|
+
} catch {}
|
|
7045
|
+
return out;
|
|
7046
|
+
}
|
|
6463
7047
|
function rowOfKey(key) {
|
|
6464
7048
|
return rows.find((row) => row.key === key) ?? null;
|
|
6465
7049
|
}
|
|
@@ -6496,7 +7080,7 @@ ${body}`;
|
|
|
6496
7080
|
}
|
|
6497
7081
|
async function copyWith(text, okNotice, key) {
|
|
6498
7082
|
try {
|
|
6499
|
-
await copyText(text);
|
|
7083
|
+
await copyText$1(text);
|
|
6500
7084
|
say(okNotice, key);
|
|
6501
7085
|
} catch {
|
|
6502
7086
|
say(batchText("batch.toast.copy-fail", currentLang()), key);
|
|
@@ -6535,6 +7119,7 @@ ${body}`;
|
|
|
6535
7119
|
loaded = true;
|
|
6536
7120
|
lastError = null;
|
|
6537
7121
|
if (expandedKey !== null && !rows.some((row) => row.key === expandedKey)) expandedKey = null;
|
|
7122
|
+
pruneFallbackOffers();
|
|
6538
7123
|
return;
|
|
6539
7124
|
}
|
|
6540
7125
|
const err = typeof reply["error"] === "string" ? reply["error"].trim() : "";
|
|
@@ -6555,6 +7140,7 @@ ${body}`;
|
|
|
6555
7140
|
}
|
|
6556
7141
|
render();
|
|
6557
7142
|
maybeAutoRowChangelog(expandedKey);
|
|
7143
|
+
maybeAutoPlanCompliant();
|
|
6558
7144
|
}
|
|
6559
7145
|
async function phone(name, args, busyRowKey = null) {
|
|
6560
7146
|
if (!mounted || inFlight) return null;
|
|
@@ -6583,6 +7169,7 @@ ${body}`;
|
|
|
6583
7169
|
if (mounted) render();
|
|
6584
7170
|
}
|
|
6585
7171
|
maybeAutoRowChangelog(expandedKey);
|
|
7172
|
+
maybeAutoPlanCompliant();
|
|
6586
7173
|
return out;
|
|
6587
7174
|
}
|
|
6588
7175
|
function remainingCount() {
|
|
@@ -6757,6 +7344,225 @@ ${body}`;
|
|
|
6757
7344
|
await copyWith(diagTextOf(row, currentLang()), batchText("batch.toast.copy-diag-ok", currentLang()), row.key);
|
|
6758
7345
|
return;
|
|
6759
7346
|
}
|
|
7347
|
+
case "copy-all-diag": {
|
|
7348
|
+
const failed = batchFailedRows(rows);
|
|
7349
|
+
if (failed.length === 0) return;
|
|
7350
|
+
await copyWith(batchFailedDiagText(rows, currentLang()), batchText("batch.toast.copy-all-diag-ok", currentLang(), { n: String(failed.length) }), null);
|
|
7351
|
+
return;
|
|
7352
|
+
}
|
|
7353
|
+
case "copy-all-manual": {
|
|
7354
|
+
if (batchFailedRows(rows).length === 0) return;
|
|
7355
|
+
const all = batchFailedManualText(rows, currentLang(), titles);
|
|
7356
|
+
if (all.commands === 0) return;
|
|
7357
|
+
await copyWith(all.text, batchText("batch.toast.copy-all-manual-ok", currentLang(), { n: String(all.commands) }), null);
|
|
7358
|
+
return;
|
|
7359
|
+
}
|
|
7360
|
+
case "row-fallback": {
|
|
7361
|
+
const row = typeof key === "string" && key ? rowOfKey(key) : null;
|
|
7362
|
+
if (!row) return;
|
|
7363
|
+
const cause = batchFallbackCauseOf(row);
|
|
7364
|
+
const phoneName = singleFallbackPhoneOf(row);
|
|
7365
|
+
if (!cause || phoneName === null) {
|
|
7366
|
+
say(copyText("panel.toast.fallback-unavailable", currentLang()), row.key);
|
|
7367
|
+
render();
|
|
7368
|
+
return;
|
|
7369
|
+
}
|
|
7370
|
+
if (inFlight) return;
|
|
7371
|
+
inFlight = true;
|
|
7372
|
+
fallbackBusyKey = row.key;
|
|
7373
|
+
clearNotice();
|
|
7374
|
+
render();
|
|
7375
|
+
try {
|
|
7376
|
+
let reply;
|
|
7377
|
+
try {
|
|
7378
|
+
reply = await call(phoneName, {
|
|
7379
|
+
kind: cause.kind,
|
|
7380
|
+
blame: "target",
|
|
7381
|
+
targetVersion: cause.targetVersion,
|
|
7382
|
+
...typeof cause.windowMs === "number" ? { windowMs: cause.windowMs } : {},
|
|
7383
|
+
windowSource: cause.windowSource,
|
|
7384
|
+
...typeof cause.publishedAtMs === "number" ? { publishedAtMs: cause.publishedAtMs } : {}
|
|
7385
|
+
});
|
|
7386
|
+
} catch {
|
|
7387
|
+
reply = null;
|
|
7388
|
+
}
|
|
7389
|
+
if (!mounted) return;
|
|
7390
|
+
if (!isObject$2(reply) || reply["ok"] === false) {
|
|
7391
|
+
say(copyText("panel.toast.fallback-unavailable", currentLang()), row.key);
|
|
7392
|
+
render();
|
|
7393
|
+
return;
|
|
7394
|
+
}
|
|
7395
|
+
const outcome = fallbackOutcomeOf(reply);
|
|
7396
|
+
if (outcome.candidate) {
|
|
7397
|
+
rowFallbackOffers.set(row.key, {
|
|
7398
|
+
candidate: outcome.candidate,
|
|
7399
|
+
checkId: outcome.checkId,
|
|
7400
|
+
targetVersion: cause.targetVersion
|
|
7401
|
+
});
|
|
7402
|
+
clearNotice();
|
|
7403
|
+
} else if (outcome.kind === "wait-until") {
|
|
7404
|
+
const time = typeof outcome.unlockAtMs === "number" ? formatUnlockAt(outcome.unlockAtMs, currentLang()) ?? null : null;
|
|
7405
|
+
say(time ? copyText("panel.toast.fallback-wait", currentLang(), { time }) : copyText("panel.toast.fallback-unavailable", currentLang()), row.key);
|
|
7406
|
+
} else say(copyText("panel.toast.fallback-unavailable", currentLang()), row.key);
|
|
7407
|
+
} finally {
|
|
7408
|
+
inFlight = false;
|
|
7409
|
+
fallbackBusyKey = null;
|
|
7410
|
+
}
|
|
7411
|
+
render();
|
|
7412
|
+
return;
|
|
7413
|
+
}
|
|
7414
|
+
case "batch-fallback-scan": {
|
|
7415
|
+
const targets = rows.filter((row) => batchFallbackCauseOf(row) !== null && singleFallbackPhoneOf(row) !== null);
|
|
7416
|
+
if (targets.length === 0) {
|
|
7417
|
+
say(copyText("panel.toast.fallback-unavailable", currentLang()));
|
|
7418
|
+
render();
|
|
7419
|
+
return;
|
|
7420
|
+
}
|
|
7421
|
+
if (inFlight) return;
|
|
7422
|
+
inFlight = true;
|
|
7423
|
+
clearNotice();
|
|
7424
|
+
render();
|
|
7425
|
+
const got = [];
|
|
7426
|
+
let waitTime = null;
|
|
7427
|
+
try {
|
|
7428
|
+
for (const row of targets) {
|
|
7429
|
+
if (!batchFallbackCauseOf(row) || singleFallbackPhoneOf(row) === null) continue;
|
|
7430
|
+
const outcome = await resolveGated(row);
|
|
7431
|
+
if (!mounted) return;
|
|
7432
|
+
if (outcome.candidate) got.push(row.key);
|
|
7433
|
+
else if (outcome.kind === "wait-until" && waitTime === null) waitTime = typeof outcome.unlockAtMs === "number" ? formatUnlockAt(outcome.unlockAtMs, currentLang()) ?? null : null;
|
|
7434
|
+
}
|
|
7435
|
+
} finally {
|
|
7436
|
+
inFlight = false;
|
|
7437
|
+
}
|
|
7438
|
+
if (got.length > 0) {
|
|
7439
|
+
const merged = [...batchCompliantKeys];
|
|
7440
|
+
for (const k of got) if (!merged.includes(k)) merged.push(k);
|
|
7441
|
+
batchCompliantKeys = merged.filter((k) => rowFallbackOffers.has(k));
|
|
7442
|
+
clearNotice();
|
|
7443
|
+
} else if (waitTime) say(copyText("panel.toast.fallback-wait", currentLang(), { time: waitTime }));
|
|
7444
|
+
else say(copyText("panel.toast.fallback-unavailable", currentLang()));
|
|
7445
|
+
render();
|
|
7446
|
+
return;
|
|
7447
|
+
}
|
|
7448
|
+
case "batch-fallback-confirm": {
|
|
7449
|
+
const keys = batchCompliantKeys.filter((k) => rowFallbackOffers.has(k));
|
|
7450
|
+
if (keys.length === 0) {
|
|
7451
|
+
batchCompliantKeys = [];
|
|
7452
|
+
say(copyText("panel.toast.fallback-unavailable", currentLang()));
|
|
7453
|
+
render();
|
|
7454
|
+
return;
|
|
7455
|
+
}
|
|
7456
|
+
if (inFlight) return;
|
|
7457
|
+
inFlight = true;
|
|
7458
|
+
clearNotice();
|
|
7459
|
+
render();
|
|
7460
|
+
let done = 0;
|
|
7461
|
+
let bad = 0;
|
|
7462
|
+
let busyCount = 0;
|
|
7463
|
+
try {
|
|
7464
|
+
for (const k of keys) {
|
|
7465
|
+
const row = rowOfKey(k);
|
|
7466
|
+
const offer = rowFallbackOffers.get(k) ?? null;
|
|
7467
|
+
const phoneName = row ? singleInstallPhoneOf(row) : null;
|
|
7468
|
+
if (!row || !offer || phoneName === null || offer.targetVersion !== latestVersionOf(row)) {
|
|
7469
|
+
rowFallbackOffers.delete(k);
|
|
7470
|
+
bad++;
|
|
7471
|
+
continue;
|
|
7472
|
+
}
|
|
7473
|
+
const freshRequestId = `r${Date.now().toString(36)}${Math.floor(Math.random() * 16777215).toString(36)}`.slice(0, 64);
|
|
7474
|
+
let reply = null;
|
|
7475
|
+
try {
|
|
7476
|
+
reply = await call(phoneName, {
|
|
7477
|
+
checkId: offer.checkId,
|
|
7478
|
+
requestId: freshRequestId,
|
|
7479
|
+
version: offer.candidate,
|
|
7480
|
+
from: "batch",
|
|
7481
|
+
includeEnv: true,
|
|
7482
|
+
includeQueue: true
|
|
7483
|
+
});
|
|
7484
|
+
} catch {
|
|
7485
|
+
reply = null;
|
|
7486
|
+
}
|
|
7487
|
+
const busy = isObject$2(reply) && reply["ok"] === false && (reply["error"] === "update-busy" || reply["errorKind"] === "update-busy");
|
|
7488
|
+
if (!busy) rowFallbackOffers.delete(k);
|
|
7489
|
+
if (!mounted) return;
|
|
7490
|
+
if (isObject$2(reply) && reply["ok"] !== false) {
|
|
7491
|
+
done++;
|
|
7492
|
+
const prev = gatedOutcomes.get(k);
|
|
7493
|
+
gatedOutcomes.set(k, {
|
|
7494
|
+
kind: "installed",
|
|
7495
|
+
unlockAtMs: prev ? prev.unlockAtMs : null
|
|
7496
|
+
});
|
|
7497
|
+
} else if (busy) busyCount++;
|
|
7498
|
+
else bad++;
|
|
7499
|
+
}
|
|
7500
|
+
} finally {
|
|
7501
|
+
inFlight = false;
|
|
7502
|
+
}
|
|
7503
|
+
batchCompliantKeys = keys.filter((k) => rowFallbackOffers.has(k));
|
|
7504
|
+
pruneFallbackOffers();
|
|
7505
|
+
await refresh();
|
|
7506
|
+
const parts = [];
|
|
7507
|
+
if (done > 0 || bad > 0) parts.push(batchText("batch.toast.compliant-installed", currentLang(), {
|
|
7508
|
+
a: String(done),
|
|
7509
|
+
b: String(bad)
|
|
7510
|
+
}));
|
|
7511
|
+
if (busyCount > 0) parts.push(copyText("batch.toast.queue-missed", currentLang()));
|
|
7512
|
+
if (parts.length > 0) say(parts.join(" "));
|
|
7513
|
+
render();
|
|
7514
|
+
return;
|
|
7515
|
+
}
|
|
7516
|
+
case "row-fallback-confirm": {
|
|
7517
|
+
const row = typeof key === "string" && key ? rowOfKey(key) : null;
|
|
7518
|
+
if (!row) return;
|
|
7519
|
+
const offer = rowFallbackOffers.get(row.key) ?? null;
|
|
7520
|
+
const phoneName = singleInstallPhoneOf(row);
|
|
7521
|
+
if (!offer || phoneName === null || offer.targetVersion !== latestVersionOf(row)) {
|
|
7522
|
+
rowFallbackOffers.delete(row.key);
|
|
7523
|
+
say(copyText("panel.toast.fallback-unavailable", currentLang()), row.key);
|
|
7524
|
+
render();
|
|
7525
|
+
return;
|
|
7526
|
+
}
|
|
7527
|
+
if (inFlight) return;
|
|
7528
|
+
inFlight = true;
|
|
7529
|
+
clearNotice();
|
|
7530
|
+
render();
|
|
7531
|
+
try {
|
|
7532
|
+
const freshRequestId = `r${Date.now().toString(36)}${Math.floor(Math.random() * 16777215).toString(36)}`.slice(0, 64);
|
|
7533
|
+
let reply;
|
|
7534
|
+
try {
|
|
7535
|
+
reply = await call(phoneName, {
|
|
7536
|
+
checkId: offer.checkId,
|
|
7537
|
+
requestId: freshRequestId,
|
|
7538
|
+
version: offer.candidate,
|
|
7539
|
+
from: "batch",
|
|
7540
|
+
includeEnv: true,
|
|
7541
|
+
includeQueue: true
|
|
7542
|
+
});
|
|
7543
|
+
} catch {
|
|
7544
|
+
reply = null;
|
|
7545
|
+
}
|
|
7546
|
+
if (!mounted) return;
|
|
7547
|
+
if (isObject$2(reply) && reply["ok"] === false && (reply["error"] === "update-busy" || reply["errorKind"] === "update-busy")) say(copyText("batch.toast.queue-missed", currentLang()), row.key);
|
|
7548
|
+
else {
|
|
7549
|
+
rowFallbackOffers.delete(row.key);
|
|
7550
|
+
if (!isObject$2(reply) || reply["ok"] === false) say(copyText("panel.toast.fallback-unavailable", currentLang()), row.key);
|
|
7551
|
+
else {
|
|
7552
|
+
const prev = gatedOutcomes.get(row.key);
|
|
7553
|
+
gatedOutcomes.set(row.key, {
|
|
7554
|
+
kind: "installed",
|
|
7555
|
+
unlockAtMs: prev ? prev.unlockAtMs : null
|
|
7556
|
+
});
|
|
7557
|
+
}
|
|
7558
|
+
}
|
|
7559
|
+
} finally {
|
|
7560
|
+
inFlight = false;
|
|
7561
|
+
}
|
|
7562
|
+
pruneFallbackOffers();
|
|
7563
|
+
await refresh();
|
|
7564
|
+
return;
|
|
7565
|
+
}
|
|
6760
7566
|
case "toggle-details":
|
|
6761
7567
|
if (typeof key !== "string" || !key) return;
|
|
6762
7568
|
expandedKey = expandedKey === key ? null : key;
|
|
@@ -6936,7 +7742,7 @@ ${body}`;
|
|
|
6936
7742
|
};
|
|
6937
7743
|
}
|
|
6938
7744
|
//#endregion
|
|
6939
|
-
//#region ../../node_modules/.pnpm/dsh-plugin-update@0.18.
|
|
7745
|
+
//#region ../../node_modules/.pnpm/dsh-plugin-update@0.18.11/node_modules/dsh-plugin-update/dist/entry-batch.js
|
|
6940
7746
|
function isObject$1(value) {
|
|
6941
7747
|
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
6942
7748
|
}
|
|
@@ -6947,11 +7753,20 @@ ${body}`;
|
|
|
6947
7753
|
function escapeHtml$1(value) {
|
|
6948
7754
|
return String(value).replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """);
|
|
6949
7755
|
}
|
|
7756
|
+
function compliantEntryDone(rows) {
|
|
7757
|
+
const done = /* @__PURE__ */ new Map();
|
|
7758
|
+
if (!Array.isArray(rows)) return done;
|
|
7759
|
+
for (const row of rows) try {
|
|
7760
|
+
const fact = compliantInstalledOf(row);
|
|
7761
|
+
if (fact) done.set(row.key, fact.needsRestart);
|
|
7762
|
+
} catch {}
|
|
7763
|
+
return done;
|
|
7764
|
+
}
|
|
6950
7765
|
function batchEntrySummary(state, lang) {
|
|
6951
7766
|
const rows = state?.rows ?? null;
|
|
6952
7767
|
const inventory = state?.inventory ?? void 0;
|
|
6953
7768
|
const session = state?.session;
|
|
6954
|
-
const counts = batchLedgerCounts(Array.isArray(rows) ? rows : [], inventory, session);
|
|
7769
|
+
const counts = batchLedgerCounts(Array.isArray(rows) ? rows : [], inventory, session, compliantEntryDone(rows));
|
|
6955
7770
|
const total = Array.isArray(rows) ? rows.length : 0;
|
|
6956
7771
|
let kind;
|
|
6957
7772
|
if (!Array.isArray(rows) || rows.length === 0) kind = state?.error ? "failed" : "idle";
|
|
@@ -7372,6 +8187,29 @@ ${body}`;
|
|
|
7372
8187
|
}
|
|
7373
8188
|
} catch {}
|
|
7374
8189
|
}
|
|
8190
|
+
function installButtonFallbackOf(input, bannerKind) {
|
|
8191
|
+
try {
|
|
8192
|
+
if (bannerKind !== "failed") return null;
|
|
8193
|
+
if (input.busyAct === "check" || input.busyAct === "install") return null;
|
|
8194
|
+
const code = typeof input.lastError === "string" && input.lastError ? input.lastError : "install-failed";
|
|
8195
|
+
const cause = fallbackCauseFromDiag(input.errorDiag, input.errorDetail ?? null, code, input.snapshot?.job?.targetVersion) ?? fallbackCauseFromDetail(input.errorDetail ?? null, code, input.pluginId ?? null);
|
|
8196
|
+
if (!cause) return null;
|
|
8197
|
+
const latest = input.snapshot?.latestVersion ?? null;
|
|
8198
|
+
if (typeof latest !== "string" || !latest || cause.targetVersion !== latest) return null;
|
|
8199
|
+
const offered = typeof input.fallbackOffer?.candidate === "string" ? input.fallbackOffer.candidate.trim() : "";
|
|
8200
|
+
const offerTarget = typeof input.fallbackOffer?.targetVersion === "string" ? input.fallbackOffer.targetVersion.trim() : "";
|
|
8201
|
+
if (offered && offerTarget === cause.targetVersion) return {
|
|
8202
|
+
stage: "confirm",
|
|
8203
|
+
candidate: offered
|
|
8204
|
+
};
|
|
8205
|
+
return {
|
|
8206
|
+
stage: "offer",
|
|
8207
|
+
candidate: null
|
|
8208
|
+
};
|
|
8209
|
+
} catch {
|
|
8210
|
+
return null;
|
|
8211
|
+
}
|
|
8212
|
+
}
|
|
7375
8213
|
function installButtonViewModel(input) {
|
|
7376
8214
|
const l = normalizeLangTag(input.lang ?? "zh");
|
|
7377
8215
|
const view = panelViewModel({
|
|
@@ -7384,6 +8222,8 @@ ${body}`;
|
|
|
7384
8222
|
}, l);
|
|
7385
8223
|
const jobState = (input.snapshot?.job ?? null)?.state ?? null;
|
|
7386
8224
|
const jobActive = jobState === "installing" || jobState === "verifying";
|
|
8225
|
+
const fallback = installButtonFallbackOf(input, view.banner.kind);
|
|
8226
|
+
const fallbackBusy = input.busyAct === "fallback";
|
|
7387
8227
|
if (input.pollCapped === true && jobActive && !input.busyAct) return {
|
|
7388
8228
|
role: "check",
|
|
7389
8229
|
buttonLabel: copyText("panel.action.check", l),
|
|
@@ -7394,9 +8234,12 @@ ${body}`;
|
|
|
7394
8234
|
statusAction: view.banner.action,
|
|
7395
8235
|
showManual: view.showManual,
|
|
7396
8236
|
queueNote: view.queueNote,
|
|
7397
|
-
bannerKind: view.banner.kind
|
|
8237
|
+
bannerKind: view.banner.kind,
|
|
8238
|
+
fallbackStage: null,
|
|
8239
|
+
fallbackCandidate: null,
|
|
8240
|
+
fallbackBusy: false
|
|
7398
8241
|
};
|
|
7399
|
-
if (input.busyAct === "check" || input.busyAct === "install" || jobActive) return {
|
|
8242
|
+
if (input.busyAct === "check" || input.busyAct === "install" || input.busyAct === "fallback" || jobActive) return {
|
|
7400
8243
|
role: "none",
|
|
7401
8244
|
buttonLabel: input.busyAct === "check" ? copyText("panel.action.checking-busy", l) : input.busyAct === "install" ? copyText("panel.action.installing-busy", l) : view.installLabel,
|
|
7402
8245
|
buttonEnabled: false,
|
|
@@ -7406,7 +8249,10 @@ ${body}`;
|
|
|
7406
8249
|
statusAction: view.banner.action,
|
|
7407
8250
|
showManual: view.showManual,
|
|
7408
8251
|
queueNote: view.queueNote,
|
|
7409
|
-
bannerKind: view.banner.kind
|
|
8252
|
+
bannerKind: view.banner.kind,
|
|
8253
|
+
fallbackStage: fallback?.stage ?? null,
|
|
8254
|
+
fallbackCandidate: fallback?.candidate ?? null,
|
|
8255
|
+
fallbackBusy
|
|
7410
8256
|
};
|
|
7411
8257
|
if (view.installEnabled) return {
|
|
7412
8258
|
role: "install",
|
|
@@ -7418,7 +8264,10 @@ ${body}`;
|
|
|
7418
8264
|
statusAction: view.banner.action,
|
|
7419
8265
|
showManual: view.showManual,
|
|
7420
8266
|
queueNote: view.queueNote,
|
|
7421
|
-
bannerKind: view.banner.kind
|
|
8267
|
+
bannerKind: view.banner.kind,
|
|
8268
|
+
fallbackStage: fallback?.stage ?? null,
|
|
8269
|
+
fallbackCandidate: fallback?.candidate ?? null,
|
|
8270
|
+
fallbackBusy
|
|
7422
8271
|
};
|
|
7423
8272
|
if (!input.snapshot || !input.snapshot.latestVersion) return {
|
|
7424
8273
|
role: "check",
|
|
@@ -7430,7 +8279,10 @@ ${body}`;
|
|
|
7430
8279
|
statusAction: view.banner.action,
|
|
7431
8280
|
showManual: view.showManual,
|
|
7432
8281
|
queueNote: view.queueNote,
|
|
7433
|
-
bannerKind: view.banner.kind
|
|
8282
|
+
bannerKind: view.banner.kind,
|
|
8283
|
+
fallbackStage: null,
|
|
8284
|
+
fallbackCandidate: null,
|
|
8285
|
+
fallbackBusy: false
|
|
7434
8286
|
};
|
|
7435
8287
|
if (input.lastError && isCheckSideFailureCode(input.lastError)) return {
|
|
7436
8288
|
role: "check",
|
|
@@ -7442,7 +8294,10 @@ ${body}`;
|
|
|
7442
8294
|
statusAction: view.banner.action,
|
|
7443
8295
|
showManual: view.showManual,
|
|
7444
8296
|
queueNote: view.queueNote,
|
|
7445
|
-
bannerKind: view.banner.kind
|
|
8297
|
+
bannerKind: view.banner.kind,
|
|
8298
|
+
fallbackStage: null,
|
|
8299
|
+
fallbackCandidate: null,
|
|
8300
|
+
fallbackBusy: false
|
|
7446
8301
|
};
|
|
7447
8302
|
const done = view.banner.kind === "done";
|
|
7448
8303
|
return {
|
|
@@ -7455,7 +8310,10 @@ ${body}`;
|
|
|
7455
8310
|
statusAction: view.banner.action,
|
|
7456
8311
|
showManual: view.showManual,
|
|
7457
8312
|
queueNote: view.queueNote,
|
|
7458
|
-
bannerKind: view.banner.kind
|
|
8313
|
+
bannerKind: view.banner.kind,
|
|
8314
|
+
fallbackStage: fallback?.stage ?? null,
|
|
8315
|
+
fallbackCandidate: fallback?.candidate ?? null,
|
|
8316
|
+
fallbackBusy
|
|
7459
8317
|
};
|
|
7460
8318
|
}
|
|
7461
8319
|
function renderInstallButtonHTML(view, opts) {
|
|
@@ -7472,6 +8330,13 @@ ${body}`;
|
|
|
7472
8330
|
const busy = view.buttonBusy ? " aria-busy=\"true\"" : "";
|
|
7473
8331
|
parts.push("<div class=\"dsh-upd-ib-row\"><button type=\"button\"" + actionAttr + " data-primary=\"1\"" + disabled + busy + ">" + escapeHtml(view.buttonLabel) + "</button></div>");
|
|
7474
8332
|
}
|
|
8333
|
+
if (view.fallbackStage === "confirm" && view.fallbackCandidate) {
|
|
8334
|
+
const busy = view.fallbackBusy || view.buttonBusy ? " disabled aria-busy=\"true\"" : "";
|
|
8335
|
+
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>");
|
|
8336
|
+
} else if (view.fallbackStage === "offer") {
|
|
8337
|
+
const busy = view.fallbackBusy || view.buttonBusy ? " disabled aria-busy=\"true\"" : "";
|
|
8338
|
+
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>");
|
|
8339
|
+
}
|
|
7475
8340
|
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>");
|
|
7476
8341
|
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>");
|
|
7477
8342
|
if (opts.notice) parts.push("<div class=\"dsh-upd-ib-notice\" role=\"status\">" + escapeHtml(opts.notice) + "</div>");
|
|
@@ -7577,6 +8442,7 @@ ${body}`;
|
|
|
7577
8442
|
let requestId = null;
|
|
7578
8443
|
let latch = null;
|
|
7579
8444
|
let busyAct = null;
|
|
8445
|
+
let fallbackOffer = null;
|
|
7580
8446
|
let ensuring = false;
|
|
7581
8447
|
let pollCount = 0;
|
|
7582
8448
|
let pollCapped = false;
|
|
@@ -7626,9 +8492,11 @@ ${body}`;
|
|
|
7626
8492
|
}
|
|
7627
8493
|
function setLatch(next) {
|
|
7628
8494
|
latch = next;
|
|
8495
|
+
fallbackOffer = null;
|
|
7629
8496
|
}
|
|
7630
8497
|
function clearLatch() {
|
|
7631
8498
|
latch = null;
|
|
8499
|
+
fallbackOffer = null;
|
|
7632
8500
|
}
|
|
7633
8501
|
function latchFromReply(reply, source) {
|
|
7634
8502
|
const env = currentEnvPair();
|
|
@@ -7653,7 +8521,7 @@ ${body}`;
|
|
|
7653
8521
|
atMs: latchNow()
|
|
7654
8522
|
};
|
|
7655
8523
|
}
|
|
7656
|
-
function latchFromJob(job, snap) {
|
|
8524
|
+
function latchFromJob(job, snap, replyDiag) {
|
|
7657
8525
|
const env = currentEnvPair();
|
|
7658
8526
|
const message = typeof job.message === "string" ? job.message : null;
|
|
7659
8527
|
const detail = message && message.includes(":") ? message.slice(message.indexOf(":") + 1).trim() || null : message;
|
|
@@ -7661,7 +8529,7 @@ ${body}`;
|
|
|
7661
8529
|
code: messageCodeOf(message) || "install-failed",
|
|
7662
8530
|
kind: null,
|
|
7663
8531
|
detail,
|
|
7664
|
-
diag: latch?.diag ?? null,
|
|
8532
|
+
diag: latch?.diag ?? replyDiag ?? null,
|
|
7665
8533
|
requestId: job.requestId ?? latch?.requestId ?? requestId,
|
|
7666
8534
|
checkId: receipt?.checkId ?? latch?.checkId ?? null,
|
|
7667
8535
|
runningVersion: snap?.runningVersion ?? snapshot?.runningVersion ?? null,
|
|
@@ -7715,7 +8583,7 @@ ${body}`;
|
|
|
7715
8583
|
if (jobState === "installing" || jobState === "verifying") clearLatch();
|
|
7716
8584
|
else if (jobState === "completed" || jobState === "restart-required") clearLatch();
|
|
7717
8585
|
else if ((jobState === "failed" || jobState === "interrupted") && snapshot?.job) {
|
|
7718
|
-
const next = latchFromJob(snapshot.job, snapshot);
|
|
8586
|
+
const next = latchFromJob(snapshot.job, snapshot, isObject(reply["diag"]) ? reply["diag"] : null);
|
|
7719
8587
|
if (!latch || latch.volatile || latch.code !== next.code || latch.targetVersion !== next.targetVersion || latch.latestVersion !== next.latestVersion) setLatch(next);
|
|
7720
8588
|
} else if (via === "install") clearLatch();
|
|
7721
8589
|
else if (via === "check" && latch?.source === "check") clearLatch();
|
|
@@ -7754,6 +8622,13 @@ ${body}`;
|
|
|
7754
8622
|
queue,
|
|
7755
8623
|
lastError: latch?.code ?? null,
|
|
7756
8624
|
errorKind: latch?.kind ?? null,
|
|
8625
|
+
errorDetail: latch?.detail ?? null,
|
|
8626
|
+
errorDiag: latch?.diag ?? null,
|
|
8627
|
+
pluginId,
|
|
8628
|
+
fallbackOffer: fallbackOffer ? {
|
|
8629
|
+
candidate: fallbackOffer.candidate,
|
|
8630
|
+
targetVersion: fallbackOffer.targetVersion
|
|
8631
|
+
} : null,
|
|
7757
8632
|
busyAct,
|
|
7758
8633
|
pollCapped,
|
|
7759
8634
|
lang: currentLang()
|
|
@@ -7780,9 +8655,9 @@ ${body}`;
|
|
|
7780
8655
|
logClient("error", "update.panel.render.fail", { kind: "unknown" });
|
|
7781
8656
|
}
|
|
7782
8657
|
}
|
|
7783
|
-
function sayCopyKey(key) {
|
|
8658
|
+
function sayCopyKey(key, params) {
|
|
7784
8659
|
try {
|
|
7785
|
-
copyNotice = copyText(key, currentLang());
|
|
8660
|
+
copyNotice = copyText(key, currentLang(), params);
|
|
7786
8661
|
noticeExpiresAt = Date.now() + 5e3;
|
|
7787
8662
|
} catch {
|
|
7788
8663
|
copyNotice = null;
|
|
@@ -7980,6 +8855,124 @@ ${body}`;
|
|
|
7980
8855
|
});
|
|
7981
8856
|
}
|
|
7982
8857
|
}
|
|
8858
|
+
async function doFallbackResolve() {
|
|
8859
|
+
if (!latch) {
|
|
8860
|
+
sayCopyKey("panel.toast.fallback-unavailable");
|
|
8861
|
+
paint();
|
|
8862
|
+
return;
|
|
8863
|
+
}
|
|
8864
|
+
const cause = fallbackCauseFromDetail(latch.detail, latch.code, pluginId);
|
|
8865
|
+
if (!cause || cause.targetVersion !== (latch.latestVersion ?? snapshot?.latestVersion ?? null)) {
|
|
8866
|
+
sayCopyKey("panel.toast.fallback-unavailable");
|
|
8867
|
+
paint();
|
|
8868
|
+
return;
|
|
8869
|
+
}
|
|
8870
|
+
busyAct = "fallback";
|
|
8871
|
+
paint();
|
|
8872
|
+
try {
|
|
8873
|
+
let reply;
|
|
8874
|
+
try {
|
|
8875
|
+
reply = await call(phoneNames.updateCheckFallback, {
|
|
8876
|
+
kind: cause.kind,
|
|
8877
|
+
blame: "target",
|
|
8878
|
+
targetVersion: cause.targetVersion,
|
|
8879
|
+
...typeof cause.windowMs === "number" ? { windowMs: cause.windowMs } : {},
|
|
8880
|
+
windowSource: cause.windowSource,
|
|
8881
|
+
...typeof cause.publishedAtMs === "number" ? { publishedAtMs: cause.publishedAtMs } : {}
|
|
8882
|
+
});
|
|
8883
|
+
} catch {
|
|
8884
|
+
reply = null;
|
|
8885
|
+
}
|
|
8886
|
+
if (!mounted) return;
|
|
8887
|
+
if (!isObject(reply) || reply["ok"] === false) {
|
|
8888
|
+
sayCopyKey("panel.toast.fallback-unavailable");
|
|
8889
|
+
paint();
|
|
8890
|
+
return;
|
|
8891
|
+
}
|
|
8892
|
+
const snap = isObject(reply["snapshot"]) ? reply["snapshot"] : null;
|
|
8893
|
+
const verdict = snap && isObject(snap["verdict"]) ? snap["verdict"] : null;
|
|
8894
|
+
const vKind = verdict && typeof verdict["kind"] === "string" ? verdict["kind"] : "";
|
|
8895
|
+
const vVersion = verdict && typeof verdict["version"] === "string" ? verdict["version"].trim() : "";
|
|
8896
|
+
const snapCandidate = snap && typeof snap["candidate"] === "string" ? snap["candidate"].trim() : "";
|
|
8897
|
+
const rec = isObject(reply["receipt"]) ? reply["receipt"] : null;
|
|
8898
|
+
const gotCheckId = rec && typeof rec["checkId"] === "string" ? rec["checkId"] : "";
|
|
8899
|
+
const candidate = snapCandidate || (vKind === "ok-now" ? vVersion : "");
|
|
8900
|
+
if ((vKind === "downgrade-available" || vKind === "ok-now") && candidate && gotCheckId) fallbackOffer = {
|
|
8901
|
+
candidate,
|
|
8902
|
+
checkId: gotCheckId,
|
|
8903
|
+
targetVersion: cause.targetVersion
|
|
8904
|
+
};
|
|
8905
|
+
else if (vKind === "wait-until") {
|
|
8906
|
+
const unlockAt = verdict && typeof verdict["unlockAtMs"] === "number" ? verdict["unlockAtMs"] : null;
|
|
8907
|
+
const time = typeof unlockAt === "number" ? formatUnlockAt(unlockAt, currentLang()) ?? null : null;
|
|
8908
|
+
if (time) sayCopyKey("panel.toast.fallback-wait", { time });
|
|
8909
|
+
else sayCopyKey("panel.toast.fallback-unavailable");
|
|
8910
|
+
} else sayCopyKey("panel.toast.fallback-unavailable");
|
|
8911
|
+
} finally {
|
|
8912
|
+
busyAct = null;
|
|
8913
|
+
}
|
|
8914
|
+
paint();
|
|
8915
|
+
}
|
|
8916
|
+
async function doFallbackConfirm() {
|
|
8917
|
+
if (!fallbackOffer) return;
|
|
8918
|
+
const offer = fallbackOffer;
|
|
8919
|
+
busyAct = "install";
|
|
8920
|
+
copyNotice = copyText("panel.toast.installing", currentLang());
|
|
8921
|
+
paint();
|
|
8922
|
+
try {
|
|
8923
|
+
requestId = randomRequestId();
|
|
8924
|
+
pollCount = 0;
|
|
8925
|
+
pollCapped = false;
|
|
8926
|
+
let reply;
|
|
8927
|
+
try {
|
|
8928
|
+
reply = await call(phoneNames.updateInstall, {
|
|
8929
|
+
checkId: offer.checkId,
|
|
8930
|
+
requestId,
|
|
8931
|
+
version: offer.candidate,
|
|
8932
|
+
...queueArgs()
|
|
8933
|
+
});
|
|
8934
|
+
} catch (err) {
|
|
8935
|
+
if (!mounted) return;
|
|
8936
|
+
fallbackOffer = null;
|
|
8937
|
+
if (thrownIsCheckExpired(err)) {
|
|
8938
|
+
sayCopyKey("panel.toast.fallback-unavailable");
|
|
8939
|
+
paint();
|
|
8940
|
+
return;
|
|
8941
|
+
}
|
|
8942
|
+
const env = currentEnvPair();
|
|
8943
|
+
setLatch({
|
|
8944
|
+
code: "install-failed",
|
|
8945
|
+
kind: null,
|
|
8946
|
+
detail: thrownDetail(err),
|
|
8947
|
+
diag: null,
|
|
8948
|
+
requestId,
|
|
8949
|
+
checkId: offer.checkId,
|
|
8950
|
+
runningVersion: snapshot?.runningVersion ?? null,
|
|
8951
|
+
installedVersion: snapshot?.installedVersion ?? null,
|
|
8952
|
+
latestVersion: snapshot?.latestVersion ?? null,
|
|
8953
|
+
targetVersion: null,
|
|
8954
|
+
hostKind: env.hostKind,
|
|
8955
|
+
profileName: env.profileName,
|
|
8956
|
+
source: "install",
|
|
8957
|
+
volatile: false,
|
|
8958
|
+
atMs: latchNow()
|
|
8959
|
+
});
|
|
8960
|
+
paint();
|
|
8961
|
+
return;
|
|
8962
|
+
}
|
|
8963
|
+
if (!mounted) return;
|
|
8964
|
+
fallbackOffer = null;
|
|
8965
|
+
if (replyIsCheckExpired(reply)) {
|
|
8966
|
+
sayCopyKey("panel.toast.fallback-unavailable");
|
|
8967
|
+
paint();
|
|
8968
|
+
return;
|
|
8969
|
+
}
|
|
8970
|
+
applyStatusReply(reply, "install");
|
|
8971
|
+
} finally {
|
|
8972
|
+
busyAct = null;
|
|
8973
|
+
}
|
|
8974
|
+
paint();
|
|
8975
|
+
}
|
|
7983
8976
|
async function runAction(kind) {
|
|
7984
8977
|
copyNotice = null;
|
|
7985
8978
|
switch (kind) {
|
|
@@ -8031,6 +9024,20 @@ ${body}`;
|
|
|
8031
9024
|
paint();
|
|
8032
9025
|
return;
|
|
8033
9026
|
}
|
|
9027
|
+
case "install-fallback":
|
|
9028
|
+
if (busyAct) return;
|
|
9029
|
+
await doFallbackResolve();
|
|
9030
|
+
return;
|
|
9031
|
+
case "install-fallback-confirm":
|
|
9032
|
+
if (busyAct || !fallbackOffer) return;
|
|
9033
|
+
await doFallbackConfirm();
|
|
9034
|
+
return;
|
|
9035
|
+
case "wait-latest":
|
|
9036
|
+
fallbackOffer = null;
|
|
9037
|
+
clearLatch();
|
|
9038
|
+
sayCopyKey("panel.toast.failure-dismissed");
|
|
9039
|
+
paint();
|
|
9040
|
+
return;
|
|
8034
9041
|
}
|
|
8035
9042
|
}
|
|
8036
9043
|
function onClick(ev) {
|
|
@@ -8038,7 +9045,7 @@ ${body}`;
|
|
|
8038
9045
|
const t = ev;
|
|
8039
9046
|
const btn = t?.target && typeof t.target.closest === "function" ? t.target.closest("[data-action]") : null;
|
|
8040
9047
|
const kind = btn?.getAttribute ? btn.getAttribute("data-action") : null;
|
|
8041
|
-
if (kind !== "install" && kind !== "check" && kind !== "copy-manual" && kind !== "copy-diag") return;
|
|
9048
|
+
if (kind !== "install" && kind !== "check" && kind !== "copy-manual" && kind !== "copy-diag" && kind !== "install-fallback" && kind !== "install-fallback-confirm" && kind !== "wait-latest") return;
|
|
8042
9049
|
act(kind);
|
|
8043
9050
|
} catch {}
|
|
8044
9051
|
}
|
|
@@ -10895,7 +11902,7 @@ ${body}`;
|
|
|
10895
11902
|
}, 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)))));
|
|
10896
11903
|
}
|
|
10897
11904
|
/** 版本胶囊那一行字:只在这里拼一次,屏上与用例读的是同一串。 */
|
|
10898
|
-
const MANAGER_VERSION_TEXT = "dsh-life-pack · 0.3.
|
|
11905
|
+
const MANAGER_VERSION_TEXT = "dsh-life-pack · 0.3.68";
|
|
10899
11906
|
/** 右下角那本书离面板两沿的距离:用户口径「一直处于面板右下角、不随列表滑动消失」
|
|
10900
11907
|
* ⇒ sticky 吸附(面板相对,视口多大都落在面板角上);INSET=右沿,BOTTOM=底沿。 */
|
|
10901
11908
|
const MANUAL_ENTRY_INSET = 16;
|
|
@@ -11096,7 +12103,40 @@ ${body}`;
|
|
|
11096
12103
|
});
|
|
11097
12104
|
} catch {}
|
|
11098
12105
|
}, [active]);
|
|
11099
|
-
|
|
12106
|
+
/** 面板宽度不许跟着宿主滚动条变:宿主承载本面板的滚动体一出现滚动条,
|
|
12107
|
+
* 内容盒就窄 5px(主题里 `--dsh-scrollbar-width:5px`),标题行右对齐的按钮组便跟着左右挪;
|
|
12108
|
+
* 而滚动条出不出,取决于**当前页签**的内容高——装了的那家有配置卡,必然要滚,缺席页签不必。
|
|
12109
|
+
*
|
|
12110
|
+
* 这里不动面板高度、也不改宿主样式表,只给**最近的可滚动祖先**钉一条内联
|
|
12111
|
+
* `scrollbar-gutter: stable`:槽位恒定预留,滚动条本身仍按需出现/消失,内容盒宽度因此恒定。
|
|
12112
|
+
* 卸载时还原(宿主本来就有 stable 时压根不写),改动不留在宿主上。
|
|
12113
|
+
* 替身渲染台(test/helpers/panel-render.mjs)里 ref 拿不到元素 ⇒ 这里天然空过,不碰 window。 */
|
|
12114
|
+
const rootRef = react.useRef(null);
|
|
12115
|
+
react.useEffect(() => {
|
|
12116
|
+
const root = rootRef.current;
|
|
12117
|
+
if (root === null || typeof window === "undefined") return;
|
|
12118
|
+
let node = root.parentElement;
|
|
12119
|
+
while (node !== null) {
|
|
12120
|
+
const overflowY = window.getComputedStyle(node).overflowY;
|
|
12121
|
+
if (overflowY === "auto" || overflowY === "scroll") break;
|
|
12122
|
+
node = node.parentElement;
|
|
12123
|
+
}
|
|
12124
|
+
const scroller = node;
|
|
12125
|
+
if (scroller === null) return;
|
|
12126
|
+
if (window.getComputedStyle(scroller).getPropertyValue("scrollbar-gutter").trim() === "stable") return;
|
|
12127
|
+
const previous = scroller.style.getPropertyValue("scrollbar-gutter");
|
|
12128
|
+
scroller.style.setProperty("scrollbar-gutter", "stable");
|
|
12129
|
+
return () => {
|
|
12130
|
+
if (previous.length > 0) scroller.style.setProperty("scrollbar-gutter", previous);
|
|
12131
|
+
else scroller.style.removeProperty("scrollbar-gutter");
|
|
12132
|
+
};
|
|
12133
|
+
}, []);
|
|
12134
|
+
return react.createElement("div", {
|
|
12135
|
+
style: { position: "relative" },
|
|
12136
|
+
ref: (element) => {
|
|
12137
|
+
rootRef.current = element;
|
|
12138
|
+
}
|
|
12139
|
+
}, react.createElement("div", { style: S.headRow }, react.createElement("div", { style: S.head }, "爱生活"), react.createElement("span", {
|
|
11100
12140
|
style: S.versionCapsule,
|
|
11101
12141
|
"data-ilife-version": "capsule"
|
|
11102
12142
|
}, MANAGER_VERSION_TEXT), react.createElement("div", { style: S.headActions }, react.createElement("button", {
|