dsh-plugin-update 0.5.7 → 0.6.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 +17 -4
- package/README.md +29 -10
- package/dist/bilingual.d.ts +23 -13
- package/dist/bilingual.js +324 -10
- 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 +22 -5
- package/dist/entry-batch.js +86 -19
- package/dist/entry.d.ts +37 -9
- package/dist/entry.js +105 -51
- package/dist/host-batch.js +104 -13
- package/dist/http.d.ts +2 -2
- package/dist/http.js +1 -1
- package/dist/lang.js +150 -0
- package/dist/panel-batch.d.ts +50 -9
- package/dist/panel-batch.js +484 -150
- package/dist/panel.d.ts +37 -22
- package/dist/panel.js +504 -362
- 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,7 +10,7 @@ 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,
|
|
@@ -27,7 +29,9 @@ function buildBatchPhoneNames(prefix) {
|
|
|
27
29
|
check: p + ".batchCheck",
|
|
28
30
|
install: p + ".batchInstall",
|
|
29
31
|
resume: p + ".batchResume",
|
|
30
|
-
cancel: p + ".batchCancel"
|
|
32
|
+
cancel: p + ".batchCancel",
|
|
33
|
+
prefs: p + ".batchPrefs",
|
|
34
|
+
prefsSave: p + ".batchPrefsSave"
|
|
31
35
|
};
|
|
32
36
|
}
|
|
33
37
|
function batchLedgerCounts(rows) {
|
|
@@ -53,44 +57,122 @@ function batchLedgerCounts(rows) {
|
|
|
53
57
|
}
|
|
54
58
|
return counts;
|
|
55
59
|
}
|
|
56
|
-
function batchLedgerText(counts) {
|
|
60
|
+
function batchLedgerText(counts, lang) {
|
|
61
|
+
const l = langOf(lang);
|
|
57
62
|
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 ") : "
|
|
63
|
+
if (counts.updatable > 0) parts.push(batchText("batch.summary.updatable", l, { n: String(counts.updatable) }));
|
|
64
|
+
if (counts.installing > 0) parts.push(batchText("batch.summary.installing", l, { n: String(counts.installing) }));
|
|
65
|
+
if (counts.pending > 0) parts.push(batchText("batch.summary.pending", l, { n: String(counts.pending) }));
|
|
66
|
+
if (counts.restart > 0) parts.push(batchText("batch.summary.restart", l, { n: String(counts.restart) }));
|
|
67
|
+
if (counts.failed > 0) parts.push(batchText("batch.summary.failed", l, { n: String(counts.failed) }));
|
|
68
|
+
if (counts.skipped > 0) parts.push(batchText("batch.summary.skipped", l, { n: String(counts.skipped) }));
|
|
69
|
+
if (counts.settled > 0) parts.push(batchText("batch.summary.settled", l, { n: String(counts.settled) }));
|
|
70
|
+
return parts.length > 0 ? parts.join(" \xB7 ") : batchText("batch.summary.empty", l);
|
|
66
71
|
}
|
|
67
|
-
function batchQueuedStatus(position) {
|
|
68
|
-
|
|
69
|
-
|
|
72
|
+
function batchQueuedStatus(position, lang) {
|
|
73
|
+
const l = langOf(lang);
|
|
74
|
+
if (typeof position !== "number" || !Number.isFinite(position) || position < 1) return batchText("batch.row.queued-generic", l);
|
|
75
|
+
return batchText("batch.row.queued-n", l, { n: String(position) });
|
|
70
76
|
}
|
|
71
|
-
function
|
|
77
|
+
function knowledgeEntryOf(inventory, key) {
|
|
78
|
+
if (!isObject(inventory)) return null;
|
|
79
|
+
const entries = inventory["entries"];
|
|
80
|
+
if (!isObject(entries)) return null;
|
|
81
|
+
const item = entries[key];
|
|
82
|
+
if (!isObject(item)) return null;
|
|
83
|
+
const e = item;
|
|
84
|
+
const canInstallRaw = e["canInstall"];
|
|
85
|
+
return {
|
|
86
|
+
lastCheckedAt: typeof e["lastCheckedAt"] === "number" ? e["lastCheckedAt"] : 0,
|
|
87
|
+
installedVersion: typeof e["installedVersion"] === "string" ? e["installedVersion"] : null,
|
|
88
|
+
latestVersion: typeof e["latestVersion"] === "string" ? e["latestVersion"] : null,
|
|
89
|
+
canInstall: typeof canInstallRaw === "boolean" ? canInstallRaw : null,
|
|
90
|
+
error: typeof e["error"] === "string" ? e["error"] : null
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
function langOf(lang) {
|
|
94
|
+
try {
|
|
95
|
+
return normalizeLangTag(typeof lang === "string" ? lang : resolveLang(lang));
|
|
96
|
+
} catch {
|
|
97
|
+
return "zh";
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
function batchText(key, lang, values) {
|
|
101
|
+
try {
|
|
102
|
+
return bilingualText(key, langOf(lang), values);
|
|
103
|
+
} catch {
|
|
104
|
+
return "";
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
function hasUnfinishedRows(rows, session) {
|
|
108
|
+
if (isObject(session)) {
|
|
109
|
+
const entries = session["entries"];
|
|
110
|
+
if (Array.isArray(entries)) {
|
|
111
|
+
for (const item of entries) {
|
|
112
|
+
if (!isObject(item)) continue;
|
|
113
|
+
const phase = item["phase"];
|
|
114
|
+
if (typeof phase === "string" && !isTerminalPhase(asBatchPhase(phase))) return true;
|
|
115
|
+
}
|
|
116
|
+
return false;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
if (rows.length === 0) return false;
|
|
120
|
+
return !rows.every((row) => isTerminalPhase(asBatchPhase(row.phase)));
|
|
121
|
+
}
|
|
122
|
+
function unfinishedCount(rows, session) {
|
|
123
|
+
if (isObject(session)) {
|
|
124
|
+
const entries = session["entries"];
|
|
125
|
+
if (Array.isArray(entries)) {
|
|
126
|
+
let n = 0;
|
|
127
|
+
for (const item of entries) {
|
|
128
|
+
if (!isObject(item)) continue;
|
|
129
|
+
const phase = item["phase"];
|
|
130
|
+
if (typeof phase === "string" && !isTerminalPhase(asBatchPhase(phase))) n += 1;
|
|
131
|
+
}
|
|
132
|
+
return n;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
return rows.filter((row) => !isTerminalPhase(asBatchPhase(row.phase))).length;
|
|
136
|
+
}
|
|
137
|
+
function batchRowStatus(row, skippedVersion, lang) {
|
|
138
|
+
const l = langOf(lang);
|
|
72
139
|
const skipped = typeof skippedVersion === "string" && skippedVersion ? skippedVersion : null;
|
|
73
|
-
if (skipped !== null && asBatchPhase(row.phase) === "ready") return "
|
|
140
|
+
if (skipped !== null && asBatchPhase(row.phase) === "ready") return batchText("batch.row.skipped", l, { version: skipped });
|
|
74
141
|
switch (asBatchPhase(row.phase)) {
|
|
75
142
|
case "pending":
|
|
76
|
-
return "
|
|
143
|
+
return batchText("batch.row.wait-turn", l);
|
|
77
144
|
case "checking":
|
|
78
|
-
return "
|
|
145
|
+
return batchText("batch.row.checking", l);
|
|
79
146
|
case "ready":
|
|
80
|
-
return row.targetVersion ? "
|
|
147
|
+
return row.targetVersion ? batchText("batch.row.cta-version", l, { version: row.targetVersion }) : batchText("batch.row.cta-generic", l);
|
|
81
148
|
case "installing":
|
|
82
|
-
return "
|
|
149
|
+
return batchText("batch.row.installing", l);
|
|
83
150
|
case "current":
|
|
84
|
-
return "
|
|
151
|
+
return batchText("batch.row.current", l);
|
|
85
152
|
case "done":
|
|
86
|
-
return row.restartRequired === true ? "
|
|
153
|
+
return row.restartRequired === true ? batchText("batch.row.done-restart", l) : batchText("batch.row.done", l);
|
|
87
154
|
case "failed":
|
|
88
|
-
return "
|
|
155
|
+
return batchText("batch.row.failed-retry", l);
|
|
89
156
|
case "skipped":
|
|
90
|
-
return "
|
|
157
|
+
return batchText("batch.row.skipped-idle", l);
|
|
91
158
|
default:
|
|
92
|
-
return "
|
|
159
|
+
return batchText("batch.row.unknown", l);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
function batchRowKnowledgeText(row, entry, lang) {
|
|
163
|
+
if (asBatchPhase(row.phase) !== "pending" || !entry) return null;
|
|
164
|
+
if (entry.error) return batchText("batch.row.failed", lang);
|
|
165
|
+
if (entry.latestVersion && entry.installedVersion && entry.latestVersion !== entry.installedVersion) {
|
|
166
|
+
return batchText("batch.row.update", lang, { version: entry.latestVersion });
|
|
167
|
+
}
|
|
168
|
+
if (entry.latestVersion && entry.installedVersion && entry.latestVersion === entry.installedVersion) {
|
|
169
|
+
return batchText("batch.row.current", lang);
|
|
93
170
|
}
|
|
171
|
+
if (entry.latestVersion && !entry.installedVersion) {
|
|
172
|
+
return batchText("batch.row.update", lang, { version: entry.latestVersion });
|
|
173
|
+
}
|
|
174
|
+
if (entry.lastCheckedAt > 0) return batchText("batch.row.current", lang);
|
|
175
|
+
return batchText("batch.row.never", lang);
|
|
94
176
|
}
|
|
95
177
|
function renderBatchPanelHTML(input) {
|
|
96
178
|
const rows = Array.isArray(input.rows) ? input.rows : [];
|
|
@@ -105,16 +187,12 @@ function renderBatchPanelHTML(input) {
|
|
|
105
187
|
const installing = counts.installing > 0;
|
|
106
188
|
const macroBusy = input.inFlight === true || installing;
|
|
107
189
|
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
190
|
const disabled = macroBusy ? " disabled" : "";
|
|
114
191
|
const notice = typeof input.notice === "string" && input.notice ? input.notice : null;
|
|
115
192
|
const noticeKey = typeof input.noticeKey === "string" && input.noticeKey ? input.noticeKey : null;
|
|
116
193
|
const detailNoticeKey = notice !== null && noticeKey !== null && noticeKey === expandedKey ? noticeKey : null;
|
|
117
194
|
const changelogs = input.changelogs && typeof input.changelogs === "object" ? input.changelogs : {};
|
|
195
|
+
const lang = langOf(input["lang"]);
|
|
118
196
|
const ctx = {
|
|
119
197
|
expanded: false,
|
|
120
198
|
busy: installing,
|
|
@@ -123,103 +201,144 @@ function renderBatchPanelHTML(input) {
|
|
|
123
201
|
titles,
|
|
124
202
|
skipped: null,
|
|
125
203
|
notice: null,
|
|
126
|
-
changelogMarkdown: null
|
|
204
|
+
changelogMarkdown: null,
|
|
205
|
+
lang,
|
|
206
|
+
knowledge: null,
|
|
207
|
+
inRound: false
|
|
127
208
|
};
|
|
128
209
|
const parts = [];
|
|
129
210
|
parts.push('<div class="dsh-upd-batch-head">');
|
|
130
|
-
parts.push('<div class="dsh-upd-batch-title"
|
|
211
|
+
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
212
|
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="
|
|
213
|
+
parts.push('<button type="button" data-act="check"' + disabled + ' title="' + escapeHtml(batchText("batch.action.check-title", lang)) + '">' + escapeHtml(batchText("batch.action.check", lang)) + "</button>");
|
|
214
|
+
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>");
|
|
215
|
+
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
216
|
parts.push("</div>");
|
|
136
217
|
parts.push("</div>");
|
|
137
|
-
const summary = loaded ? batchSummaryText(counts, rows, total, installing, lastError !== null) : "
|
|
218
|
+
const summary = loaded ? batchSummaryText(counts, rows, total, installing, lastError !== null, lang) : batchText("batch.banner.loading", lang);
|
|
138
219
|
parts.push('<div class="dsh-upd-batch-sum" role="status" aria-live="polite">' + escapeHtml(summary) + "</div>");
|
|
139
|
-
parts.push(bannersHTML(rows, titles, lastError));
|
|
220
|
+
parts.push(bannersHTML(rows, titles, lastError, lang));
|
|
221
|
+
const session = isObject(input.session) ? input.session : null;
|
|
222
|
+
const unfinished = unfinishedCount(rows, session ?? void 0);
|
|
223
|
+
const showControls = total > 0 && hasUnfinishedRows(rows, session ?? void 0);
|
|
224
|
+
const prefs = isObject(input.prefs) ? input.prefs : null;
|
|
225
|
+
const checkOnOpen = prefs === null ? null : prefs["checkOnOpen"] === false ? false : true;
|
|
226
|
+
function roundEntryPhase(key) {
|
|
227
|
+
if (!session) return null;
|
|
228
|
+
const entries = session["entries"];
|
|
229
|
+
if (!Array.isArray(entries)) return null;
|
|
230
|
+
for (const item of entries) {
|
|
231
|
+
if (!isObject(item)) continue;
|
|
232
|
+
const e = item;
|
|
233
|
+
if (e["key"] === key && typeof e["phase"] === "string") return e["phase"];
|
|
234
|
+
}
|
|
235
|
+
return null;
|
|
236
|
+
}
|
|
140
237
|
parts.push('<div class="dsh-upd-btable">');
|
|
141
238
|
for (const row of rows) {
|
|
142
239
|
const raw = skippedVersions[row.key];
|
|
143
240
|
const skipped = typeof raw === "string" && raw ? raw : null;
|
|
144
241
|
const expanded = row.key === expandedKey;
|
|
242
|
+
const entryPhase = roundEntryPhase(row.key);
|
|
243
|
+
const inRound = entryPhase !== null && !isTerminalPhase(asBatchPhase(entryPhase));
|
|
145
244
|
parts.push(
|
|
146
245
|
rowSetHTML(row, {
|
|
147
246
|
...ctx,
|
|
148
247
|
expanded,
|
|
149
248
|
skipped,
|
|
150
249
|
notice: expanded && row.key === detailNoticeKey ? notice : null,
|
|
151
|
-
changelogMarkdown: expanded && typeof changelogs[row.key] === "string" ? changelogs[row.key] : null
|
|
250
|
+
changelogMarkdown: expanded && typeof changelogs[row.key] === "string" ? changelogs[row.key] : null,
|
|
251
|
+
lang,
|
|
252
|
+
knowledge: asBatchPhase(row.phase) === "pending" && !inRound ? knowledgeEntryOf(input.inventory, row.key) : null,
|
|
253
|
+
inRound
|
|
152
254
|
})
|
|
153
255
|
);
|
|
154
256
|
}
|
|
155
257
|
parts.push("</div>");
|
|
156
258
|
if (total > 0) {
|
|
157
|
-
parts.push('<div class="dsh-upd-batch-ledger">' + escapeHtml(batchLedgerText(counts)) + "</div>");
|
|
259
|
+
parts.push('<div class="dsh-upd-batch-ledger">' + escapeHtml(batchLedgerText(counts, lang)) + "</div>");
|
|
158
260
|
}
|
|
159
|
-
if (
|
|
261
|
+
if (showControls) {
|
|
160
262
|
const more = [];
|
|
161
|
-
|
|
263
|
+
more.push(
|
|
264
|
+
'<button type="button" data-act="resume">' + escapeHtml(batchText("batch.action.resume", lang, { count: String(unfinished) })) + "</button>"
|
|
265
|
+
);
|
|
162
266
|
const confirmCancel = input.confirmCancel === true;
|
|
267
|
+
const discardLabel = confirmCancel ? batchText("batch.action.confirm-discard", lang) : batchText("batch.action.discard", lang);
|
|
163
268
|
more.push(
|
|
164
|
-
'<button type="button" data-act="cancel"' + disabled + (confirmCancel ? ' data-confirm="1" title="
|
|
269
|
+
'<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
270
|
);
|
|
166
271
|
parts.push('<div class="dsh-upd-batch-more">' + more.join("") + "</div>");
|
|
272
|
+
parts.push('<div class="dsh-upd-batch-fact" role="note">' + escapeHtml(batchText("batch.fact.close-safe", lang)) + "</div>");
|
|
273
|
+
if (macroBusy) {
|
|
274
|
+
parts.push('<div class="dsh-upd-batch-fact" role="note">' + escapeHtml(batchText("batch.notice.busy-cancel", lang)) + "</div>");
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
if (prefs !== null && checkOnOpen !== null) {
|
|
278
|
+
parts.push(
|
|
279
|
+
'<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>"
|
|
280
|
+
);
|
|
167
281
|
}
|
|
168
282
|
if (notice !== null && detailNoticeKey === null) {
|
|
169
283
|
parts.push('<div class="dsh-upd-batch-notice" role="status">' + escapeHtml(notice) + "</div>");
|
|
170
284
|
}
|
|
171
285
|
const kernel = parts.join(String.fromCharCode(10));
|
|
172
|
-
const
|
|
173
|
-
const attr =
|
|
174
|
-
const seal = batchSealOf(counts);
|
|
286
|
+
const archive = normalizePanelTheme(theme) === "archive";
|
|
287
|
+
const attr = archive ? ' data-theme="archive"' : "";
|
|
288
|
+
const seal = batchSealOf(counts, lang);
|
|
175
289
|
const root = '<div class="dsh-upd dsh-upd-batch" data-mode="' + mode + '" data-seal="' + escapeHtml(seal.text) + '" data-seal-tone="' + seal.tone + '"' + attr + ">\n" + kernel + "\n</div>";
|
|
176
290
|
const body = mode === "dialog" ? '<div class="dsh-upd-overlay" data-mode="dialog">' + root + "</div>" : root;
|
|
177
|
-
const css =
|
|
291
|
+
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
292
|
return "<style>" + css + "</style>\n" + body;
|
|
179
293
|
}
|
|
180
|
-
function batchSummaryText(counts, rows, total, installing, hasError) {
|
|
181
|
-
|
|
182
|
-
if (
|
|
294
|
+
function batchSummaryText(counts, rows, total, installing, hasError, lang) {
|
|
295
|
+
const l = langOf(lang);
|
|
296
|
+
if (hasError) return batchText("batch.hint.error", l);
|
|
297
|
+
if (total === 0) return batchText("batch.hint.empty", l);
|
|
183
298
|
if (installing) {
|
|
184
299
|
const canQueue = rows.filter((row) => asBatchPhase(row.phase) === "ready" && !isQueuedRow(row)).length;
|
|
185
|
-
return canQueue > 0 ? "
|
|
300
|
+
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
301
|
}
|
|
187
|
-
if (counts.failed > 0) return
|
|
302
|
+
if (counts.failed > 0) return batchText("batch.hint.failed", l, { n: String(counts.failed) });
|
|
188
303
|
if (counts.updatable > 0)
|
|
189
|
-
return
|
|
190
|
-
if (counts.restart > 0) return
|
|
191
|
-
if (counts.pending > 0) return
|
|
192
|
-
return "
|
|
304
|
+
return batchText("batch.hint.updatable", l, { n: String(counts.updatable) });
|
|
305
|
+
if (counts.restart > 0) return batchText("batch.hint.restart", l, { n: String(counts.restart) });
|
|
306
|
+
if (counts.pending > 0) return batchText("batch.hint.pending", l, { n: String(counts.pending) });
|
|
307
|
+
return batchText("batch.hint.done", l);
|
|
193
308
|
}
|
|
194
|
-
function batchSealOf(counts) {
|
|
195
|
-
|
|
196
|
-
if (counts.
|
|
197
|
-
if (counts.
|
|
198
|
-
return { text
|
|
309
|
+
function batchSealOf(counts, lang) {
|
|
310
|
+
const text = batchText("batch.seal.ledger", langOf(lang));
|
|
311
|
+
if (counts.failed > 0) return { text, tone: "red" };
|
|
312
|
+
if (counts.installing > 0 || counts.restart > 0) return { text, tone: "yellow" };
|
|
313
|
+
if (counts.updatable > 0) return { text, tone: "green" };
|
|
314
|
+
return { text, tone: "ink" };
|
|
199
315
|
}
|
|
200
|
-
function bannersHTML(rows, titles, lastError) {
|
|
316
|
+
function bannersHTML(rows, titles, lastError, lang) {
|
|
317
|
+
const l = langOf(lang);
|
|
201
318
|
const parts = [];
|
|
202
319
|
if (lastError) {
|
|
203
|
-
const copy = failureCopy(lastError);
|
|
320
|
+
const copy = failureCopy(lastError, l);
|
|
321
|
+
const detail = copy?.zh ?? failureCopy("unknown", l)?.zh ?? "";
|
|
322
|
+
const act = copy?.act ?? batchText("batch.banner.error-action-fallback", l);
|
|
204
323
|
parts.push(
|
|
205
|
-
'<div class="dsh-upd-banner" data-kind="failed" data-mini="\u963B" role="status"><div><strong
|
|
324
|
+
'<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
325
|
);
|
|
207
326
|
}
|
|
208
327
|
const failed = rows.filter((row) => asBatchPhase(row.phase) === "failed" && !isQueueBusyRow(row));
|
|
209
328
|
if (failed.length > 0) {
|
|
210
329
|
const lines = failed.map((row) => {
|
|
211
330
|
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
|
|
331
|
+
const copy = failureCopy(code, l);
|
|
332
|
+
return "<div>" + escapeHtml(titleOf(row, titles)) + "\uFF1A<code>" + escapeHtml(code) + "</code> " + escapeHtml(copy?.zh ?? failureCopy("unknown", l)?.zh ?? "") + "</div>";
|
|
214
333
|
}).join("");
|
|
215
334
|
parts.push(
|
|
216
|
-
'<div class="dsh-upd-banner" data-kind="failed" data-mini="\u963B" role="status"><div><strong>' + failed.length +
|
|
335
|
+
'<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
336
|
);
|
|
218
337
|
}
|
|
219
338
|
const restart = rows.filter((row) => row.restartRequired === true);
|
|
220
339
|
if (restart.length > 0) {
|
|
221
340
|
parts.push(
|
|
222
|
-
'<div class="dsh-upd-banner" data-kind="restart" role="status"><div><strong>' + restart.length +
|
|
341
|
+
'<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
342
|
);
|
|
224
343
|
}
|
|
225
344
|
return parts.join("");
|
|
@@ -236,35 +355,43 @@ function rowSetHTML(row, ctx) {
|
|
|
236
355
|
const off = ctx.inFlight ? " disabled" : "";
|
|
237
356
|
if (phase === "installing") {
|
|
238
357
|
actions.push(
|
|
239
|
-
'<button type="button" data-act="row-install" data-key="' + keyAttr + '" disabled
|
|
358
|
+
'<button type="button" data-act="row-install" data-key="' + keyAttr + '" disabled>' + escapeHtml(batchText("batch.row-action.installing", ctx.lang)) + "</button>"
|
|
240
359
|
);
|
|
241
360
|
} else if (queued) {
|
|
242
361
|
if (cancelQueuePhoneOf(row) !== null && queuedRequestIdOf(row) !== null) {
|
|
243
362
|
actions.push(
|
|
244
|
-
'<button type="button" data-act="row-cancel-queue" data-key="' + keyAttr + '"' + off + "
|
|
363
|
+
'<button type="button" data-act="row-cancel-queue" data-key="' + keyAttr + '"' + off + ">" + escapeHtml(batchText("batch.row-action.cancel-queue", ctx.lang)) + "</button>"
|
|
245
364
|
);
|
|
246
365
|
}
|
|
247
366
|
} else if (phase === "ready" && skipped === null) {
|
|
248
367
|
actions.push(
|
|
249
|
-
'<button type="button" data-act="row-install" data-key="' + keyAttr + '" data-primary="1"' + off + ">" + (ctx.busy ? "
|
|
368
|
+
'<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
369
|
);
|
|
251
370
|
} else if (phase === "ready" && skipped !== null) {
|
|
252
371
|
actions.push(
|
|
253
|
-
'<button type="button" data-act="row-resume-skip" data-key="' + keyAttr + '"' + off + "
|
|
372
|
+
'<button type="button" data-act="row-resume-skip" data-key="' + keyAttr + '"' + off + ">" + escapeHtml(batchText("batch.row-action.unskip", ctx.lang, { version: skipped })) + "</button>"
|
|
254
373
|
);
|
|
255
374
|
} else if (phase === "failed") {
|
|
256
375
|
actions.push(
|
|
257
|
-
'<button type="button" data-act="row-install" data-key="' + keyAttr + '"' + off + ">" + (ctx.busy ? "
|
|
376
|
+
'<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
377
|
);
|
|
259
378
|
}
|
|
260
379
|
if (row.restartRequired === true) {
|
|
261
|
-
actions.push('<button type="button" data-act="restart" data-key="' + keyAttr + '"
|
|
380
|
+
actions.push('<button type="button" data-act="restart" data-key="' + keyAttr + '">' + escapeHtml(batchText("batch.row-action.restart", ctx.lang)) + "</button>");
|
|
262
381
|
}
|
|
263
382
|
actions.push(
|
|
264
|
-
'<button type="button" data-act="toggle-details" data-key="' + keyAttr + '">' + (ctx.expanded ? "
|
|
383
|
+
'<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
384
|
);
|
|
266
|
-
const failLine = phase === "failed" && !queued ?
|
|
267
|
-
|
|
385
|
+
const failLine = phase === "failed" && !queued ? (() => {
|
|
386
|
+
const failCode = row.error || "install-failed";
|
|
387
|
+
const failDetail = failureCopy(failCode, ctx.lang)?.zh ?? failureCopy("unknown", ctx.lang)?.zh ?? "";
|
|
388
|
+
const label = batchText("batch.row.error-label", ctx.lang, { code: failCode, detail: failDetail });
|
|
389
|
+
const escaped = escapeHtml(label);
|
|
390
|
+
const codeEsc = escapeHtml(failCode);
|
|
391
|
+
const withCode = escaped.includes(codeEsc) ? escaped.replace(codeEsc, "<code>" + codeEsc + "</code>") : escaped;
|
|
392
|
+
return '<span class="dsh-upd-bfail">' + withCode + "</span>";
|
|
393
|
+
})() : "";
|
|
394
|
+
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
395
|
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
396
|
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
397
|
}
|
|
@@ -286,7 +413,7 @@ function detailHTML(row, ctx) {
|
|
|
286
413
|
theme: ctx.theme,
|
|
287
414
|
profileName: typeof row.profileName === "string" && row.profileName ? row.profileName : null,
|
|
288
415
|
actions: "none"
|
|
289
|
-
});
|
|
416
|
+
}, ctx.lang);
|
|
290
417
|
return stripActionButtons(html);
|
|
291
418
|
}
|
|
292
419
|
function detailActionsHTML(row, ctx) {
|
|
@@ -297,38 +424,38 @@ function detailActionsHTML(row, ctx) {
|
|
|
297
424
|
const off = ctx.inFlight ? " disabled" : "";
|
|
298
425
|
const buttons = [];
|
|
299
426
|
if (phase === "installing") {
|
|
300
|
-
buttons.push('<button type="button" data-act="row-install" data-key="' + keyAttr + '" disabled
|
|
427
|
+
buttons.push('<button type="button" data-act="row-install" data-key="' + keyAttr + '" disabled>' + escapeHtml(batchText("batch.row-action.installing", ctx.lang)) + "</button>");
|
|
301
428
|
} else if (queued) {
|
|
302
429
|
if (cancelQueuePhoneOf(row) !== null && queuedRequestIdOf(row) !== null) {
|
|
303
430
|
buttons.push(
|
|
304
|
-
'<button type="button" data-act="row-cancel-queue" data-key="' + keyAttr + '"' + off + "
|
|
431
|
+
'<button type="button" data-act="row-cancel-queue" data-key="' + keyAttr + '"' + off + ">" + escapeHtml(batchText("batch.row-action.cancel-queue", ctx.lang)) + "</button>"
|
|
305
432
|
);
|
|
306
433
|
}
|
|
307
434
|
} else if (phase === "failed") {
|
|
308
435
|
buttons.push(
|
|
309
|
-
'<button type="button" data-act="row-install" data-key="' + keyAttr + '"' + off + ">" + (ctx.busy ? "
|
|
436
|
+
'<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
437
|
);
|
|
311
438
|
} else if (phase === "ready" && ctx.skipped === null) {
|
|
312
439
|
buttons.push(
|
|
313
|
-
'<button type="button" data-act="row-install" data-key="' + keyAttr + '" data-primary="1"' + off + ">" + (ctx.busy ? "
|
|
440
|
+
'<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
441
|
);
|
|
315
442
|
}
|
|
316
443
|
if (!queued && phase === "ready" && ctx.skipped === null && version !== null) {
|
|
317
444
|
buttons.push(
|
|
318
|
-
'<button type="button" data-act="row-skip" data-key="' + keyAttr + '"' + off + "
|
|
445
|
+
'<button type="button" data-act="row-skip" data-key="' + keyAttr + '"' + off + ">" + escapeHtml(batchText("batch.row-action.skip", ctx.lang)) + "</button>"
|
|
319
446
|
);
|
|
320
447
|
}
|
|
321
448
|
if (ctx.skipped !== null) {
|
|
322
449
|
buttons.push(
|
|
323
|
-
'<button type="button" data-act="row-resume-skip" data-key="' + keyAttr + '"' + off + "
|
|
450
|
+
'<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
451
|
);
|
|
325
452
|
}
|
|
326
453
|
if (typeof row.manual === "string" && row.manual) {
|
|
327
454
|
buttons.push(
|
|
328
|
-
'<button type="button" data-act="row-copy-manual" data-key="' + keyAttr + '"' + off + "
|
|
455
|
+
'<button type="button" data-act="row-copy-manual" data-key="' + keyAttr + '"' + off + ">" + escapeHtml(batchText("batch.row-action.copy-manual", ctx.lang)) + "</button>"
|
|
329
456
|
);
|
|
330
457
|
}
|
|
331
|
-
buttons.push('<button type="button" data-act="row-copy-diag" data-key="' + keyAttr + '"' + off + "
|
|
458
|
+
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
459
|
return '<span class="dsh-upd-bdetail-actions">' + buttons.join("") + "</span>";
|
|
333
460
|
}
|
|
334
461
|
function stripActionButtons(html) {
|
|
@@ -344,37 +471,37 @@ function dotToneOf(row, phase, skipped, queued) {
|
|
|
344
471
|
return "idle";
|
|
345
472
|
}
|
|
346
473
|
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\
|
|
474
|
+
"/* \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
475
|
".dsh-upd-batch-head{display:flex;align-items:baseline;justify-content:space-between;gap:10px;flex-wrap:wrap}",
|
|
349
476
|
".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-
|
|
477
|
+
".dsh-upd-batch-title i{font-style:normal;color:var(--dsh-update-primary,#2563eb)}",
|
|
351
478
|
".dsh-upd-batch-macros{flex:none}",
|
|
352
479
|
".dsh-upd-batch-sum{margin:4px 0 8px;font-size:13.5px}",
|
|
353
480
|
".dsh-upd-btable{margin-top:2px}",
|
|
354
|
-
".dsh-upd-brow-set{border-top:1px solid var(--dsh-
|
|
481
|
+
".dsh-upd-brow-set{border-top:1px solid var(--dsh-update-border,#e5e7eb)}",
|
|
355
482
|
".dsh-upd-brow-set:first-child{border-top:0}",
|
|
356
483
|
".dsh-upd-brow{display:flex;align-items:center;gap:8px;flex-wrap:wrap;padding:6px 0}",
|
|
357
484
|
".dsh-upd .dsh-upd-brow-main{display:flex;align-items:center;gap:8px;flex-wrap:wrap;flex:1 1 260px;min-width:0;",
|
|
358
485
|
"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-
|
|
486
|
+
".dsh-upd .dsh-upd-brow-main:hover{color:var(--dsh-update-primary,#2563eb)}",
|
|
360
487
|
".dsh-upd-brow-actions{flex:none;margin-left:auto}",
|
|
361
488
|
".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-
|
|
489
|
+
".dsh-upd-updot{width:8px;height:8px;border-radius:50%;flex:none;background:var(--dsh-update-border,#9ca3af);opacity:.55}",
|
|
490
|
+
'.dsh-upd-updot[data-tone="todo"]{background:var(--dsh-update-ok-border,#059669);opacity:1}',
|
|
491
|
+
'.dsh-upd-updot[data-tone="ok"]{background:var(--dsh-update-ok-border,#059669);opacity:1}',
|
|
492
|
+
'.dsh-upd-updot[data-tone="busy"]{background:var(--dsh-update-busy-border,#2563eb);opacity:1}',
|
|
493
|
+
'.dsh-upd-updot[data-tone="warn"]{background:var(--dsh-update-warn-border,#d97706);opacity:1}',
|
|
494
|
+
'.dsh-upd-updot[data-tone="bad"]{background:var(--dsh-update-bad-border,#dc2626);opacity:1}',
|
|
368
495
|
".dsh-upd-bname{font-weight:700;flex:none}",
|
|
369
496
|
".dsh-upd-bver{font-family:Consolas,Menlo,monospace;font-size:12px;opacity:.8;flex:none}",
|
|
370
497
|
".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-
|
|
498
|
+
".dsh-upd-bfail{flex:1 1 100%;display:block;font-size:12.5px;color:var(--dsh-update-bad-border,#dc2626)}",
|
|
372
499
|
".dsh-upd-blist{font-size:12.5px;margin-top:2px}",
|
|
373
500
|
".dsh-upd-batch-ledger{margin:8px 0 0;font-size:13px;opacity:.85}",
|
|
374
501
|
".dsh-upd-batch-more{margin-top:6px}",
|
|
375
502
|
".dsh-upd-batch-more button{font-size:12px}",
|
|
376
503
|
// 确认态:红框红字,与「关闭」等中性按钮一眼区分;disabled 照旧置灰。
|
|
377
|
-
'.dsh-upd-batch-more button[data-confirm="1"]{border-color:var(--dsh-
|
|
504
|
+
'.dsh-upd-batch-more button[data-confirm="1"]{border-color:var(--dsh-update-bad-border,#dc2626);color:var(--dsh-update-bad-border,#dc2626)}',
|
|
378
505
|
".dsh-upd-batch-notice{margin-top:6px;font-size:12.5px;opacity:.85}",
|
|
379
506
|
".dsh-upd-bdetail-actions{margin:0 0 6px}",
|
|
380
507
|
".dsh-upd .dsh-upd-bdetail-actions button{font-size:12.5px}",
|
|
@@ -385,21 +512,28 @@ const UPDATE_BATCH_PANEL_CSS = [
|
|
|
385
512
|
".dsh-upd-overlay .dsh-upd-bdetail .dsh-upd{max-height:none;overflow:visible}",
|
|
386
513
|
".dsh-upd-overlay .dsh-upd-bdetail .dsh-upd-body{overflow:visible}",
|
|
387
514
|
".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}}"
|
|
515
|
+
"@media (prefers-color-scheme: dark){.dsh-upd-batch-title i{color:var(--dsh-update-focus,#93c5fd)}}",
|
|
516
|
+
"@media (prefers-reduced-motion: reduce){.dsh-upd-batch *{transition:none !important;animation:none !important}}",
|
|
517
|
+
// Batch check layout stability: reserve macro width + rows/summary heights + no scroll anchoring jumps.
|
|
518
|
+
".dsh-upd-batch{overflow-anchor:none}",
|
|
519
|
+
".dsh-upd-btable{overflow-anchor:none}",
|
|
520
|
+
".dsh-upd-batch-macros{display:flex;flex-wrap:wrap;align-items:center;gap:0}",
|
|
521
|
+
'.dsh-upd-batch-macros button:first-child,.dsh-upd-batch-macros button[data-primary="1"]{min-width:6em;text-align:center}',
|
|
522
|
+
".dsh-upd-batch-sum,.dsh-upd-batch-ledger{min-height:1.6em}",
|
|
523
|
+
".dsh-upd-brow{min-height:28px}"
|
|
390
524
|
].join(String.fromCharCode(10));
|
|
391
|
-
const
|
|
392
|
-
"/* \u6279\u91CF\u9762\u677F\u7684
|
|
525
|
+
const UPDATE_BATCH_PANEL_ARCHIVE_CSS = [
|
|
526
|
+
"/* \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
527
|
'.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(--
|
|
528
|
+
'.dsh-upd[data-theme="archive"] .dsh-upd-batch-title{font-family:var(--dsh-update-font-serif);font-size:21px;letter-spacing:.04em}',
|
|
529
|
+
'.dsh-upd[data-theme="archive"] .dsh-upd-batch-title i{color:var(--dsh-update-primary)}',
|
|
530
|
+
'.dsh-upd[data-theme="archive"] .dsh-upd-brow-main{background:transparent;border:0;color:var(--dsh-update-text)}',
|
|
531
|
+
'.dsh-upd[data-theme="archive"] .dsh-upd-brow-main:hover{color:var(--dsh-update-primary)}',
|
|
532
|
+
'.dsh-upd[data-theme="archive"] .dsh-upd-bname{font-family:var(--dsh-update-font-serif)}',
|
|
533
|
+
'.dsh-upd[data-theme="archive"] .dsh-upd-bver{font-family:var(--dsh-update-font-mono);color:var(--dsh-update-text-muted)}',
|
|
534
|
+
'.dsh-upd[data-theme="archive"] .dsh-upd-batch-ledger{color:var(--dsh-update-text-muted)}',
|
|
535
|
+
'.dsh-upd[data-theme="archive"] .dsh-upd-batch-sum{color:var(--dsh-update-text)}',
|
|
536
|
+
'.dsh-upd[data-theme="archive"] .dsh-upd-brow-set{border-top-color:var(--dsh-update-border)}'
|
|
403
537
|
].join(String.fromCharCode(10));
|
|
404
538
|
function escapeHtml(text) {
|
|
405
539
|
return String(text).replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """);
|
|
@@ -513,14 +647,14 @@ function jobFailureOf(row) {
|
|
|
513
647
|
const detail = message.slice(at + 1).trim();
|
|
514
648
|
return { code: code || null, detail: detail || null };
|
|
515
649
|
}
|
|
516
|
-
function diagTextOf(row) {
|
|
650
|
+
function diagTextOf(row, lang) {
|
|
517
651
|
const snapshot = isObject(row.snapshot) ? row.snapshot : null;
|
|
518
652
|
const queue = isObject(row.queue) ? row.queue : null;
|
|
519
653
|
const diag = isObject(row.diag) ? row.diag : null;
|
|
520
654
|
const text = (value) => typeof value === "string" && value ? value : null;
|
|
521
655
|
const job = jobFailureOf(row);
|
|
522
656
|
const diagDetail = diag ? text(diag["detail"]) : null;
|
|
523
|
-
const detail = diagDetail !== null ? diagDetail : job !== null && job.detail !== null ? job.detail + "
|
|
657
|
+
const detail = diagDetail !== null ? diagDetail : job !== null && job.detail !== null ? job.detail + batchText("batch.diag.source-job", langOf(lang)) : null;
|
|
524
658
|
const input = {
|
|
525
659
|
pluginId: pluginIdOf(row),
|
|
526
660
|
code: job !== null && job.code !== null ? job.code : row.error || "check-failed",
|
|
@@ -532,7 +666,9 @@ function diagTextOf(row) {
|
|
|
532
666
|
queuePosition: queue && typeof queue["position"] === "number" ? queue["position"] : null,
|
|
533
667
|
manual: text(row.manual),
|
|
534
668
|
diag: row.diag ?? null,
|
|
535
|
-
profileName: text(row.profileName)
|
|
669
|
+
profileName: text(row.profileName),
|
|
670
|
+
// #63 透传语言(批量 en 跟随在 #64/#65 落;此处缺省 zh 零回归)。
|
|
671
|
+
lang: lang ?? "zh"
|
|
536
672
|
};
|
|
537
673
|
return buildDiagnosticText(input);
|
|
538
674
|
}
|
|
@@ -622,8 +758,8 @@ function mountUpdateBatchPanel(container, options) {
|
|
|
622
758
|
if (mode !== "embedded" && mode !== "dialog") {
|
|
623
759
|
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
760
|
}
|
|
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\
|
|
761
|
+
if (options.theme !== void 0 && options.theme !== "default" && options.theme !== "archive") {
|
|
762
|
+
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
763
|
}
|
|
628
764
|
let theme = normalizePanelTheme(options.theme ?? "default");
|
|
629
765
|
const call = options.call;
|
|
@@ -647,6 +783,18 @@ function mountUpdateBatchPanel(container, options) {
|
|
|
647
783
|
let refreshing = false;
|
|
648
784
|
let confirmCancelArmed = false;
|
|
649
785
|
let mounted = true;
|
|
786
|
+
const localeOpt = options["locale"];
|
|
787
|
+
function currentLang() {
|
|
788
|
+
return langOf(localeOpt);
|
|
789
|
+
}
|
|
790
|
+
const checkOnOpenOption = options["checkOnOpen"] !== false;
|
|
791
|
+
const autoResumeOption = options["autoResume"] !== false;
|
|
792
|
+
let lastSession = null;
|
|
793
|
+
let lastInventory = null;
|
|
794
|
+
let lastPrefs = null;
|
|
795
|
+
let lastCheckedAt = 0;
|
|
796
|
+
let autoCheckDone = false;
|
|
797
|
+
let autoResumeDone = false;
|
|
650
798
|
function changelogView() {
|
|
651
799
|
const out = {};
|
|
652
800
|
for (const row of rows) {
|
|
@@ -680,13 +828,13 @@ function mountUpdateBatchPanel(container, options) {
|
|
|
680
828
|
const failKey = key + "\0" + version;
|
|
681
829
|
const hasCache = false;
|
|
682
830
|
const failedAt = rowFailedAt.has(failKey) ? rowFailedAt.get(failKey) : null;
|
|
683
|
-
let
|
|
831
|
+
let nowMs2 = 0;
|
|
684
832
|
try {
|
|
685
|
-
|
|
833
|
+
nowMs2 = Date.now();
|
|
686
834
|
} catch {
|
|
687
|
-
|
|
835
|
+
nowMs2 = 0;
|
|
688
836
|
}
|
|
689
|
-
if (!shouldFetchChangelog({ hasCache, failedAt, now:
|
|
837
|
+
if (!shouldFetchChangelog({ hasCache, failedAt, now: nowMs2, isManual: false })) return;
|
|
690
838
|
} catch {
|
|
691
839
|
}
|
|
692
840
|
const phone2 = changelogPhoneOf(row);
|
|
@@ -727,6 +875,77 @@ function mountUpdateBatchPanel(container, options) {
|
|
|
727
875
|
}
|
|
728
876
|
);
|
|
729
877
|
}
|
|
878
|
+
function setStableHTML(target, html) {
|
|
879
|
+
try {
|
|
880
|
+
const g = globalThis;
|
|
881
|
+
const doc = g["document"];
|
|
882
|
+
const el = target;
|
|
883
|
+
if (!doc || typeof el.querySelectorAll !== "function") {
|
|
884
|
+
target.innerHTML = html;
|
|
885
|
+
return;
|
|
886
|
+
}
|
|
887
|
+
let focusAct = null;
|
|
888
|
+
let focusKey = null;
|
|
889
|
+
try {
|
|
890
|
+
const active = doc.activeElement;
|
|
891
|
+
if (active && typeof active.getAttribute === "function") {
|
|
892
|
+
focusAct = active.getAttribute("data-act");
|
|
893
|
+
focusKey = active.getAttribute("data-key");
|
|
894
|
+
}
|
|
895
|
+
} catch {
|
|
896
|
+
focusAct = null;
|
|
897
|
+
focusKey = null;
|
|
898
|
+
}
|
|
899
|
+
let scrolls = [];
|
|
900
|
+
try {
|
|
901
|
+
const nodes = el.querySelectorAll(".dsh-upd-btable");
|
|
902
|
+
if (nodes) {
|
|
903
|
+
for (let i = 0; i < nodes.length; i++) {
|
|
904
|
+
const n = nodes[i];
|
|
905
|
+
scrolls.push(typeof n.scrollTop === "number" ? n.scrollTop : 0);
|
|
906
|
+
}
|
|
907
|
+
}
|
|
908
|
+
} catch {
|
|
909
|
+
scrolls = [];
|
|
910
|
+
}
|
|
911
|
+
target.innerHTML = html;
|
|
912
|
+
try {
|
|
913
|
+
const bodies = el.querySelectorAll(".dsh-upd-btable");
|
|
914
|
+
if (bodies) {
|
|
915
|
+
for (let i = 0; i < bodies.length && i < scrolls.length; i++) {
|
|
916
|
+
const n = bodies[i];
|
|
917
|
+
try {
|
|
918
|
+
n.scrollTop = scrolls[i];
|
|
919
|
+
} catch {
|
|
920
|
+
}
|
|
921
|
+
}
|
|
922
|
+
}
|
|
923
|
+
} catch {
|
|
924
|
+
}
|
|
925
|
+
try {
|
|
926
|
+
if (focusAct && typeof el.querySelector === "function") {
|
|
927
|
+
const sel = focusKey ? '[data-act="' + focusAct + '"][data-key="' + focusKey + '"]' : '[data-act="' + focusAct + '"]';
|
|
928
|
+
const next = el.querySelector(sel);
|
|
929
|
+
if (next && typeof next.focus === "function") {
|
|
930
|
+
try {
|
|
931
|
+
next.focus.call(next, { preventScroll: true });
|
|
932
|
+
} catch {
|
|
933
|
+
try {
|
|
934
|
+
next.focus.call(next);
|
|
935
|
+
} catch {
|
|
936
|
+
}
|
|
937
|
+
}
|
|
938
|
+
}
|
|
939
|
+
}
|
|
940
|
+
} catch {
|
|
941
|
+
}
|
|
942
|
+
} catch {
|
|
943
|
+
try {
|
|
944
|
+
target.innerHTML = html;
|
|
945
|
+
} catch {
|
|
946
|
+
}
|
|
947
|
+
}
|
|
948
|
+
}
|
|
730
949
|
let lastHTML = "";
|
|
731
950
|
function render() {
|
|
732
951
|
if (!mounted) return;
|
|
@@ -743,11 +962,15 @@ function mountUpdateBatchPanel(container, options) {
|
|
|
743
962
|
loaded,
|
|
744
963
|
titles,
|
|
745
964
|
confirmCancel: confirmCancelArmed,
|
|
746
|
-
changelogs: changelogView()
|
|
965
|
+
changelogs: changelogView(),
|
|
966
|
+
session: lastSession,
|
|
967
|
+
inventory: lastInventory,
|
|
968
|
+
prefs: lastPrefs,
|
|
969
|
+
lang: currentLang()
|
|
747
970
|
});
|
|
748
971
|
if (nextHTML !== lastHTML) {
|
|
749
972
|
lastHTML = nextHTML;
|
|
750
|
-
container
|
|
973
|
+
setStableHTML(container, nextHTML);
|
|
751
974
|
}
|
|
752
975
|
}
|
|
753
976
|
function rowOfKey(key) {
|
|
@@ -789,7 +1012,7 @@ function mountUpdateBatchPanel(container, options) {
|
|
|
789
1012
|
await copyText(text);
|
|
790
1013
|
say(okNotice, key);
|
|
791
1014
|
} catch {
|
|
792
|
-
say("
|
|
1015
|
+
say(batchText("batch.toast.copy-fail", currentLang()), key);
|
|
793
1016
|
}
|
|
794
1017
|
render();
|
|
795
1018
|
}
|
|
@@ -802,6 +1025,13 @@ function mountUpdateBatchPanel(container, options) {
|
|
|
802
1025
|
const session = normalizeBatchSession(reply["session"]);
|
|
803
1026
|
const parsed = readRows(reply["rows"]);
|
|
804
1027
|
rows = parsed.length > 0 ? parsed : rowsFromSession(session);
|
|
1028
|
+
lastSession = session;
|
|
1029
|
+
if (isObject(reply["inventory"])) {
|
|
1030
|
+
lastInventory = reply["inventory"];
|
|
1031
|
+
const at = reply["inventory"]["updatedAt"];
|
|
1032
|
+
if (typeof at === "number" && Number.isFinite(at) && at > 0) lastCheckedAt = at;
|
|
1033
|
+
}
|
|
1034
|
+
if (isObject(reply["prefs"])) lastPrefs = reply["prefs"];
|
|
805
1035
|
loaded = true;
|
|
806
1036
|
lastError = null;
|
|
807
1037
|
if (expandedKey !== null && !rows.some((row) => row.key === expandedKey)) expandedKey = null;
|
|
@@ -828,27 +1058,49 @@ function mountUpdateBatchPanel(container, options) {
|
|
|
828
1058
|
maybeAutoRowChangelog(expandedKey);
|
|
829
1059
|
}
|
|
830
1060
|
async function phone(name, args, busyRowKey = null) {
|
|
831
|
-
if (!mounted || inFlight) return;
|
|
1061
|
+
if (!mounted || inFlight) return null;
|
|
832
1062
|
inFlight = true;
|
|
833
1063
|
clearNotice();
|
|
834
1064
|
render();
|
|
1065
|
+
let out = null;
|
|
835
1066
|
try {
|
|
836
1067
|
const reply = await call(name, args);
|
|
837
|
-
if (!mounted) return;
|
|
1068
|
+
if (!mounted) return null;
|
|
838
1069
|
if (busyRowKey !== null && isBusyReply(reply)) {
|
|
839
|
-
say("
|
|
840
|
-
return;
|
|
1070
|
+
say(batchText("batch.toast.queue-missed", currentLang()), busyRowKey);
|
|
1071
|
+
return null;
|
|
841
1072
|
}
|
|
842
1073
|
applyReply(reply);
|
|
843
1074
|
rowFailedAt.clear();
|
|
1075
|
+
out = isObject(reply) ? reply : null;
|
|
844
1076
|
} catch {
|
|
845
|
-
if (!mounted) return;
|
|
1077
|
+
if (!mounted) return null;
|
|
846
1078
|
lastError = "check-failed";
|
|
1079
|
+
out = null;
|
|
847
1080
|
} finally {
|
|
848
1081
|
inFlight = false;
|
|
849
1082
|
if (mounted) render();
|
|
850
1083
|
}
|
|
851
1084
|
maybeAutoRowChangelog(expandedKey);
|
|
1085
|
+
return out;
|
|
1086
|
+
}
|
|
1087
|
+
function remainingCount() {
|
|
1088
|
+
return unfinishedCount(rows, lastSession ?? void 0);
|
|
1089
|
+
}
|
|
1090
|
+
function checkOnOpenEffective() {
|
|
1091
|
+
if (isObject(lastPrefs)) {
|
|
1092
|
+
const v = lastPrefs["checkOnOpen"];
|
|
1093
|
+
if (v === false) return false;
|
|
1094
|
+
if (v === true) return true;
|
|
1095
|
+
}
|
|
1096
|
+
return checkOnOpenOption;
|
|
1097
|
+
}
|
|
1098
|
+
function nowMs() {
|
|
1099
|
+
try {
|
|
1100
|
+
return Date.now();
|
|
1101
|
+
} catch {
|
|
1102
|
+
return 0;
|
|
1103
|
+
}
|
|
852
1104
|
}
|
|
853
1105
|
async function act(kind, key) {
|
|
854
1106
|
if (!mounted) return;
|
|
@@ -858,17 +1110,26 @@ function mountUpdateBatchPanel(container, options) {
|
|
|
858
1110
|
}
|
|
859
1111
|
switch (kind) {
|
|
860
1112
|
case "check":
|
|
861
|
-
|
|
1113
|
+
await phone(phones.check, {});
|
|
1114
|
+
return;
|
|
862
1115
|
case "install":
|
|
863
|
-
|
|
1116
|
+
await phone(phones.install, {});
|
|
1117
|
+
return;
|
|
864
1118
|
case "row-install": {
|
|
865
1119
|
if (typeof key !== "string" || !key) return;
|
|
866
|
-
|
|
1120
|
+
await phone(phones.install, { keys: [key] }, key);
|
|
1121
|
+
return;
|
|
867
1122
|
}
|
|
868
1123
|
case "resume": {
|
|
869
|
-
await phone(phones.resume, {});
|
|
1124
|
+
const reply = await phone(phones.resume, {});
|
|
870
1125
|
if (!mounted) return;
|
|
871
|
-
|
|
1126
|
+
if (!reply || reply["ok"] !== true) return;
|
|
1127
|
+
if (reply["resumed"] === false) {
|
|
1128
|
+
say(batchText("batch.notice.no-resume", currentLang()));
|
|
1129
|
+
render();
|
|
1130
|
+
return;
|
|
1131
|
+
}
|
|
1132
|
+
say(batchText("batch.notice.resumed", currentLang(), { count: String(remainingCount()) }));
|
|
872
1133
|
render();
|
|
873
1134
|
return;
|
|
874
1135
|
}
|
|
@@ -876,9 +1137,18 @@ function mountUpdateBatchPanel(container, options) {
|
|
|
876
1137
|
// 鼠标误触的防护在 onClick 那一层(第一次点击只上膛)。
|
|
877
1138
|
case "cancel": {
|
|
878
1139
|
confirmCancelArmed = false;
|
|
879
|
-
await phone(phones.cancel, {});
|
|
1140
|
+
const reply = await phone(phones.cancel, {});
|
|
880
1141
|
if (!mounted) return;
|
|
881
|
-
|
|
1142
|
+
if (!reply || reply["ok"] !== true) return;
|
|
1143
|
+
say(batchText("batch.notice.discarded", currentLang()));
|
|
1144
|
+
render();
|
|
1145
|
+
return;
|
|
1146
|
+
}
|
|
1147
|
+
case "toggle-check-on-open": {
|
|
1148
|
+
const next = !checkOnOpenEffective();
|
|
1149
|
+
const reply = await phone(phones.prefsSave, { checkOnOpen: next });
|
|
1150
|
+
if (!mounted) return;
|
|
1151
|
+
if (reply && reply["ok"] === true && isObject(reply["prefs"])) lastPrefs = reply["prefs"];
|
|
882
1152
|
render();
|
|
883
1153
|
return;
|
|
884
1154
|
}
|
|
@@ -891,7 +1161,7 @@ function mountUpdateBatchPanel(container, options) {
|
|
|
891
1161
|
skipStoreFor(pluginIdOf(row)).skip(version);
|
|
892
1162
|
} catch {
|
|
893
1163
|
}
|
|
894
|
-
say("
|
|
1164
|
+
say(batchText("batch.toast.skipped", currentLang(), { version }), row.key);
|
|
895
1165
|
render();
|
|
896
1166
|
return;
|
|
897
1167
|
}
|
|
@@ -903,7 +1173,7 @@ function mountUpdateBatchPanel(container, options) {
|
|
|
903
1173
|
skipStoreFor(pluginIdOf(row)).reset(version ?? void 0);
|
|
904
1174
|
} catch {
|
|
905
1175
|
}
|
|
906
|
-
say(version ? "
|
|
1176
|
+
say(version ? batchText("batch.toast.unskipped-version", currentLang(), { version }) : batchText("batch.toast.unskipped-all", currentLang()), row.key);
|
|
907
1177
|
render();
|
|
908
1178
|
return;
|
|
909
1179
|
}
|
|
@@ -915,7 +1185,7 @@ function mountUpdateBatchPanel(container, options) {
|
|
|
915
1185
|
const phoneName = cancelQueuePhoneOf(row);
|
|
916
1186
|
const requestId = queuedRequestIdOf(row);
|
|
917
1187
|
if (phoneName === null || requestId === null) {
|
|
918
|
-
say("
|
|
1188
|
+
say(batchText("batch.toast.cancel-unavailable", currentLang()), row.key);
|
|
919
1189
|
render();
|
|
920
1190
|
return;
|
|
921
1191
|
}
|
|
@@ -925,9 +1195,9 @@ function mountUpdateBatchPanel(container, options) {
|
|
|
925
1195
|
render();
|
|
926
1196
|
try {
|
|
927
1197
|
await call(phoneName, { cancelQueued: true, requestId });
|
|
928
|
-
if (mounted) say("
|
|
1198
|
+
if (mounted) say(batchText("batch.toast.cancel-ok", currentLang()), row.key);
|
|
929
1199
|
} catch {
|
|
930
|
-
if (mounted) say("
|
|
1200
|
+
if (mounted) say(batchText("batch.toast.cancel-fail", currentLang()), row.key);
|
|
931
1201
|
} finally {
|
|
932
1202
|
inFlight = false;
|
|
933
1203
|
}
|
|
@@ -938,13 +1208,13 @@ function mountUpdateBatchPanel(container, options) {
|
|
|
938
1208
|
const row = typeof key === "string" && key ? rowOfKey(key) : null;
|
|
939
1209
|
const manual = row && typeof row.manual === "string" ? row.manual : "";
|
|
940
1210
|
if (!row || !manual) return;
|
|
941
|
-
await copyWith(manual, "
|
|
1211
|
+
await copyWith(manual, batchText("batch.toast.copy-manual-ok", currentLang()), row.key);
|
|
942
1212
|
return;
|
|
943
1213
|
}
|
|
944
1214
|
case "row-copy-diag": {
|
|
945
1215
|
const row = typeof key === "string" && key ? rowOfKey(key) : null;
|
|
946
1216
|
if (!row) return;
|
|
947
|
-
await copyWith(diagTextOf(row), "
|
|
1217
|
+
await copyWith(diagTextOf(row, currentLang()), batchText("batch.toast.copy-diag-ok", currentLang()), row.key);
|
|
948
1218
|
return;
|
|
949
1219
|
}
|
|
950
1220
|
case "toggle-details": {
|
|
@@ -960,12 +1230,12 @@ function mountUpdateBatchPanel(container, options) {
|
|
|
960
1230
|
try {
|
|
961
1231
|
if (typeof onRestartRequested === "function") {
|
|
962
1232
|
await onRestartRequested();
|
|
963
|
-
say("
|
|
1233
|
+
say(batchText("batch.toast.restart-delegated", currentLang()));
|
|
964
1234
|
} else {
|
|
965
|
-
say("
|
|
1235
|
+
say(batchText("batch.toast.restart-manual", currentLang()));
|
|
966
1236
|
}
|
|
967
1237
|
} catch {
|
|
968
|
-
say("
|
|
1238
|
+
say(batchText("batch.toast.restart-failed", currentLang()));
|
|
969
1239
|
}
|
|
970
1240
|
render();
|
|
971
1241
|
return;
|
|
@@ -997,8 +1267,8 @@ function mountUpdateBatchPanel(container, options) {
|
|
|
997
1267
|
}
|
|
998
1268
|
}
|
|
999
1269
|
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\
|
|
1270
|
+
if (next !== "default" && next !== "archive") {
|
|
1271
|
+
throw new Error("[dsh-plugin-update] \u4E3B\u9898\u975E\u6CD5\uFF1A\u53EA\u6536 default \u6216 archive\uFF08\u6536\u5230 " + JSON.stringify(next) + "\uFF09");
|
|
1002
1272
|
}
|
|
1003
1273
|
theme = normalizePanelTheme(next);
|
|
1004
1274
|
render();
|
|
@@ -1018,7 +1288,7 @@ function mountUpdateBatchPanel(container, options) {
|
|
|
1018
1288
|
if (!kind) return;
|
|
1019
1289
|
if (kind === "cancel" && !confirmCancelArmed) {
|
|
1020
1290
|
confirmCancelArmed = true;
|
|
1021
|
-
say("
|
|
1291
|
+
say(batchText("batch.notice.cancel-confirm", currentLang()));
|
|
1022
1292
|
render();
|
|
1023
1293
|
return;
|
|
1024
1294
|
}
|
|
@@ -1028,9 +1298,64 @@ function mountUpdateBatchPanel(container, options) {
|
|
|
1028
1298
|
} catch {
|
|
1029
1299
|
}
|
|
1030
1300
|
}
|
|
1301
|
+
async function autoOnce() {
|
|
1302
|
+
if (!mounted) return;
|
|
1303
|
+
if (autoResumeOption && !autoResumeDone) {
|
|
1304
|
+
autoResumeDone = true;
|
|
1305
|
+
if (hasUnfinishedRows(rows, lastSession ?? void 0) && !inFlight && !refreshing) {
|
|
1306
|
+
const before = lastError;
|
|
1307
|
+
try {
|
|
1308
|
+
const reply = await call(phones.resume, {});
|
|
1309
|
+
if (!mounted) return;
|
|
1310
|
+
if (isObject(reply) && reply["ok"] === true) {
|
|
1311
|
+
applyReply(reply);
|
|
1312
|
+
const r = reply;
|
|
1313
|
+
if (r["resumed"] !== false) {
|
|
1314
|
+
say(batchText("batch.notice.auto-resumed", currentLang(), { count: String(remainingCount()) }));
|
|
1315
|
+
rowFailedAt.clear();
|
|
1316
|
+
}
|
|
1317
|
+
render();
|
|
1318
|
+
maybeAutoRowChangelog(expandedKey);
|
|
1319
|
+
return;
|
|
1320
|
+
}
|
|
1321
|
+
lastError = before;
|
|
1322
|
+
render();
|
|
1323
|
+
} catch {
|
|
1324
|
+
if (mounted) render();
|
|
1325
|
+
}
|
|
1326
|
+
}
|
|
1327
|
+
}
|
|
1328
|
+
if (!autoCheckDone) {
|
|
1329
|
+
autoCheckDone = true;
|
|
1330
|
+
if (!checkOnOpenEffective()) return;
|
|
1331
|
+
if (hasUnfinishedRows(rows, lastSession ?? void 0)) return;
|
|
1332
|
+
const stale = lastCheckedAt <= 0 || nowMs() - lastCheckedAt >= 6e4;
|
|
1333
|
+
if (!stale || inFlight || refreshing) return;
|
|
1334
|
+
const before = lastError;
|
|
1335
|
+
try {
|
|
1336
|
+
const reply = await call(phones.check, {});
|
|
1337
|
+
if (!mounted) return;
|
|
1338
|
+
if (isObject(reply) && reply["ok"] === true) {
|
|
1339
|
+
applyReply(reply);
|
|
1340
|
+
rowFailedAt.clear();
|
|
1341
|
+
render();
|
|
1342
|
+
maybeAutoRowChangelog(expandedKey);
|
|
1343
|
+
return;
|
|
1344
|
+
}
|
|
1345
|
+
lastError = before;
|
|
1346
|
+
render();
|
|
1347
|
+
} catch {
|
|
1348
|
+
if (mounted) render();
|
|
1349
|
+
}
|
|
1350
|
+
}
|
|
1351
|
+
}
|
|
1031
1352
|
function unmount() {
|
|
1032
1353
|
if (!mounted) return;
|
|
1033
1354
|
mounted = false;
|
|
1355
|
+
try {
|
|
1356
|
+
unsubLang();
|
|
1357
|
+
} catch {
|
|
1358
|
+
}
|
|
1034
1359
|
rowAutoSeq++;
|
|
1035
1360
|
rowInflight.clear();
|
|
1036
1361
|
try {
|
|
@@ -1046,6 +1371,9 @@ function mountUpdateBatchPanel(container, options) {
|
|
|
1046
1371
|
} catch {
|
|
1047
1372
|
}
|
|
1048
1373
|
}
|
|
1374
|
+
const unsubLang = subscribeLang(() => {
|
|
1375
|
+
render();
|
|
1376
|
+
}, localeOpt);
|
|
1049
1377
|
render();
|
|
1050
1378
|
try {
|
|
1051
1379
|
container.addEventListener?.("click", onClick);
|
|
@@ -1057,6 +1385,7 @@ function mountUpdateBatchPanel(container, options) {
|
|
|
1057
1385
|
}
|
|
1058
1386
|
const timer = getTimer();
|
|
1059
1387
|
const handle = timer.set(() => {
|
|
1388
|
+
if (inFlight) return;
|
|
1060
1389
|
void refresh();
|
|
1061
1390
|
}, pollMs);
|
|
1062
1391
|
try {
|
|
@@ -1064,18 +1393,23 @@ function mountUpdateBatchPanel(container, options) {
|
|
|
1064
1393
|
if (h && typeof h.unref === "function") h.unref();
|
|
1065
1394
|
} catch {
|
|
1066
1395
|
}
|
|
1067
|
-
void refresh()
|
|
1396
|
+
void refresh().then(() => {
|
|
1397
|
+
void autoOnce();
|
|
1398
|
+
});
|
|
1068
1399
|
return { refresh, act, setTheme, setMode, unmount };
|
|
1069
1400
|
}
|
|
1070
1401
|
export {
|
|
1071
1402
|
BATCH_PANEL_POLL,
|
|
1403
|
+
UPDATE_BATCH_PANEL_ARCHIVE_CSS,
|
|
1072
1404
|
UPDATE_BATCH_PANEL_CSS,
|
|
1073
|
-
UPDATE_BATCH_PANEL_D5_CSS,
|
|
1074
1405
|
batchLedgerCounts,
|
|
1075
1406
|
batchLedgerText,
|
|
1076
1407
|
batchQueuedStatus,
|
|
1408
|
+
batchRowKnowledgeText,
|
|
1077
1409
|
batchRowStatus,
|
|
1078
1410
|
buildBatchPhoneNames,
|
|
1411
|
+
hasUnfinishedRows,
|
|
1079
1412
|
mountUpdateBatchPanel,
|
|
1080
|
-
renderBatchPanelHTML
|
|
1413
|
+
renderBatchPanelHTML,
|
|
1414
|
+
unfinishedCount
|
|
1081
1415
|
};
|