dsh-plugin-update 0.5.8 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +16 -4
- package/README.md +46 -9
- package/dist/bilingual.d.ts +4 -4
- package/dist/bilingual.js +300 -1
- package/dist/changelog.d.ts +19 -13
- package/dist/changelog.js +60 -22
- package/dist/diag.d.ts +3 -0
- package/dist/diag.js +32 -20
- package/dist/entry-batch.d.ts +10 -2
- package/dist/entry-batch.js +21 -7
- package/dist/entry.d.ts +31 -2
- package/dist/entry.js +83 -27
- package/dist/host-batch.js +104 -13
- package/dist/http.d.ts +2 -2
- package/dist/http.js +1 -1
- package/dist/panel-batch.d.ts +53 -11
- package/dist/panel-batch.js +500 -153
- package/dist/panel.d.ts +84 -25
- package/dist/panel.js +618 -364
- package/dist/store.d.ts +42 -0
- package/dist/store.js +139 -0
- package/package.json +1 -1
package/dist/panel-batch.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
// AUTO-GENERATED by node build.mjs — DO NOT EDIT. Source: src/panel-batch.ts
|
|
2
2
|
import { assertPrefix, MIN_PANEL_POLL_MS } from "./config.js";
|
|
3
|
+
import { copyText as bilingualText } from "./bilingual.js";
|
|
4
|
+
import { normalizeLangTag, resolveLang, subscribeLang } from "./lang.js";
|
|
3
5
|
import { validReleaseVersion } from "./service.js";
|
|
4
6
|
import { shouldFetchChangelog } from "./changelog.js";
|
|
5
7
|
import {
|
|
@@ -8,13 +10,14 @@ import {
|
|
|
8
10
|
} from "./batch.js";
|
|
9
11
|
import {
|
|
10
12
|
UPDATE_PANEL_CSS,
|
|
11
|
-
|
|
13
|
+
UPDATE_PANEL_ARCHIVE_CSS,
|
|
12
14
|
buildDiagnosticText,
|
|
13
15
|
createBrowserSkipStore,
|
|
14
16
|
failureCopy,
|
|
15
17
|
isKnownFailureCode,
|
|
16
18
|
normalizePanelTheme,
|
|
17
|
-
renderUpdatePanelHTML
|
|
19
|
+
renderUpdatePanelHTML,
|
|
20
|
+
themeTokensStyleFor
|
|
18
21
|
} from "./panel.js";
|
|
19
22
|
const BATCH_PANEL_POLL = {
|
|
20
23
|
defaultMs: 1500,
|
|
@@ -27,7 +30,9 @@ function buildBatchPhoneNames(prefix) {
|
|
|
27
30
|
check: p + ".batchCheck",
|
|
28
31
|
install: p + ".batchInstall",
|
|
29
32
|
resume: p + ".batchResume",
|
|
30
|
-
cancel: p + ".batchCancel"
|
|
33
|
+
cancel: p + ".batchCancel",
|
|
34
|
+
prefs: p + ".batchPrefs",
|
|
35
|
+
prefsSave: p + ".batchPrefsSave"
|
|
31
36
|
};
|
|
32
37
|
}
|
|
33
38
|
function batchLedgerCounts(rows) {
|
|
@@ -53,44 +58,122 @@ function batchLedgerCounts(rows) {
|
|
|
53
58
|
}
|
|
54
59
|
return counts;
|
|
55
60
|
}
|
|
56
|
-
function batchLedgerText(counts) {
|
|
61
|
+
function batchLedgerText(counts, lang) {
|
|
62
|
+
const l = langOf(lang);
|
|
57
63
|
const parts = [];
|
|
58
|
-
if (counts.updatable > 0) parts.push(
|
|
59
|
-
if (counts.installing > 0) parts.push(
|
|
60
|
-
if (counts.pending > 0) parts.push(
|
|
61
|
-
if (counts.restart > 0) parts.push(
|
|
62
|
-
if (counts.failed > 0) parts.push(
|
|
63
|
-
if (counts.skipped > 0) parts.push(
|
|
64
|
-
if (counts.settled > 0) parts.push(
|
|
65
|
-
return parts.length > 0 ? parts.join(" \xB7 ") : "
|
|
64
|
+
if (counts.updatable > 0) parts.push(batchText("batch.summary.updatable", l, { n: String(counts.updatable) }));
|
|
65
|
+
if (counts.installing > 0) parts.push(batchText("batch.summary.installing", l, { n: String(counts.installing) }));
|
|
66
|
+
if (counts.pending > 0) parts.push(batchText("batch.summary.pending", l, { n: String(counts.pending) }));
|
|
67
|
+
if (counts.restart > 0) parts.push(batchText("batch.summary.restart", l, { n: String(counts.restart) }));
|
|
68
|
+
if (counts.failed > 0) parts.push(batchText("batch.summary.failed", l, { n: String(counts.failed) }));
|
|
69
|
+
if (counts.skipped > 0) parts.push(batchText("batch.summary.skipped", l, { n: String(counts.skipped) }));
|
|
70
|
+
if (counts.settled > 0) parts.push(batchText("batch.summary.settled", l, { n: String(counts.settled) }));
|
|
71
|
+
return parts.length > 0 ? parts.join(" \xB7 ") : batchText("batch.summary.empty", l);
|
|
66
72
|
}
|
|
67
|
-
function batchQueuedStatus(position) {
|
|
68
|
-
|
|
69
|
-
|
|
73
|
+
function batchQueuedStatus(position, lang) {
|
|
74
|
+
const l = langOf(lang);
|
|
75
|
+
if (typeof position !== "number" || !Number.isFinite(position) || position < 1) return batchText("batch.row.queued-generic", l);
|
|
76
|
+
return batchText("batch.row.queued-n", l, { n: String(position) });
|
|
70
77
|
}
|
|
71
|
-
function
|
|
78
|
+
function knowledgeEntryOf(inventory, key) {
|
|
79
|
+
if (!isObject(inventory)) return null;
|
|
80
|
+
const entries = inventory["entries"];
|
|
81
|
+
if (!isObject(entries)) return null;
|
|
82
|
+
const item = entries[key];
|
|
83
|
+
if (!isObject(item)) return null;
|
|
84
|
+
const e = item;
|
|
85
|
+
const canInstallRaw = e["canInstall"];
|
|
86
|
+
return {
|
|
87
|
+
lastCheckedAt: typeof e["lastCheckedAt"] === "number" ? e["lastCheckedAt"] : 0,
|
|
88
|
+
installedVersion: typeof e["installedVersion"] === "string" ? e["installedVersion"] : null,
|
|
89
|
+
latestVersion: typeof e["latestVersion"] === "string" ? e["latestVersion"] : null,
|
|
90
|
+
canInstall: typeof canInstallRaw === "boolean" ? canInstallRaw : null,
|
|
91
|
+
error: typeof e["error"] === "string" ? e["error"] : null
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
function langOf(lang) {
|
|
95
|
+
try {
|
|
96
|
+
return normalizeLangTag(typeof lang === "string" ? lang : resolveLang(lang));
|
|
97
|
+
} catch {
|
|
98
|
+
return "zh";
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
function batchText(key, lang, values) {
|
|
102
|
+
try {
|
|
103
|
+
return bilingualText(key, langOf(lang), values);
|
|
104
|
+
} catch {
|
|
105
|
+
return "";
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
function hasUnfinishedRows(rows, session) {
|
|
109
|
+
if (isObject(session)) {
|
|
110
|
+
const entries = session["entries"];
|
|
111
|
+
if (Array.isArray(entries)) {
|
|
112
|
+
for (const item of entries) {
|
|
113
|
+
if (!isObject(item)) continue;
|
|
114
|
+
const phase = item["phase"];
|
|
115
|
+
if (typeof phase === "string" && !isTerminalPhase(asBatchPhase(phase))) return true;
|
|
116
|
+
}
|
|
117
|
+
return false;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
if (rows.length === 0) return false;
|
|
121
|
+
return !rows.every((row) => isTerminalPhase(asBatchPhase(row.phase)));
|
|
122
|
+
}
|
|
123
|
+
function unfinishedCount(rows, session) {
|
|
124
|
+
if (isObject(session)) {
|
|
125
|
+
const entries = session["entries"];
|
|
126
|
+
if (Array.isArray(entries)) {
|
|
127
|
+
let n = 0;
|
|
128
|
+
for (const item of entries) {
|
|
129
|
+
if (!isObject(item)) continue;
|
|
130
|
+
const phase = item["phase"];
|
|
131
|
+
if (typeof phase === "string" && !isTerminalPhase(asBatchPhase(phase))) n += 1;
|
|
132
|
+
}
|
|
133
|
+
return n;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
return rows.filter((row) => !isTerminalPhase(asBatchPhase(row.phase))).length;
|
|
137
|
+
}
|
|
138
|
+
function batchRowStatus(row, skippedVersion, lang) {
|
|
139
|
+
const l = langOf(lang);
|
|
72
140
|
const skipped = typeof skippedVersion === "string" && skippedVersion ? skippedVersion : null;
|
|
73
|
-
if (skipped !== null && asBatchPhase(row.phase) === "ready") return "
|
|
141
|
+
if (skipped !== null && asBatchPhase(row.phase) === "ready") return batchText("batch.row.skipped", l, { version: skipped });
|
|
74
142
|
switch (asBatchPhase(row.phase)) {
|
|
75
143
|
case "pending":
|
|
76
|
-
return "
|
|
144
|
+
return batchText("batch.row.wait-turn", l);
|
|
77
145
|
case "checking":
|
|
78
|
-
return "
|
|
146
|
+
return batchText("batch.row.checking", l);
|
|
79
147
|
case "ready":
|
|
80
|
-
return row.targetVersion ? "
|
|
148
|
+
return row.targetVersion ? batchText("batch.row.cta-version", l, { version: row.targetVersion }) : batchText("batch.row.cta-generic", l);
|
|
81
149
|
case "installing":
|
|
82
|
-
return "
|
|
150
|
+
return batchText("batch.row.installing", l);
|
|
83
151
|
case "current":
|
|
84
|
-
return "
|
|
152
|
+
return batchText("batch.row.current", l);
|
|
85
153
|
case "done":
|
|
86
|
-
return row.restartRequired === true ? "
|
|
154
|
+
return row.restartRequired === true ? batchText("batch.row.done-restart", l) : batchText("batch.row.done", l);
|
|
87
155
|
case "failed":
|
|
88
|
-
return "
|
|
156
|
+
return batchText("batch.row.failed-retry", l);
|
|
89
157
|
case "skipped":
|
|
90
|
-
return "
|
|
158
|
+
return batchText("batch.row.skipped-idle", l);
|
|
91
159
|
default:
|
|
92
|
-
return "
|
|
160
|
+
return batchText("batch.row.unknown", l);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
function batchRowKnowledgeText(row, entry, lang) {
|
|
164
|
+
if (asBatchPhase(row.phase) !== "pending" || !entry) return null;
|
|
165
|
+
if (entry.error) return batchText("batch.row.failed", lang);
|
|
166
|
+
if (entry.latestVersion && entry.installedVersion && entry.latestVersion !== entry.installedVersion) {
|
|
167
|
+
return batchText("batch.row.update", lang, { version: entry.latestVersion });
|
|
168
|
+
}
|
|
169
|
+
if (entry.latestVersion && entry.installedVersion && entry.latestVersion === entry.installedVersion) {
|
|
170
|
+
return batchText("batch.row.current", lang);
|
|
171
|
+
}
|
|
172
|
+
if (entry.latestVersion && !entry.installedVersion) {
|
|
173
|
+
return batchText("batch.row.update", lang, { version: entry.latestVersion });
|
|
93
174
|
}
|
|
175
|
+
if (entry.lastCheckedAt > 0) return batchText("batch.row.current", lang);
|
|
176
|
+
return batchText("batch.row.never", lang);
|
|
94
177
|
}
|
|
95
178
|
function renderBatchPanelHTML(input) {
|
|
96
179
|
const rows = Array.isArray(input.rows) ? input.rows : [];
|
|
@@ -105,121 +188,161 @@ function renderBatchPanelHTML(input) {
|
|
|
105
188
|
const installing = counts.installing > 0;
|
|
106
189
|
const macroBusy = input.inFlight === true || installing;
|
|
107
190
|
const total = rows.length;
|
|
108
|
-
const terminal = total > 0 && rows.every((row) => isTerminalPhase(asBatchPhase(row.phase)));
|
|
109
|
-
const stalled = total > 0 && !terminal && !rows.some((row) => {
|
|
110
|
-
const phase = asBatchPhase(row.phase);
|
|
111
|
-
return phase === "installing" || phase === "checking";
|
|
112
|
-
});
|
|
113
191
|
const disabled = macroBusy ? " disabled" : "";
|
|
114
192
|
const notice = typeof input.notice === "string" && input.notice ? input.notice : null;
|
|
115
193
|
const noticeKey = typeof input.noticeKey === "string" && input.noticeKey ? input.noticeKey : null;
|
|
116
194
|
const detailNoticeKey = notice !== null && noticeKey !== null && noticeKey === expandedKey ? noticeKey : null;
|
|
117
195
|
const changelogs = input.changelogs && typeof input.changelogs === "object" ? input.changelogs : {};
|
|
196
|
+
const lang = langOf(input["lang"]);
|
|
118
197
|
const ctx = {
|
|
119
198
|
expanded: false,
|
|
120
199
|
busy: installing,
|
|
121
200
|
inFlight: input.inFlight === true,
|
|
122
201
|
theme,
|
|
202
|
+
themeTokens: input.themeTokens ?? void 0,
|
|
123
203
|
titles,
|
|
124
204
|
skipped: null,
|
|
125
205
|
notice: null,
|
|
126
|
-
changelogMarkdown: null
|
|
206
|
+
changelogMarkdown: null,
|
|
207
|
+
lang,
|
|
208
|
+
knowledge: null,
|
|
209
|
+
inRound: false
|
|
127
210
|
};
|
|
128
211
|
const parts = [];
|
|
129
212
|
parts.push('<div class="dsh-upd-batch-head">');
|
|
130
|
-
parts.push('<div class="dsh-upd-batch-title"
|
|
213
|
+
parts.push('<div class="dsh-upd-batch-title">' + escapeHtml(batchText("batch.header.title", lang)) + " \xB7 <i>" + escapeHtml(batchText("batch.seal.ledger", lang)) + "</i></div>");
|
|
131
214
|
parts.push('<div class="dsh-upd-batch-macros">');
|
|
132
|
-
parts.push('<button type="button" data-act="check"' + disabled + ' title="
|
|
133
|
-
parts.push('<button type="button" data-act="install" data-primary="1"' + disabled + ' title="
|
|
134
|
-
if (mode === "dialog") parts.push('<button type="button" data-act="close" title="
|
|
215
|
+
parts.push('<button type="button" data-act="check"' + disabled + ' title="' + escapeHtml(batchText("batch.action.check-title", lang)) + '">' + escapeHtml(batchText("batch.action.check", lang)) + "</button>");
|
|
216
|
+
parts.push('<button type="button" data-act="install" data-primary="1"' + disabled + ' title="' + escapeHtml(batchText("batch.action.install-all-title", lang)) + '">' + escapeHtml(batchText("batch.action.install-all", lang)) + "</button>");
|
|
217
|
+
if (mode === "dialog") parts.push('<button type="button" data-act="close" title="' + escapeHtml(batchText("batch.action.close-title", lang)) + '">' + escapeHtml(batchText("batch.action.close", lang)) + "</button>");
|
|
135
218
|
parts.push("</div>");
|
|
136
219
|
parts.push("</div>");
|
|
137
|
-
const summary = loaded ? batchSummaryText(counts, rows, total, installing, lastError !== null) : "
|
|
220
|
+
const summary = loaded ? batchSummaryText(counts, rows, total, installing, lastError !== null, lang) : batchText("batch.banner.loading", lang);
|
|
138
221
|
parts.push('<div class="dsh-upd-batch-sum" role="status" aria-live="polite">' + escapeHtml(summary) + "</div>");
|
|
139
|
-
parts.push(bannersHTML(rows, titles, lastError));
|
|
222
|
+
parts.push(bannersHTML(rows, titles, lastError, lang));
|
|
223
|
+
const session = isObject(input.session) ? input.session : null;
|
|
224
|
+
const unfinished = unfinishedCount(rows, session ?? void 0);
|
|
225
|
+
const showControls = total > 0 && hasUnfinishedRows(rows, session ?? void 0);
|
|
226
|
+
const prefs = isObject(input.prefs) ? input.prefs : null;
|
|
227
|
+
const checkOnOpen = prefs === null ? null : prefs["checkOnOpen"] === false ? false : true;
|
|
228
|
+
function roundEntryPhase(key) {
|
|
229
|
+
if (!session) return null;
|
|
230
|
+
const entries = session["entries"];
|
|
231
|
+
if (!Array.isArray(entries)) return null;
|
|
232
|
+
for (const item of entries) {
|
|
233
|
+
if (!isObject(item)) continue;
|
|
234
|
+
const e = item;
|
|
235
|
+
if (e["key"] === key && typeof e["phase"] === "string") return e["phase"];
|
|
236
|
+
}
|
|
237
|
+
return null;
|
|
238
|
+
}
|
|
140
239
|
parts.push('<div class="dsh-upd-btable">');
|
|
141
240
|
for (const row of rows) {
|
|
142
241
|
const raw = skippedVersions[row.key];
|
|
143
242
|
const skipped = typeof raw === "string" && raw ? raw : null;
|
|
144
243
|
const expanded = row.key === expandedKey;
|
|
244
|
+
const entryPhase = roundEntryPhase(row.key);
|
|
245
|
+
const inRound = entryPhase !== null && !isTerminalPhase(asBatchPhase(entryPhase));
|
|
145
246
|
parts.push(
|
|
146
247
|
rowSetHTML(row, {
|
|
147
248
|
...ctx,
|
|
148
249
|
expanded,
|
|
149
250
|
skipped,
|
|
150
251
|
notice: expanded && row.key === detailNoticeKey ? notice : null,
|
|
151
|
-
changelogMarkdown: expanded && typeof changelogs[row.key] === "string" ? changelogs[row.key] : null
|
|
252
|
+
changelogMarkdown: expanded && typeof changelogs[row.key] === "string" ? changelogs[row.key] : null,
|
|
253
|
+
lang,
|
|
254
|
+
knowledge: asBatchPhase(row.phase) === "pending" && !inRound ? knowledgeEntryOf(input.inventory, row.key) : null,
|
|
255
|
+
inRound
|
|
152
256
|
})
|
|
153
257
|
);
|
|
154
258
|
}
|
|
155
259
|
parts.push("</div>");
|
|
156
260
|
if (total > 0) {
|
|
157
|
-
parts.push('<div class="dsh-upd-batch-ledger">' + escapeHtml(batchLedgerText(counts)) + "</div>");
|
|
261
|
+
parts.push('<div class="dsh-upd-batch-ledger">' + escapeHtml(batchLedgerText(counts, lang)) + "</div>");
|
|
158
262
|
}
|
|
159
|
-
if (
|
|
263
|
+
if (showControls) {
|
|
160
264
|
const more = [];
|
|
161
|
-
|
|
265
|
+
more.push(
|
|
266
|
+
'<button type="button" data-act="resume">' + escapeHtml(batchText("batch.action.resume", lang, { count: String(unfinished) })) + "</button>"
|
|
267
|
+
);
|
|
162
268
|
const confirmCancel = input.confirmCancel === true;
|
|
269
|
+
const discardLabel = confirmCancel ? batchText("batch.action.confirm-discard", lang) : batchText("batch.action.discard", lang);
|
|
163
270
|
more.push(
|
|
164
|
-
'<button type="button" data-act="cancel"' + disabled + (confirmCancel ? ' data-confirm="1" title="
|
|
271
|
+
'<button type="button" data-act="cancel"' + disabled + (confirmCancel ? ' data-confirm="1" title="' + escapeHtml(batchText("batch.notice.cancel-confirm", lang)) + '"' : ' title="' + escapeHtml(batchText("batch.action.discard", lang)) + '"') + ">" + escapeHtml(discardLabel) + "</button>"
|
|
165
272
|
);
|
|
166
273
|
parts.push('<div class="dsh-upd-batch-more">' + more.join("") + "</div>");
|
|
274
|
+
parts.push('<div class="dsh-upd-batch-fact" role="note">' + escapeHtml(batchText("batch.fact.close-safe", lang)) + "</div>");
|
|
275
|
+
if (macroBusy) {
|
|
276
|
+
parts.push('<div class="dsh-upd-batch-fact" role="note">' + escapeHtml(batchText("batch.notice.busy-cancel", lang)) + "</div>");
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
if (prefs !== null && checkOnOpen !== null) {
|
|
280
|
+
parts.push(
|
|
281
|
+
'<div class="dsh-upd-batch-prefs"><button type="button" data-act="toggle-check-on-open" aria-pressed="' + (checkOnOpen ? "true" : "false") + '">' + escapeHtml((checkOnOpen ? "[x] " : "[ ] ") + batchText("batch.setting.check-on-open", lang)) + "</button></div>"
|
|
282
|
+
);
|
|
167
283
|
}
|
|
168
284
|
if (notice !== null && detailNoticeKey === null) {
|
|
169
285
|
parts.push('<div class="dsh-upd-batch-notice" role="status">' + escapeHtml(notice) + "</div>");
|
|
170
286
|
}
|
|
171
287
|
const kernel = parts.join(String.fromCharCode(10));
|
|
172
|
-
const
|
|
173
|
-
const attr =
|
|
174
|
-
const
|
|
175
|
-
const
|
|
288
|
+
const archive = normalizePanelTheme(theme) === "archive";
|
|
289
|
+
const attr = archive ? ' data-theme="archive"' : "";
|
|
290
|
+
const tokensStyle = themeTokensStyleFor(input.themeTokens ?? void 0);
|
|
291
|
+
const tokensAttr = tokensStyle ? ' style="' + tokensStyle + '"' : "";
|
|
292
|
+
const seal = batchSealOf(counts, lang);
|
|
293
|
+
const root = '<div class="dsh-upd dsh-upd-batch" data-mode="' + mode + '" data-seal="' + escapeHtml(seal.text) + '" data-seal-tone="' + seal.tone + '"' + attr + tokensAttr + ">\n" + kernel + "\n</div>";
|
|
176
294
|
const body = mode === "dialog" ? '<div class="dsh-upd-overlay" data-mode="dialog">' + root + "</div>" : root;
|
|
177
|
-
const css =
|
|
295
|
+
const css = archive ? [UPDATE_PANEL_CSS, UPDATE_BATCH_PANEL_CSS, UPDATE_PANEL_ARCHIVE_CSS, UPDATE_BATCH_PANEL_ARCHIVE_CSS].join(String.fromCharCode(10)) : [UPDATE_PANEL_CSS, UPDATE_BATCH_PANEL_CSS].join(String.fromCharCode(10));
|
|
178
296
|
return "<style>" + css + "</style>\n" + body;
|
|
179
297
|
}
|
|
180
|
-
function batchSummaryText(counts, rows, total, installing, hasError) {
|
|
181
|
-
|
|
182
|
-
if (
|
|
298
|
+
function batchSummaryText(counts, rows, total, installing, hasError, lang) {
|
|
299
|
+
const l = langOf(lang);
|
|
300
|
+
if (hasError) return batchText("batch.hint.error", l);
|
|
301
|
+
if (total === 0) return batchText("batch.hint.empty", l);
|
|
183
302
|
if (installing) {
|
|
184
303
|
const canQueue = rows.filter((row) => asBatchPhase(row.phase) === "ready" && !isQueuedRow(row)).length;
|
|
185
|
-
return canQueue > 0 ? "
|
|
304
|
+
return canQueue > 0 ? batchText("batch.hint.installing-queueable", l, { a: String(counts.installing), b: String(canQueue) }) : batchText("batch.hint.installing-auto", l, { a: String(counts.installing) });
|
|
186
305
|
}
|
|
187
|
-
if (counts.failed > 0) return
|
|
306
|
+
if (counts.failed > 0) return batchText("batch.hint.failed", l, { n: String(counts.failed) });
|
|
188
307
|
if (counts.updatable > 0)
|
|
189
|
-
return
|
|
190
|
-
if (counts.restart > 0) return
|
|
191
|
-
if (counts.pending > 0) return
|
|
192
|
-
return "
|
|
308
|
+
return batchText("batch.hint.updatable", l, { n: String(counts.updatable) });
|
|
309
|
+
if (counts.restart > 0) return batchText("batch.hint.restart", l, { n: String(counts.restart) });
|
|
310
|
+
if (counts.pending > 0) return batchText("batch.hint.pending", l, { n: String(counts.pending) });
|
|
311
|
+
return batchText("batch.hint.done", l);
|
|
193
312
|
}
|
|
194
|
-
function batchSealOf(counts) {
|
|
195
|
-
|
|
196
|
-
if (counts.
|
|
197
|
-
if (counts.
|
|
198
|
-
return { text
|
|
313
|
+
function batchSealOf(counts, lang) {
|
|
314
|
+
const text = batchText("batch.seal.ledger", langOf(lang));
|
|
315
|
+
if (counts.failed > 0) return { text, tone: "red" };
|
|
316
|
+
if (counts.installing > 0 || counts.restart > 0) return { text, tone: "yellow" };
|
|
317
|
+
if (counts.updatable > 0) return { text, tone: "green" };
|
|
318
|
+
return { text, tone: "ink" };
|
|
199
319
|
}
|
|
200
|
-
function bannersHTML(rows, titles, lastError) {
|
|
320
|
+
function bannersHTML(rows, titles, lastError, lang) {
|
|
321
|
+
const l = langOf(lang);
|
|
201
322
|
const parts = [];
|
|
202
323
|
if (lastError) {
|
|
203
|
-
const copy = failureCopy(lastError);
|
|
324
|
+
const copy = failureCopy(lastError, l);
|
|
325
|
+
const detail = copy?.zh ?? failureCopy("unknown", l)?.zh ?? "";
|
|
326
|
+
const act = copy?.act ?? batchText("batch.banner.error-action-fallback", l);
|
|
204
327
|
parts.push(
|
|
205
|
-
'<div class="dsh-upd-banner" data-kind="failed" data-mini="\u963B" role="status"><div><strong
|
|
328
|
+
'<div class="dsh-upd-banner" data-kind="failed" data-mini="\u963B" role="status"><div><strong>' + escapeHtml(batchText("batch.banner.error-title", l, { code: lastError, detail })) + "</strong></div><div>" + escapeHtml(act) + "</div></div>"
|
|
206
329
|
);
|
|
207
330
|
}
|
|
208
331
|
const failed = rows.filter((row) => asBatchPhase(row.phase) === "failed" && !isQueueBusyRow(row));
|
|
209
332
|
if (failed.length > 0) {
|
|
210
333
|
const lines = failed.map((row) => {
|
|
211
334
|
const code = row.error || "install-failed";
|
|
212
|
-
const copy = failureCopy(code);
|
|
213
|
-
return "<div>" + escapeHtml(titleOf(row, titles)) + "\uFF1A<code>" + escapeHtml(code) + "</code> " + escapeHtml(copy
|
|
335
|
+
const copy = failureCopy(code, l);
|
|
336
|
+
return "<div>" + escapeHtml(titleOf(row, titles)) + "\uFF1A<code>" + escapeHtml(code) + "</code> " + escapeHtml(copy?.zh ?? failureCopy("unknown", l)?.zh ?? "") + "</div>";
|
|
214
337
|
}).join("");
|
|
215
338
|
parts.push(
|
|
216
|
-
'<div class="dsh-upd-banner" data-kind="failed" data-mini="\u963B" role="status"><div><strong>' + failed.length +
|
|
339
|
+
'<div class="dsh-upd-banner" data-kind="failed" data-mini="\u963B" role="status"><div><strong>' + escapeHtml(batchText("batch.banner.failed-title", l, { n: String(failed.length) })) + "</strong></div><div>" + escapeHtml(batchText("batch.banner.failed-action", l)) + '</div><div class="dsh-upd-blist">' + lines + "</div></div>"
|
|
217
340
|
);
|
|
218
341
|
}
|
|
219
342
|
const restart = rows.filter((row) => row.restartRequired === true);
|
|
220
343
|
if (restart.length > 0) {
|
|
221
344
|
parts.push(
|
|
222
|
-
'<div class="dsh-upd-banner" data-kind="restart" role="status"><div><strong>' + restart.length +
|
|
345
|
+
'<div class="dsh-upd-banner" data-kind="restart" role="status"><div><strong>' + escapeHtml(batchText("batch.banner.restart-title", l, { n: String(restart.length) })) + "</strong></div><div>" + escapeHtml(batchText("batch.banner.restart-action", l)) + '</div><div class="dsh-upd-blist">' + restart.map((row) => escapeHtml(titleOf(row, titles))).join("\u3001") + '</div><div><button type="button" data-act="restart" data-primary="1">' + escapeHtml(batchText("batch.banner.restart-button", l)) + "</button></div></div>"
|
|
223
346
|
);
|
|
224
347
|
}
|
|
225
348
|
return parts.join("");
|
|
@@ -236,35 +359,43 @@ function rowSetHTML(row, ctx) {
|
|
|
236
359
|
const off = ctx.inFlight ? " disabled" : "";
|
|
237
360
|
if (phase === "installing") {
|
|
238
361
|
actions.push(
|
|
239
|
-
'<button type="button" data-act="row-install" data-key="' + keyAttr + '" disabled
|
|
362
|
+
'<button type="button" data-act="row-install" data-key="' + keyAttr + '" disabled>' + escapeHtml(batchText("batch.row-action.installing", ctx.lang)) + "</button>"
|
|
240
363
|
);
|
|
241
364
|
} else if (queued) {
|
|
242
365
|
if (cancelQueuePhoneOf(row) !== null && queuedRequestIdOf(row) !== null) {
|
|
243
366
|
actions.push(
|
|
244
|
-
'<button type="button" data-act="row-cancel-queue" data-key="' + keyAttr + '"' + off + "
|
|
367
|
+
'<button type="button" data-act="row-cancel-queue" data-key="' + keyAttr + '"' + off + ">" + escapeHtml(batchText("batch.row-action.cancel-queue", ctx.lang)) + "</button>"
|
|
245
368
|
);
|
|
246
369
|
}
|
|
247
370
|
} else if (phase === "ready" && skipped === null) {
|
|
248
371
|
actions.push(
|
|
249
|
-
'<button type="button" data-act="row-install" data-key="' + keyAttr + '" data-primary="1"' + off + ">" + (ctx.busy ? "
|
|
372
|
+
'<button type="button" data-act="row-install" data-key="' + keyAttr + '" data-primary="1"' + off + ">" + escapeHtml(ctx.busy ? batchText("batch.row-action.queue", ctx.lang) : batchText("batch.row-action.install-row", ctx.lang)) + "</button>"
|
|
250
373
|
);
|
|
251
374
|
} else if (phase === "ready" && skipped !== null) {
|
|
252
375
|
actions.push(
|
|
253
|
-
'<button type="button" data-act="row-resume-skip" data-key="' + keyAttr + '"' + off + "
|
|
376
|
+
'<button type="button" data-act="row-resume-skip" data-key="' + keyAttr + '"' + off + ">" + escapeHtml(batchText("batch.row-action.unskip", ctx.lang, { version: skipped })) + "</button>"
|
|
254
377
|
);
|
|
255
378
|
} else if (phase === "failed") {
|
|
256
379
|
actions.push(
|
|
257
|
-
'<button type="button" data-act="row-install" data-key="' + keyAttr + '"' + off + ">" + (ctx.busy ? "
|
|
380
|
+
'<button type="button" data-act="row-install" data-key="' + keyAttr + '"' + off + ">" + escapeHtml(ctx.busy ? batchText("batch.row-action.queue", ctx.lang) : batchText("batch.row-action.retry", ctx.lang)) + "</button>"
|
|
258
381
|
);
|
|
259
382
|
}
|
|
260
383
|
if (row.restartRequired === true) {
|
|
261
|
-
actions.push('<button type="button" data-act="restart" data-key="' + keyAttr + '"
|
|
384
|
+
actions.push('<button type="button" data-act="restart" data-key="' + keyAttr + '">' + escapeHtml(batchText("batch.row-action.restart", ctx.lang)) + "</button>");
|
|
262
385
|
}
|
|
263
386
|
actions.push(
|
|
264
|
-
'<button type="button" data-act="toggle-details" data-key="' + keyAttr + '">' + (ctx.expanded ? "
|
|
387
|
+
'<button type="button" data-act="toggle-details" data-key="' + keyAttr + '">' + escapeHtml(ctx.expanded ? batchText("batch.row-action.hide-detail", ctx.lang) : batchText("batch.row-action.show-detail", ctx.lang)) + "</button>"
|
|
265
388
|
);
|
|
266
|
-
const failLine = phase === "failed" && !queued ?
|
|
267
|
-
|
|
389
|
+
const failLine = phase === "failed" && !queued ? (() => {
|
|
390
|
+
const failCode = row.error || "install-failed";
|
|
391
|
+
const failDetail = failureCopy(failCode, ctx.lang)?.zh ?? failureCopy("unknown", ctx.lang)?.zh ?? "";
|
|
392
|
+
const label = batchText("batch.row.error-label", ctx.lang, { code: failCode, detail: failDetail });
|
|
393
|
+
const escaped = escapeHtml(label);
|
|
394
|
+
const codeEsc = escapeHtml(failCode);
|
|
395
|
+
const withCode = escaped.includes(codeEsc) ? escaped.replace(codeEsc, "<code>" + codeEsc + "</code>") : escaped;
|
|
396
|
+
return '<span class="dsh-upd-bfail">' + withCode + "</span>";
|
|
397
|
+
})() : "";
|
|
398
|
+
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) + '"></span><span class="dsh-upd-bname">' + escapeHtml(titleOf(row, ctx.titles)) + "</span>" + (version ? '<span class="dsh-upd-bver">' + escapeHtml(version) + "</span>" : "") + '<span class="dsh-upd-bstat">' + escapeHtml(queued ? batchQueuedStatus(position, ctx.lang) : batchRowKnowledgeText(row, ctx.knowledge, ctx.lang) ?? batchRowStatus(row, skipped, ctx.lang)) + (ctx.inRound && !queued ? "\uFF08" + escapeHtml(batchText("batch.row.unfinished-tag", ctx.lang)) + "\uFF09" : "") + "</span>" + failLine + "</button>";
|
|
268
399
|
const detail = ctx.expanded ? '<div class="dsh-upd-bdetail" data-key="' + keyAttr + '">' + detailActionsHTML(row, ctx) + (ctx.notice !== null ? '<div class="dsh-upd-bdetail-notice" role="status">' + escapeHtml(ctx.notice) + "</div>" : "") + detailHTML(row, ctx) + "</div>" : "";
|
|
269
400
|
return '<div class="dsh-upd-brow-set" data-key="' + keyAttr + '"><div class="dsh-upd-brow" data-phase="' + escapeHtml(phase) + '" data-key="' + keyAttr + '"' + (queued ? ' data-queued="1"' : "") + ">" + main + '<span class="dsh-upd-brow-actions">' + actions.join("") + "</span></div>" + detail + "</div>";
|
|
270
401
|
}
|
|
@@ -284,9 +415,10 @@ function detailHTML(row, ctx) {
|
|
|
284
415
|
pluginId: pluginIdOf(row),
|
|
285
416
|
copyNotice: null,
|
|
286
417
|
theme: ctx.theme,
|
|
418
|
+
themeTokens: ctx.themeTokens,
|
|
287
419
|
profileName: typeof row.profileName === "string" && row.profileName ? row.profileName : null,
|
|
288
420
|
actions: "none"
|
|
289
|
-
});
|
|
421
|
+
}, ctx.lang);
|
|
290
422
|
return stripActionButtons(html);
|
|
291
423
|
}
|
|
292
424
|
function detailActionsHTML(row, ctx) {
|
|
@@ -297,38 +429,38 @@ function detailActionsHTML(row, ctx) {
|
|
|
297
429
|
const off = ctx.inFlight ? " disabled" : "";
|
|
298
430
|
const buttons = [];
|
|
299
431
|
if (phase === "installing") {
|
|
300
|
-
buttons.push('<button type="button" data-act="row-install" data-key="' + keyAttr + '" disabled
|
|
432
|
+
buttons.push('<button type="button" data-act="row-install" data-key="' + keyAttr + '" disabled>' + escapeHtml(batchText("batch.row-action.installing", ctx.lang)) + "</button>");
|
|
301
433
|
} else if (queued) {
|
|
302
434
|
if (cancelQueuePhoneOf(row) !== null && queuedRequestIdOf(row) !== null) {
|
|
303
435
|
buttons.push(
|
|
304
|
-
'<button type="button" data-act="row-cancel-queue" data-key="' + keyAttr + '"' + off + "
|
|
436
|
+
'<button type="button" data-act="row-cancel-queue" data-key="' + keyAttr + '"' + off + ">" + escapeHtml(batchText("batch.row-action.cancel-queue", ctx.lang)) + "</button>"
|
|
305
437
|
);
|
|
306
438
|
}
|
|
307
439
|
} else if (phase === "failed") {
|
|
308
440
|
buttons.push(
|
|
309
|
-
'<button type="button" data-act="row-install" data-key="' + keyAttr + '"' + off + ">" + (ctx.busy ? "
|
|
441
|
+
'<button type="button" data-act="row-install" data-key="' + keyAttr + '"' + off + ">" + escapeHtml(ctx.busy ? batchText("batch.row-action.queue", ctx.lang) : batchText("batch.row-action.retry", ctx.lang)) + "</button>"
|
|
310
442
|
);
|
|
311
443
|
} else if (phase === "ready" && ctx.skipped === null) {
|
|
312
444
|
buttons.push(
|
|
313
|
-
'<button type="button" data-act="row-install" data-key="' + keyAttr + '" data-primary="1"' + off + ">" + (ctx.busy ? "
|
|
445
|
+
'<button type="button" data-act="row-install" data-key="' + keyAttr + '" data-primary="1"' + off + ">" + escapeHtml(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>"
|
|
314
446
|
);
|
|
315
447
|
}
|
|
316
448
|
if (!queued && phase === "ready" && ctx.skipped === null && version !== null) {
|
|
317
449
|
buttons.push(
|
|
318
|
-
'<button type="button" data-act="row-skip" data-key="' + keyAttr + '"' + off + "
|
|
450
|
+
'<button type="button" data-act="row-skip" data-key="' + keyAttr + '"' + off + ">" + escapeHtml(batchText("batch.row-action.skip", ctx.lang)) + "</button>"
|
|
319
451
|
);
|
|
320
452
|
}
|
|
321
453
|
if (ctx.skipped !== null) {
|
|
322
454
|
buttons.push(
|
|
323
|
-
'<button type="button" data-act="row-resume-skip" data-key="' + keyAttr + '"' + off + "
|
|
455
|
+
'<button type="button" data-act="row-resume-skip" data-key="' + keyAttr + '"' + off + ">" + escapeHtml(batchText("batch.row-action.unskip", ctx.lang, { version: ctx.skipped })) + "</button>"
|
|
324
456
|
);
|
|
325
457
|
}
|
|
326
458
|
if (typeof row.manual === "string" && row.manual) {
|
|
327
459
|
buttons.push(
|
|
328
|
-
'<button type="button" data-act="row-copy-manual" data-key="' + keyAttr + '"' + off + "
|
|
460
|
+
'<button type="button" data-act="row-copy-manual" data-key="' + keyAttr + '"' + off + ">" + escapeHtml(batchText("batch.row-action.copy-manual", ctx.lang)) + "</button>"
|
|
329
461
|
);
|
|
330
462
|
}
|
|
331
|
-
buttons.push('<button type="button" data-act="row-copy-diag" data-key="' + keyAttr + '"' + off + "
|
|
463
|
+
buttons.push('<button type="button" data-act="row-copy-diag" data-key="' + keyAttr + '"' + off + ">" + escapeHtml(batchText("batch.row-action.copy-diag", ctx.lang)) + "</button>");
|
|
332
464
|
return '<span class="dsh-upd-bdetail-actions">' + buttons.join("") + "</span>";
|
|
333
465
|
}
|
|
334
466
|
function stripActionButtons(html) {
|
|
@@ -344,37 +476,37 @@ function dotToneOf(row, phase, skipped, queued) {
|
|
|
344
476
|
return "idle";
|
|
345
477
|
}
|
|
346
478
|
const UPDATE_BATCH_PANEL_CSS = [
|
|
347
|
-
"/* \u6279\u91CF\u9762\u677F\uFF08#25\uFF09\uFF1A\u7C7B\u540D\u6CBF\u7528 dsh-upd-* \u524D\u7F00\uFF1B\u9ED8\u8BA4\uFF08\u6700\u5C0F\uFF09\u4E3B\u9898\
|
|
479
|
+
"/* \u6279\u91CF\u9762\u677F\uFF08#25\uFF09\uFF1A\u7C7B\u540D\u6CBF\u7528 dsh-upd-* \u524D\u7F00\uFF1B\u9ED8\u8BA4\uFF08\u6700\u5C0F\uFF09\u4E3B\u9898\uFF0CArchive \u76AE\u80A4\u89C1 UPDATE_BATCH_PANEL_ARCHIVE_CSS\u3002 */",
|
|
348
480
|
".dsh-upd-batch-head{display:flex;align-items:baseline;justify-content:space-between;gap:10px;flex-wrap:wrap}",
|
|
349
481
|
".dsh-upd-batch-title{font-weight:700;font-size:15px;letter-spacing:.06em}",
|
|
350
|
-
".dsh-upd-batch-title i{font-style:normal;color:var(--dsh-
|
|
482
|
+
".dsh-upd-batch-title i{font-style:normal;color:var(--dsh-update-primary,#2563eb)}",
|
|
351
483
|
".dsh-upd-batch-macros{flex:none}",
|
|
352
484
|
".dsh-upd-batch-sum{margin:4px 0 8px;font-size:13.5px}",
|
|
353
485
|
".dsh-upd-btable{margin-top:2px}",
|
|
354
|
-
".dsh-upd-brow-set{border-top:1px solid var(--dsh-
|
|
486
|
+
".dsh-upd-brow-set{border-top:1px solid var(--dsh-update-border,#e5e7eb)}",
|
|
355
487
|
".dsh-upd-brow-set:first-child{border-top:0}",
|
|
356
488
|
".dsh-upd-brow{display:flex;align-items:center;gap:8px;flex-wrap:wrap;padding:6px 0}",
|
|
357
489
|
".dsh-upd .dsh-upd-brow-main{display:flex;align-items:center;gap:8px;flex-wrap:wrap;flex:1 1 260px;min-width:0;",
|
|
358
490
|
"text-align:left;cursor:pointer;color:inherit;font:inherit;background:transparent;border:0;padding:2px 0;margin:0}",
|
|
359
|
-
".dsh-upd .dsh-upd-brow-main:hover{color:var(--dsh-
|
|
491
|
+
".dsh-upd .dsh-upd-brow-main:hover{color:var(--dsh-update-primary,#2563eb)}",
|
|
360
492
|
".dsh-upd-brow-actions{flex:none;margin-left:auto}",
|
|
361
493
|
".dsh-upd-brow-actions button{font-size:12.5px}",
|
|
362
|
-
".dsh-upd-updot{width:8px;height:8px;border-radius:50%;flex:none;background:var(--dsh-
|
|
363
|
-
'.dsh-upd-updot[data-tone="todo"]{background:var(--dsh-
|
|
364
|
-
'.dsh-upd-updot[data-tone="ok"]{background:var(--dsh-
|
|
365
|
-
'.dsh-upd-updot[data-tone="busy"]{background:var(--dsh-
|
|
366
|
-
'.dsh-upd-updot[data-tone="warn"]{background:var(--dsh-
|
|
367
|
-
'.dsh-upd-updot[data-tone="bad"]{background:var(--dsh-
|
|
494
|
+
".dsh-upd-updot{width:8px;height:8px;border-radius:50%;flex:none;background:var(--dsh-update-border,#9ca3af);opacity:.55}",
|
|
495
|
+
'.dsh-upd-updot[data-tone="todo"]{background:var(--dsh-update-ok-border,#059669);opacity:1}',
|
|
496
|
+
'.dsh-upd-updot[data-tone="ok"]{background:var(--dsh-update-ok-border,#059669);opacity:1}',
|
|
497
|
+
'.dsh-upd-updot[data-tone="busy"]{background:var(--dsh-update-busy-border,#2563eb);opacity:1}',
|
|
498
|
+
'.dsh-upd-updot[data-tone="warn"]{background:var(--dsh-update-warn-border,#d97706);opacity:1}',
|
|
499
|
+
'.dsh-upd-updot[data-tone="bad"]{background:var(--dsh-update-bad-border,#dc2626);opacity:1}',
|
|
368
500
|
".dsh-upd-bname{font-weight:700;flex:none}",
|
|
369
501
|
".dsh-upd-bver{font-family:Consolas,Menlo,monospace;font-size:12px;opacity:.8;flex:none}",
|
|
370
502
|
".dsh-upd-bstat{font-size:12.5px;opacity:.9}",
|
|
371
|
-
".dsh-upd-bfail{flex:1 1 100%;display:block;font-size:12.5px;color:var(--dsh-
|
|
503
|
+
".dsh-upd-bfail{flex:1 1 100%;display:block;font-size:12.5px;color:var(--dsh-update-bad-border,#dc2626)}",
|
|
372
504
|
".dsh-upd-blist{font-size:12.5px;margin-top:2px}",
|
|
373
505
|
".dsh-upd-batch-ledger{margin:8px 0 0;font-size:13px;opacity:.85}",
|
|
374
506
|
".dsh-upd-batch-more{margin-top:6px}",
|
|
375
507
|
".dsh-upd-batch-more button{font-size:12px}",
|
|
376
508
|
// 确认态:红框红字,与「关闭」等中性按钮一眼区分;disabled 照旧置灰。
|
|
377
|
-
'.dsh-upd-batch-more button[data-confirm="1"]{border-color:var(--dsh-
|
|
509
|
+
'.dsh-upd-batch-more button[data-confirm="1"]{border-color:var(--dsh-update-bad-border,#dc2626);color:var(--dsh-update-bad-border,#dc2626)}',
|
|
378
510
|
".dsh-upd-batch-notice{margin-top:6px;font-size:12.5px;opacity:.85}",
|
|
379
511
|
".dsh-upd-bdetail-actions{margin:0 0 6px}",
|
|
380
512
|
".dsh-upd .dsh-upd-bdetail-actions button{font-size:12.5px}",
|
|
@@ -385,21 +517,28 @@ const UPDATE_BATCH_PANEL_CSS = [
|
|
|
385
517
|
".dsh-upd-overlay .dsh-upd-bdetail .dsh-upd{max-height:none;overflow:visible}",
|
|
386
518
|
".dsh-upd-overlay .dsh-upd-bdetail .dsh-upd-body{overflow:visible}",
|
|
387
519
|
".dsh-upd-overlay .dsh-upd-bdetail .dsh-upd-body .dsh-upd-chap-head{position:static}",
|
|
388
|
-
"@media (prefers-color-scheme: dark){.dsh-upd-batch-title i{color:var(--dsh-
|
|
389
|
-
"@media (prefers-reduced-motion: reduce){.dsh-upd-batch *{transition:none !important;animation:none !important}}"
|
|
520
|
+
"@media (prefers-color-scheme: dark){.dsh-upd-batch-title i{color:var(--dsh-update-focus,#93c5fd)}}",
|
|
521
|
+
"@media (prefers-reduced-motion: reduce){.dsh-upd-batch *{transition:none !important;animation:none !important}}",
|
|
522
|
+
// Batch check layout stability: reserve macro width + rows/summary heights + no scroll anchoring jumps.
|
|
523
|
+
".dsh-upd-batch{overflow-anchor:none}",
|
|
524
|
+
".dsh-upd-btable{overflow-anchor:none}",
|
|
525
|
+
".dsh-upd-batch-macros{display:flex;flex-wrap:wrap;align-items:center;gap:0}",
|
|
526
|
+
'.dsh-upd-batch-macros button:first-child,.dsh-upd-batch-macros button[data-primary="1"]{min-width:6em;text-align:center}',
|
|
527
|
+
".dsh-upd-batch-sum,.dsh-upd-batch-ledger{min-height:1.6em}",
|
|
528
|
+
".dsh-upd-brow{min-height:28px}"
|
|
390
529
|
].join(String.fromCharCode(10));
|
|
391
|
-
const
|
|
392
|
-
"/* \u6279\u91CF\u9762\u677F\u7684
|
|
530
|
+
const UPDATE_BATCH_PANEL_ARCHIVE_CSS = [
|
|
531
|
+
"/* \u6279\u91CF\u9762\u677F\u7684 Archive \u76AE\u80A4\uFF1A\u53EA\u6362\u989C\u8272/\u5B57\u4F53/\u95F4\u8DDD\uFF1B\u6839\u4E0A\u7684\u5927\u5370\u7AE0\u7531 UPDATE_PANEL_ARCHIVE_CSS \u8D1F\u8D23\u3002 */",
|
|
393
532
|
'.dsh-upd[data-theme="archive"] .dsh-upd-batch-head{padding-right:120px}',
|
|
394
|
-
'.dsh-upd[data-theme="archive"] .dsh-upd-batch-title{font-family:var(--
|
|
395
|
-
'.dsh-upd[data-theme="archive"] .dsh-upd-batch-title i{color:var(--
|
|
396
|
-
'.dsh-upd[data-theme="archive"] .dsh-upd-brow-main{background:transparent;border:0;color:var(--
|
|
397
|
-
'.dsh-upd[data-theme="archive"] .dsh-upd-brow-main:hover{color:var(--
|
|
398
|
-
'.dsh-upd[data-theme="archive"] .dsh-upd-bname{font-family:var(--
|
|
399
|
-
'.dsh-upd[data-theme="archive"] .dsh-upd-bver{font-family:var(--
|
|
400
|
-
'.dsh-upd[data-theme="archive"] .dsh-upd-batch-ledger{color:var(--
|
|
401
|
-
'.dsh-upd[data-theme="archive"] .dsh-upd-batch-sum{color:var(--
|
|
402
|
-
'.dsh-upd[data-theme="archive"] .dsh-upd-brow-set{border-top-color:var(--
|
|
533
|
+
'.dsh-upd[data-theme="archive"] .dsh-upd-batch-title{font-family:var(--dsh-update-font-serif);font-size:21px;letter-spacing:.04em}',
|
|
534
|
+
'.dsh-upd[data-theme="archive"] .dsh-upd-batch-title i{color:var(--dsh-update-primary)}',
|
|
535
|
+
'.dsh-upd[data-theme="archive"] .dsh-upd-brow-main{background:transparent;border:0;color:var(--dsh-update-text)}',
|
|
536
|
+
'.dsh-upd[data-theme="archive"] .dsh-upd-brow-main:hover{color:var(--dsh-update-primary)}',
|
|
537
|
+
'.dsh-upd[data-theme="archive"] .dsh-upd-bname{font-family:var(--dsh-update-font-serif)}',
|
|
538
|
+
'.dsh-upd[data-theme="archive"] .dsh-upd-bver{font-family:var(--dsh-update-font-mono);color:var(--dsh-update-text-muted)}',
|
|
539
|
+
'.dsh-upd[data-theme="archive"] .dsh-upd-batch-ledger{color:var(--dsh-update-text-muted)}',
|
|
540
|
+
'.dsh-upd[data-theme="archive"] .dsh-upd-batch-sum{color:var(--dsh-update-text)}',
|
|
541
|
+
'.dsh-upd[data-theme="archive"] .dsh-upd-brow-set{border-top-color:var(--dsh-update-border)}'
|
|
403
542
|
].join(String.fromCharCode(10));
|
|
404
543
|
function escapeHtml(text) {
|
|
405
544
|
return String(text).replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """);
|
|
@@ -513,14 +652,14 @@ function jobFailureOf(row) {
|
|
|
513
652
|
const detail = message.slice(at + 1).trim();
|
|
514
653
|
return { code: code || null, detail: detail || null };
|
|
515
654
|
}
|
|
516
|
-
function diagTextOf(row) {
|
|
655
|
+
function diagTextOf(row, lang) {
|
|
517
656
|
const snapshot = isObject(row.snapshot) ? row.snapshot : null;
|
|
518
657
|
const queue = isObject(row.queue) ? row.queue : null;
|
|
519
658
|
const diag = isObject(row.diag) ? row.diag : null;
|
|
520
659
|
const text = (value) => typeof value === "string" && value ? value : null;
|
|
521
660
|
const job = jobFailureOf(row);
|
|
522
661
|
const diagDetail = diag ? text(diag["detail"]) : null;
|
|
523
|
-
const detail = diagDetail !== null ? diagDetail : job !== null && job.detail !== null ? job.detail + "
|
|
662
|
+
const detail = diagDetail !== null ? diagDetail : job !== null && job.detail !== null ? job.detail + batchText("batch.diag.source-job", langOf(lang)) : null;
|
|
524
663
|
const input = {
|
|
525
664
|
pluginId: pluginIdOf(row),
|
|
526
665
|
code: job !== null && job.code !== null ? job.code : row.error || "check-failed",
|
|
@@ -532,7 +671,9 @@ function diagTextOf(row) {
|
|
|
532
671
|
queuePosition: queue && typeof queue["position"] === "number" ? queue["position"] : null,
|
|
533
672
|
manual: text(row.manual),
|
|
534
673
|
diag: row.diag ?? null,
|
|
535
|
-
profileName: text(row.profileName)
|
|
674
|
+
profileName: text(row.profileName),
|
|
675
|
+
// #63 透传语言(批量 en 跟随在 #64/#65 落;此处缺省 zh 零回归)。
|
|
676
|
+
lang: lang ?? "zh"
|
|
536
677
|
};
|
|
537
678
|
return buildDiagnosticText(input);
|
|
538
679
|
}
|
|
@@ -622,10 +763,12 @@ function mountUpdateBatchPanel(container, options) {
|
|
|
622
763
|
if (mode !== "embedded" && mode !== "dialog") {
|
|
623
764
|
throw new Error("[dsh-plugin-update] \u6446\u653E\u5F62\u6001\u975E\u6CD5\uFF1A\u53EA\u6536 embedded \u6216 dialog\uFF08\u6536\u5230 " + JSON.stringify(options.mode) + "\uFF09");
|
|
624
765
|
}
|
|
625
|
-
if (options.theme !== void 0 && options.theme !== "default" && options.theme !== "archive"
|
|
626
|
-
throw new Error("[dsh-plugin-update] \u4E3B\u9898\u975E\u6CD5\uFF1A\u53EA\u6536 default \u6216 archive\
|
|
766
|
+
if (options.theme !== void 0 && options.theme !== "default" && options.theme !== "archive") {
|
|
767
|
+
throw new Error("[dsh-plugin-update] \u4E3B\u9898\u975E\u6CD5\uFF1A\u53EA\u6536 default \u6216 archive\uFF08\u6536\u5230 " + JSON.stringify(options.theme) + "\uFF09");
|
|
627
768
|
}
|
|
628
769
|
let theme = normalizePanelTheme(options.theme ?? "default");
|
|
770
|
+
themeTokensStyleFor(options.themeTokens ?? void 0);
|
|
771
|
+
let themeTokens = options.themeTokens;
|
|
629
772
|
const call = options.call;
|
|
630
773
|
const titles = options.titles && typeof options.titles === "object" ? options.titles : {};
|
|
631
774
|
const onRestartRequested = options.onRestartRequested;
|
|
@@ -647,6 +790,18 @@ function mountUpdateBatchPanel(container, options) {
|
|
|
647
790
|
let refreshing = false;
|
|
648
791
|
let confirmCancelArmed = false;
|
|
649
792
|
let mounted = true;
|
|
793
|
+
const localeOpt = options["locale"];
|
|
794
|
+
function currentLang() {
|
|
795
|
+
return langOf(localeOpt);
|
|
796
|
+
}
|
|
797
|
+
const checkOnOpenOption = options["checkOnOpen"] !== false;
|
|
798
|
+
const autoResumeOption = options["autoResume"] !== false;
|
|
799
|
+
let lastSession = null;
|
|
800
|
+
let lastInventory = null;
|
|
801
|
+
let lastPrefs = null;
|
|
802
|
+
let lastCheckedAt = 0;
|
|
803
|
+
let autoCheckDone = false;
|
|
804
|
+
let autoResumeDone = false;
|
|
650
805
|
function changelogView() {
|
|
651
806
|
const out = {};
|
|
652
807
|
for (const row of rows) {
|
|
@@ -680,13 +835,13 @@ function mountUpdateBatchPanel(container, options) {
|
|
|
680
835
|
const failKey = key + "\0" + version;
|
|
681
836
|
const hasCache = false;
|
|
682
837
|
const failedAt = rowFailedAt.has(failKey) ? rowFailedAt.get(failKey) : null;
|
|
683
|
-
let
|
|
838
|
+
let nowMs2 = 0;
|
|
684
839
|
try {
|
|
685
|
-
|
|
840
|
+
nowMs2 = Date.now();
|
|
686
841
|
} catch {
|
|
687
|
-
|
|
842
|
+
nowMs2 = 0;
|
|
688
843
|
}
|
|
689
|
-
if (!shouldFetchChangelog({ hasCache, failedAt, now:
|
|
844
|
+
if (!shouldFetchChangelog({ hasCache, failedAt, now: nowMs2, isManual: false })) return;
|
|
690
845
|
} catch {
|
|
691
846
|
}
|
|
692
847
|
const phone2 = changelogPhoneOf(row);
|
|
@@ -727,12 +882,84 @@ function mountUpdateBatchPanel(container, options) {
|
|
|
727
882
|
}
|
|
728
883
|
);
|
|
729
884
|
}
|
|
885
|
+
function setStableHTML(target, html) {
|
|
886
|
+
try {
|
|
887
|
+
const g = globalThis;
|
|
888
|
+
const doc = g["document"];
|
|
889
|
+
const el = target;
|
|
890
|
+
if (!doc || typeof el.querySelectorAll !== "function") {
|
|
891
|
+
target.innerHTML = html;
|
|
892
|
+
return;
|
|
893
|
+
}
|
|
894
|
+
let focusAct = null;
|
|
895
|
+
let focusKey = null;
|
|
896
|
+
try {
|
|
897
|
+
const active = doc.activeElement;
|
|
898
|
+
if (active && typeof active.getAttribute === "function") {
|
|
899
|
+
focusAct = active.getAttribute("data-act");
|
|
900
|
+
focusKey = active.getAttribute("data-key");
|
|
901
|
+
}
|
|
902
|
+
} catch {
|
|
903
|
+
focusAct = null;
|
|
904
|
+
focusKey = null;
|
|
905
|
+
}
|
|
906
|
+
let scrolls = [];
|
|
907
|
+
try {
|
|
908
|
+
const nodes = el.querySelectorAll(".dsh-upd-btable");
|
|
909
|
+
if (nodes) {
|
|
910
|
+
for (let i = 0; i < nodes.length; i++) {
|
|
911
|
+
const n = nodes[i];
|
|
912
|
+
scrolls.push(typeof n.scrollTop === "number" ? n.scrollTop : 0);
|
|
913
|
+
}
|
|
914
|
+
}
|
|
915
|
+
} catch {
|
|
916
|
+
scrolls = [];
|
|
917
|
+
}
|
|
918
|
+
target.innerHTML = html;
|
|
919
|
+
try {
|
|
920
|
+
const bodies = el.querySelectorAll(".dsh-upd-btable");
|
|
921
|
+
if (bodies) {
|
|
922
|
+
for (let i = 0; i < bodies.length && i < scrolls.length; i++) {
|
|
923
|
+
const n = bodies[i];
|
|
924
|
+
try {
|
|
925
|
+
n.scrollTop = scrolls[i];
|
|
926
|
+
} catch {
|
|
927
|
+
}
|
|
928
|
+
}
|
|
929
|
+
}
|
|
930
|
+
} catch {
|
|
931
|
+
}
|
|
932
|
+
try {
|
|
933
|
+
if (focusAct && typeof el.querySelector === "function") {
|
|
934
|
+
const sel = focusKey ? '[data-act="' + focusAct + '"][data-key="' + focusKey + '"]' : '[data-act="' + focusAct + '"]';
|
|
935
|
+
const next = el.querySelector(sel);
|
|
936
|
+
if (next && typeof next.focus === "function") {
|
|
937
|
+
try {
|
|
938
|
+
next.focus.call(next, { preventScroll: true });
|
|
939
|
+
} catch {
|
|
940
|
+
try {
|
|
941
|
+
next.focus.call(next);
|
|
942
|
+
} catch {
|
|
943
|
+
}
|
|
944
|
+
}
|
|
945
|
+
}
|
|
946
|
+
}
|
|
947
|
+
} catch {
|
|
948
|
+
}
|
|
949
|
+
} catch {
|
|
950
|
+
try {
|
|
951
|
+
target.innerHTML = html;
|
|
952
|
+
} catch {
|
|
953
|
+
}
|
|
954
|
+
}
|
|
955
|
+
}
|
|
730
956
|
let lastHTML = "";
|
|
731
957
|
function render() {
|
|
732
958
|
if (!mounted) return;
|
|
733
959
|
const nextHTML = renderBatchPanelHTML({
|
|
734
960
|
rows,
|
|
735
961
|
theme,
|
|
962
|
+
themeTokens,
|
|
736
963
|
mode,
|
|
737
964
|
expandedKey,
|
|
738
965
|
lastError,
|
|
@@ -743,11 +970,15 @@ function mountUpdateBatchPanel(container, options) {
|
|
|
743
970
|
loaded,
|
|
744
971
|
titles,
|
|
745
972
|
confirmCancel: confirmCancelArmed,
|
|
746
|
-
changelogs: changelogView()
|
|
973
|
+
changelogs: changelogView(),
|
|
974
|
+
session: lastSession,
|
|
975
|
+
inventory: lastInventory,
|
|
976
|
+
prefs: lastPrefs,
|
|
977
|
+
lang: currentLang()
|
|
747
978
|
});
|
|
748
979
|
if (nextHTML !== lastHTML) {
|
|
749
980
|
lastHTML = nextHTML;
|
|
750
|
-
container
|
|
981
|
+
setStableHTML(container, nextHTML);
|
|
751
982
|
}
|
|
752
983
|
}
|
|
753
984
|
function rowOfKey(key) {
|
|
@@ -789,7 +1020,7 @@ function mountUpdateBatchPanel(container, options) {
|
|
|
789
1020
|
await copyText(text);
|
|
790
1021
|
say(okNotice, key);
|
|
791
1022
|
} catch {
|
|
792
|
-
say("
|
|
1023
|
+
say(batchText("batch.toast.copy-fail", currentLang()), key);
|
|
793
1024
|
}
|
|
794
1025
|
render();
|
|
795
1026
|
}
|
|
@@ -802,6 +1033,13 @@ function mountUpdateBatchPanel(container, options) {
|
|
|
802
1033
|
const session = normalizeBatchSession(reply["session"]);
|
|
803
1034
|
const parsed = readRows(reply["rows"]);
|
|
804
1035
|
rows = parsed.length > 0 ? parsed : rowsFromSession(session);
|
|
1036
|
+
lastSession = session;
|
|
1037
|
+
if (isObject(reply["inventory"])) {
|
|
1038
|
+
lastInventory = reply["inventory"];
|
|
1039
|
+
const at = reply["inventory"]["updatedAt"];
|
|
1040
|
+
if (typeof at === "number" && Number.isFinite(at) && at > 0) lastCheckedAt = at;
|
|
1041
|
+
}
|
|
1042
|
+
if (isObject(reply["prefs"])) lastPrefs = reply["prefs"];
|
|
805
1043
|
loaded = true;
|
|
806
1044
|
lastError = null;
|
|
807
1045
|
if (expandedKey !== null && !rows.some((row) => row.key === expandedKey)) expandedKey = null;
|
|
@@ -828,27 +1066,49 @@ function mountUpdateBatchPanel(container, options) {
|
|
|
828
1066
|
maybeAutoRowChangelog(expandedKey);
|
|
829
1067
|
}
|
|
830
1068
|
async function phone(name, args, busyRowKey = null) {
|
|
831
|
-
if (!mounted || inFlight) return;
|
|
1069
|
+
if (!mounted || inFlight) return null;
|
|
832
1070
|
inFlight = true;
|
|
833
1071
|
clearNotice();
|
|
834
1072
|
render();
|
|
1073
|
+
let out = null;
|
|
835
1074
|
try {
|
|
836
1075
|
const reply = await call(name, args);
|
|
837
|
-
if (!mounted) return;
|
|
1076
|
+
if (!mounted) return null;
|
|
838
1077
|
if (busyRowKey !== null && isBusyReply(reply)) {
|
|
839
|
-
say("
|
|
840
|
-
return;
|
|
1078
|
+
say(batchText("batch.toast.queue-missed", currentLang()), busyRowKey);
|
|
1079
|
+
return null;
|
|
841
1080
|
}
|
|
842
1081
|
applyReply(reply);
|
|
843
1082
|
rowFailedAt.clear();
|
|
1083
|
+
out = isObject(reply) ? reply : null;
|
|
844
1084
|
} catch {
|
|
845
|
-
if (!mounted) return;
|
|
1085
|
+
if (!mounted) return null;
|
|
846
1086
|
lastError = "check-failed";
|
|
1087
|
+
out = null;
|
|
847
1088
|
} finally {
|
|
848
1089
|
inFlight = false;
|
|
849
1090
|
if (mounted) render();
|
|
850
1091
|
}
|
|
851
1092
|
maybeAutoRowChangelog(expandedKey);
|
|
1093
|
+
return out;
|
|
1094
|
+
}
|
|
1095
|
+
function remainingCount() {
|
|
1096
|
+
return unfinishedCount(rows, lastSession ?? void 0);
|
|
1097
|
+
}
|
|
1098
|
+
function checkOnOpenEffective() {
|
|
1099
|
+
if (isObject(lastPrefs)) {
|
|
1100
|
+
const v = lastPrefs["checkOnOpen"];
|
|
1101
|
+
if (v === false) return false;
|
|
1102
|
+
if (v === true) return true;
|
|
1103
|
+
}
|
|
1104
|
+
return checkOnOpenOption;
|
|
1105
|
+
}
|
|
1106
|
+
function nowMs() {
|
|
1107
|
+
try {
|
|
1108
|
+
return Date.now();
|
|
1109
|
+
} catch {
|
|
1110
|
+
return 0;
|
|
1111
|
+
}
|
|
852
1112
|
}
|
|
853
1113
|
async function act(kind, key) {
|
|
854
1114
|
if (!mounted) return;
|
|
@@ -858,17 +1118,26 @@ function mountUpdateBatchPanel(container, options) {
|
|
|
858
1118
|
}
|
|
859
1119
|
switch (kind) {
|
|
860
1120
|
case "check":
|
|
861
|
-
|
|
1121
|
+
await phone(phones.check, {});
|
|
1122
|
+
return;
|
|
862
1123
|
case "install":
|
|
863
|
-
|
|
1124
|
+
await phone(phones.install, {});
|
|
1125
|
+
return;
|
|
864
1126
|
case "row-install": {
|
|
865
1127
|
if (typeof key !== "string" || !key) return;
|
|
866
|
-
|
|
1128
|
+
await phone(phones.install, { keys: [key] }, key);
|
|
1129
|
+
return;
|
|
867
1130
|
}
|
|
868
1131
|
case "resume": {
|
|
869
|
-
await phone(phones.resume, {});
|
|
1132
|
+
const reply = await phone(phones.resume, {});
|
|
870
1133
|
if (!mounted) return;
|
|
871
|
-
|
|
1134
|
+
if (!reply || reply["ok"] !== true) return;
|
|
1135
|
+
if (reply["resumed"] === false) {
|
|
1136
|
+
say(batchText("batch.notice.no-resume", currentLang()));
|
|
1137
|
+
render();
|
|
1138
|
+
return;
|
|
1139
|
+
}
|
|
1140
|
+
say(batchText("batch.notice.resumed", currentLang(), { count: String(remainingCount()) }));
|
|
872
1141
|
render();
|
|
873
1142
|
return;
|
|
874
1143
|
}
|
|
@@ -876,9 +1145,18 @@ function mountUpdateBatchPanel(container, options) {
|
|
|
876
1145
|
// 鼠标误触的防护在 onClick 那一层(第一次点击只上膛)。
|
|
877
1146
|
case "cancel": {
|
|
878
1147
|
confirmCancelArmed = false;
|
|
879
|
-
await phone(phones.cancel, {});
|
|
1148
|
+
const reply = await phone(phones.cancel, {});
|
|
1149
|
+
if (!mounted) return;
|
|
1150
|
+
if (!reply || reply["ok"] !== true) return;
|
|
1151
|
+
say(batchText("batch.notice.discarded", currentLang()));
|
|
1152
|
+
render();
|
|
1153
|
+
return;
|
|
1154
|
+
}
|
|
1155
|
+
case "toggle-check-on-open": {
|
|
1156
|
+
const next = !checkOnOpenEffective();
|
|
1157
|
+
const reply = await phone(phones.prefsSave, { checkOnOpen: next });
|
|
880
1158
|
if (!mounted) return;
|
|
881
|
-
|
|
1159
|
+
if (reply && reply["ok"] === true && isObject(reply["prefs"])) lastPrefs = reply["prefs"];
|
|
882
1160
|
render();
|
|
883
1161
|
return;
|
|
884
1162
|
}
|
|
@@ -891,7 +1169,7 @@ function mountUpdateBatchPanel(container, options) {
|
|
|
891
1169
|
skipStoreFor(pluginIdOf(row)).skip(version);
|
|
892
1170
|
} catch {
|
|
893
1171
|
}
|
|
894
|
-
say("
|
|
1172
|
+
say(batchText("batch.toast.skipped", currentLang(), { version }), row.key);
|
|
895
1173
|
render();
|
|
896
1174
|
return;
|
|
897
1175
|
}
|
|
@@ -903,7 +1181,7 @@ function mountUpdateBatchPanel(container, options) {
|
|
|
903
1181
|
skipStoreFor(pluginIdOf(row)).reset(version ?? void 0);
|
|
904
1182
|
} catch {
|
|
905
1183
|
}
|
|
906
|
-
say(version ? "
|
|
1184
|
+
say(version ? batchText("batch.toast.unskipped-version", currentLang(), { version }) : batchText("batch.toast.unskipped-all", currentLang()), row.key);
|
|
907
1185
|
render();
|
|
908
1186
|
return;
|
|
909
1187
|
}
|
|
@@ -915,7 +1193,7 @@ function mountUpdateBatchPanel(container, options) {
|
|
|
915
1193
|
const phoneName = cancelQueuePhoneOf(row);
|
|
916
1194
|
const requestId = queuedRequestIdOf(row);
|
|
917
1195
|
if (phoneName === null || requestId === null) {
|
|
918
|
-
say("
|
|
1196
|
+
say(batchText("batch.toast.cancel-unavailable", currentLang()), row.key);
|
|
919
1197
|
render();
|
|
920
1198
|
return;
|
|
921
1199
|
}
|
|
@@ -925,9 +1203,9 @@ function mountUpdateBatchPanel(container, options) {
|
|
|
925
1203
|
render();
|
|
926
1204
|
try {
|
|
927
1205
|
await call(phoneName, { cancelQueued: true, requestId });
|
|
928
|
-
if (mounted) say("
|
|
1206
|
+
if (mounted) say(batchText("batch.toast.cancel-ok", currentLang()), row.key);
|
|
929
1207
|
} catch {
|
|
930
|
-
if (mounted) say("
|
|
1208
|
+
if (mounted) say(batchText("batch.toast.cancel-fail", currentLang()), row.key);
|
|
931
1209
|
} finally {
|
|
932
1210
|
inFlight = false;
|
|
933
1211
|
}
|
|
@@ -938,13 +1216,13 @@ function mountUpdateBatchPanel(container, options) {
|
|
|
938
1216
|
const row = typeof key === "string" && key ? rowOfKey(key) : null;
|
|
939
1217
|
const manual = row && typeof row.manual === "string" ? row.manual : "";
|
|
940
1218
|
if (!row || !manual) return;
|
|
941
|
-
await copyWith(manual, "
|
|
1219
|
+
await copyWith(manual, batchText("batch.toast.copy-manual-ok", currentLang()), row.key);
|
|
942
1220
|
return;
|
|
943
1221
|
}
|
|
944
1222
|
case "row-copy-diag": {
|
|
945
1223
|
const row = typeof key === "string" && key ? rowOfKey(key) : null;
|
|
946
1224
|
if (!row) return;
|
|
947
|
-
await copyWith(diagTextOf(row), "
|
|
1225
|
+
await copyWith(diagTextOf(row, currentLang()), batchText("batch.toast.copy-diag-ok", currentLang()), row.key);
|
|
948
1226
|
return;
|
|
949
1227
|
}
|
|
950
1228
|
case "toggle-details": {
|
|
@@ -960,12 +1238,12 @@ function mountUpdateBatchPanel(container, options) {
|
|
|
960
1238
|
try {
|
|
961
1239
|
if (typeof onRestartRequested === "function") {
|
|
962
1240
|
await onRestartRequested();
|
|
963
|
-
say("
|
|
1241
|
+
say(batchText("batch.toast.restart-delegated", currentLang()));
|
|
964
1242
|
} else {
|
|
965
|
-
say("
|
|
1243
|
+
say(batchText("batch.toast.restart-manual", currentLang()));
|
|
966
1244
|
}
|
|
967
1245
|
} catch {
|
|
968
|
-
say("
|
|
1246
|
+
say(batchText("batch.toast.restart-failed", currentLang()));
|
|
969
1247
|
}
|
|
970
1248
|
render();
|
|
971
1249
|
return;
|
|
@@ -997,12 +1275,17 @@ function mountUpdateBatchPanel(container, options) {
|
|
|
997
1275
|
}
|
|
998
1276
|
}
|
|
999
1277
|
function setTheme(next) {
|
|
1000
|
-
if (next !== "default" && next !== "archive"
|
|
1001
|
-
throw new Error("[dsh-plugin-update] \u4E3B\u9898\u975E\u6CD5\uFF1A\u53EA\u6536 default \u6216 archive\
|
|
1278
|
+
if (next !== "default" && next !== "archive") {
|
|
1279
|
+
throw new Error("[dsh-plugin-update] \u4E3B\u9898\u975E\u6CD5\uFF1A\u53EA\u6536 default \u6216 archive\uFF08\u6536\u5230 " + JSON.stringify(next) + "\uFF09");
|
|
1002
1280
|
}
|
|
1003
1281
|
theme = normalizePanelTheme(next);
|
|
1004
1282
|
render();
|
|
1005
1283
|
}
|
|
1284
|
+
function setThemeTokens(next) {
|
|
1285
|
+
themeTokensStyleFor(next ?? void 0);
|
|
1286
|
+
themeTokens = next ?? void 0;
|
|
1287
|
+
render();
|
|
1288
|
+
}
|
|
1006
1289
|
function setMode(next) {
|
|
1007
1290
|
if (next !== "embedded" && next !== "dialog") {
|
|
1008
1291
|
throw new Error("[dsh-plugin-update] \u6446\u653E\u5F62\u6001\u975E\u6CD5\uFF1A\u53EA\u6536 embedded \u6216 dialog\uFF08\u6536\u5230 " + JSON.stringify(next) + "\uFF09");
|
|
@@ -1018,7 +1301,7 @@ function mountUpdateBatchPanel(container, options) {
|
|
|
1018
1301
|
if (!kind) return;
|
|
1019
1302
|
if (kind === "cancel" && !confirmCancelArmed) {
|
|
1020
1303
|
confirmCancelArmed = true;
|
|
1021
|
-
say("
|
|
1304
|
+
say(batchText("batch.notice.cancel-confirm", currentLang()));
|
|
1022
1305
|
render();
|
|
1023
1306
|
return;
|
|
1024
1307
|
}
|
|
@@ -1028,9 +1311,64 @@ function mountUpdateBatchPanel(container, options) {
|
|
|
1028
1311
|
} catch {
|
|
1029
1312
|
}
|
|
1030
1313
|
}
|
|
1314
|
+
async function autoOnce() {
|
|
1315
|
+
if (!mounted) return;
|
|
1316
|
+
if (autoResumeOption && !autoResumeDone) {
|
|
1317
|
+
autoResumeDone = true;
|
|
1318
|
+
if (hasUnfinishedRows(rows, lastSession ?? void 0) && !inFlight && !refreshing) {
|
|
1319
|
+
const before = lastError;
|
|
1320
|
+
try {
|
|
1321
|
+
const reply = await call(phones.resume, {});
|
|
1322
|
+
if (!mounted) return;
|
|
1323
|
+
if (isObject(reply) && reply["ok"] === true) {
|
|
1324
|
+
applyReply(reply);
|
|
1325
|
+
const r = reply;
|
|
1326
|
+
if (r["resumed"] !== false) {
|
|
1327
|
+
say(batchText("batch.notice.auto-resumed", currentLang(), { count: String(remainingCount()) }));
|
|
1328
|
+
rowFailedAt.clear();
|
|
1329
|
+
}
|
|
1330
|
+
render();
|
|
1331
|
+
maybeAutoRowChangelog(expandedKey);
|
|
1332
|
+
return;
|
|
1333
|
+
}
|
|
1334
|
+
lastError = before;
|
|
1335
|
+
render();
|
|
1336
|
+
} catch {
|
|
1337
|
+
if (mounted) render();
|
|
1338
|
+
}
|
|
1339
|
+
}
|
|
1340
|
+
}
|
|
1341
|
+
if (!autoCheckDone) {
|
|
1342
|
+
autoCheckDone = true;
|
|
1343
|
+
if (!checkOnOpenEffective()) return;
|
|
1344
|
+
if (hasUnfinishedRows(rows, lastSession ?? void 0)) return;
|
|
1345
|
+
const stale = lastCheckedAt <= 0 || nowMs() - lastCheckedAt >= 6e4;
|
|
1346
|
+
if (!stale || inFlight || refreshing) return;
|
|
1347
|
+
const before = lastError;
|
|
1348
|
+
try {
|
|
1349
|
+
const reply = await call(phones.check, {});
|
|
1350
|
+
if (!mounted) return;
|
|
1351
|
+
if (isObject(reply) && reply["ok"] === true) {
|
|
1352
|
+
applyReply(reply);
|
|
1353
|
+
rowFailedAt.clear();
|
|
1354
|
+
render();
|
|
1355
|
+
maybeAutoRowChangelog(expandedKey);
|
|
1356
|
+
return;
|
|
1357
|
+
}
|
|
1358
|
+
lastError = before;
|
|
1359
|
+
render();
|
|
1360
|
+
} catch {
|
|
1361
|
+
if (mounted) render();
|
|
1362
|
+
}
|
|
1363
|
+
}
|
|
1364
|
+
}
|
|
1031
1365
|
function unmount() {
|
|
1032
1366
|
if (!mounted) return;
|
|
1033
1367
|
mounted = false;
|
|
1368
|
+
try {
|
|
1369
|
+
unsubLang();
|
|
1370
|
+
} catch {
|
|
1371
|
+
}
|
|
1034
1372
|
rowAutoSeq++;
|
|
1035
1373
|
rowInflight.clear();
|
|
1036
1374
|
try {
|
|
@@ -1046,6 +1384,9 @@ function mountUpdateBatchPanel(container, options) {
|
|
|
1046
1384
|
} catch {
|
|
1047
1385
|
}
|
|
1048
1386
|
}
|
|
1387
|
+
const unsubLang = subscribeLang(() => {
|
|
1388
|
+
render();
|
|
1389
|
+
}, localeOpt);
|
|
1049
1390
|
render();
|
|
1050
1391
|
try {
|
|
1051
1392
|
container.addEventListener?.("click", onClick);
|
|
@@ -1057,6 +1398,7 @@ function mountUpdateBatchPanel(container, options) {
|
|
|
1057
1398
|
}
|
|
1058
1399
|
const timer = getTimer();
|
|
1059
1400
|
const handle = timer.set(() => {
|
|
1401
|
+
if (inFlight) return;
|
|
1060
1402
|
void refresh();
|
|
1061
1403
|
}, pollMs);
|
|
1062
1404
|
try {
|
|
@@ -1064,18 +1406,23 @@ function mountUpdateBatchPanel(container, options) {
|
|
|
1064
1406
|
if (h && typeof h.unref === "function") h.unref();
|
|
1065
1407
|
} catch {
|
|
1066
1408
|
}
|
|
1067
|
-
void refresh()
|
|
1068
|
-
|
|
1409
|
+
void refresh().then(() => {
|
|
1410
|
+
void autoOnce();
|
|
1411
|
+
});
|
|
1412
|
+
return { refresh, act, setTheme, setThemeTokens, setMode, unmount };
|
|
1069
1413
|
}
|
|
1070
1414
|
export {
|
|
1071
1415
|
BATCH_PANEL_POLL,
|
|
1416
|
+
UPDATE_BATCH_PANEL_ARCHIVE_CSS,
|
|
1072
1417
|
UPDATE_BATCH_PANEL_CSS,
|
|
1073
|
-
UPDATE_BATCH_PANEL_D5_CSS,
|
|
1074
1418
|
batchLedgerCounts,
|
|
1075
1419
|
batchLedgerText,
|
|
1076
1420
|
batchQueuedStatus,
|
|
1421
|
+
batchRowKnowledgeText,
|
|
1077
1422
|
batchRowStatus,
|
|
1078
1423
|
buildBatchPhoneNames,
|
|
1424
|
+
hasUnfinishedRows,
|
|
1079
1425
|
mountUpdateBatchPanel,
|
|
1080
|
-
renderBatchPanelHTML
|
|
1426
|
+
renderBatchPanelHTML,
|
|
1427
|
+
unfinishedCount
|
|
1081
1428
|
};
|