dsh-plugin-update 0.3.1 → 0.4.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 +11 -0
- package/README.md +51 -8
- package/dist/client.d.ts +4 -4
- package/dist/client.js +2 -1
- package/dist/config.d.ts +4 -1
- package/dist/config.js +8 -1
- package/dist/entry.d.ts +6 -0
- package/dist/entry.js +36 -4
- package/dist/host.d.ts +4 -4
- package/dist/host.js +77 -6
- package/dist/http.d.ts +2 -2
- package/dist/http.js +3 -2
- package/dist/panel-batch.d.ts +9 -0
- package/dist/panel-batch.js +113 -7
- package/dist/panel.d.ts +14 -1
- package/dist/panel.js +141 -16
- package/dist/service.d.ts +14 -0
- package/dist/service.js +50 -0
- package/package.json +1 -1
package/dist/panel-batch.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
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 { validReleaseVersion } from "./service.js";
|
|
3
4
|
import {
|
|
4
5
|
isTerminalPhase,
|
|
5
6
|
normalizeBatchSession
|
|
@@ -111,6 +112,7 @@ function renderBatchPanelHTML(input) {
|
|
|
111
112
|
const notice = typeof input.notice === "string" && input.notice ? input.notice : null;
|
|
112
113
|
const noticeKey = typeof input.noticeKey === "string" && input.noticeKey ? input.noticeKey : null;
|
|
113
114
|
const detailNoticeKey = notice !== null && noticeKey !== null && noticeKey === expandedKey ? noticeKey : null;
|
|
115
|
+
const changelogs = input.changelogs && typeof input.changelogs === "object" ? input.changelogs : {};
|
|
114
116
|
const ctx = {
|
|
115
117
|
expanded: false,
|
|
116
118
|
busy: installing,
|
|
@@ -118,15 +120,16 @@ function renderBatchPanelHTML(input) {
|
|
|
118
120
|
theme,
|
|
119
121
|
titles,
|
|
120
122
|
skipped: null,
|
|
121
|
-
notice: null
|
|
123
|
+
notice: null,
|
|
124
|
+
changelogMarkdown: null
|
|
122
125
|
};
|
|
123
126
|
const parts = [];
|
|
124
127
|
parts.push('<div class="dsh-upd-batch-head">');
|
|
125
128
|
parts.push('<div class="dsh-upd-batch-title">\u66F4\u65B0\u6863\u6848 \xB7 <i>\u603B\u8D26</i></div>');
|
|
126
129
|
parts.push('<div class="dsh-upd-batch-macros">');
|
|
127
|
-
parts.push('<button type="button" data-act="check"' + disabled + ">\u68C0\u67E5\u66F4\u65B0</button>
|
|
128
|
-
parts.push('<button type="button" data-act="install" data-primary="1"' + disabled + ">\u5168\u90E8\u66F4\u65B0</button>
|
|
129
|
-
if (mode === "dialog") parts.push('<button type="button" data-act="close">\u5173\u95ED</button>');
|
|
130
|
+
parts.push('<button type="button" data-act="check"' + disabled + ' title="\u91CD\u65B0\u8BFB\u53D6\u6279\u91CF\u72B6\u6001\uFF08\u53EA\u8BFB\uFF09">\u68C0\u67E5\u66F4\u65B0</button>');
|
|
131
|
+
parts.push('<button type="button" data-act="install" data-primary="1"' + disabled + ' title="\u628A\u6709\u65B0\u7248\u7684\u51E0\u5BB6\u4E00\u6B21\u63D0\u4EA4\uFF1B\u540C\u4E00\u4F1A\u8BDD\u540C\u4E00\u5E42\u7B49\u7F16\u53F7">\u5168\u90E8\u66F4\u65B0</button>');
|
|
132
|
+
if (mode === "dialog") parts.push('<button type="button" data-act="close" title="\u5173\u95ED\u9762\u677F\uFF08\u6279\u91CF\u63A8\u8FDB\u5728\u5BBF\u4E3B\u4FA7\u7EE7\u7EED\u8DD1\uFF09">\u5173\u95ED</button>');
|
|
130
133
|
parts.push("</div>");
|
|
131
134
|
parts.push("</div>");
|
|
132
135
|
const summary = loaded ? batchSummaryText(counts, rows, total, installing, lastError !== null) : "\u6B63\u5728\u8BFB\u53D6\u6279\u91CF\u66F4\u65B0\u72B6\u6001\u2026";
|
|
@@ -142,7 +145,8 @@ function renderBatchPanelHTML(input) {
|
|
|
142
145
|
...ctx,
|
|
143
146
|
expanded,
|
|
144
147
|
skipped,
|
|
145
|
-
notice: expanded && row.key === detailNoticeKey ? notice : null
|
|
148
|
+
notice: expanded && row.key === detailNoticeKey ? notice : null,
|
|
149
|
+
changelogMarkdown: expanded && typeof changelogs[row.key] === "string" ? changelogs[row.key] : null
|
|
146
150
|
})
|
|
147
151
|
);
|
|
148
152
|
}
|
|
@@ -153,7 +157,10 @@ function renderBatchPanelHTML(input) {
|
|
|
153
157
|
if (total > 0 && !terminal) {
|
|
154
158
|
const more = [];
|
|
155
159
|
if (stalled) more.push('<button type="button" data-act="resume">\u63A5\u7740\u4E0A\u6B21</button>');
|
|
156
|
-
|
|
160
|
+
const confirmCancel = input.confirmCancel === true;
|
|
161
|
+
more.push(
|
|
162
|
+
'<button type="button" data-act="cancel"' + disabled + (confirmCancel ? ' data-confirm="1" title="\u518D\u70B9\u4E00\u6B21\u786E\u8BA4\u53D6\u6D88"' : ' title="\u53D6\u6D88\u8FD9\u4E00\u6279\uFF08\u8981\u70B9\u4E24\u6B21\u786E\u8BA4\uFF0C\u9632\u8BEF\u89E6\uFF09"') + ">" + (confirmCancel ? "\u786E\u8BA4\u53D6\u6D88\u8FD9\u4E00\u6279" : "\u53D6\u6D88\u8FD9\u4E00\u6279") + "</button>"
|
|
163
|
+
);
|
|
157
164
|
parts.push('<div class="dsh-upd-batch-more">' + more.join("") + "</div>");
|
|
158
165
|
}
|
|
159
166
|
if (notice !== null && detailNoticeKey === null) {
|
|
@@ -263,6 +270,7 @@ function detailHTML(row, ctx) {
|
|
|
263
270
|
const html = renderUpdatePanelHTML({
|
|
264
271
|
snapshot: asSnapshotLike(row.snapshot),
|
|
265
272
|
manual: typeof row.manual === "string" ? row.manual : null,
|
|
273
|
+
changelogMarkdown: typeof ctx.changelogMarkdown === "string" ? ctx.changelogMarkdown : null,
|
|
266
274
|
queue: asQueueLike(row.queue),
|
|
267
275
|
// 跳过是面板本地记录(与单插件面板同一套语义):内核按「已跳过」画 tag 与提示行,
|
|
268
276
|
// 恢复按钮由上面的动作行提供,措辞与内核提示里的「恢复」对得上。
|
|
@@ -363,6 +371,8 @@ const UPDATE_BATCH_PANEL_CSS = [
|
|
|
363
371
|
".dsh-upd-batch-ledger{margin:8px 0 0;font-size:13px;opacity:.85}",
|
|
364
372
|
".dsh-upd-batch-more{margin-top:6px}",
|
|
365
373
|
".dsh-upd-batch-more button{font-size:12px}",
|
|
374
|
+
// 确认态:红框红字,与「关闭」等中性按钮一眼区分;disabled 照旧置灰。
|
|
375
|
+
'.dsh-upd-batch-more button[data-confirm="1"]{border-color:var(--dsh-upd-bad-line,#dc2626);color:var(--dsh-upd-bad-line,#dc2626)}',
|
|
366
376
|
".dsh-upd-batch-notice{margin-top:6px;font-size:12.5px;opacity:.85}",
|
|
367
377
|
".dsh-upd-bdetail-actions{margin:0 0 6px}",
|
|
368
378
|
".dsh-upd .dsh-upd-bdetail-actions button{font-size:12.5px}",
|
|
@@ -617,6 +627,11 @@ function mountUpdateBatchPanel(container, options) {
|
|
|
617
627
|
const onRestartRequested = options.onRestartRequested;
|
|
618
628
|
const copyText = options.copyText ?? defaultCopyText;
|
|
619
629
|
const skipStores = /* @__PURE__ */ new Map();
|
|
630
|
+
const autoChangelogEnabled = options.autoChangelog !== false;
|
|
631
|
+
const rowChangelog = /* @__PURE__ */ new Map();
|
|
632
|
+
const rowInflight = /* @__PURE__ */ new Set();
|
|
633
|
+
const rowFailed = /* @__PURE__ */ new Map();
|
|
634
|
+
let rowAutoSeq = 0;
|
|
620
635
|
let rows = [];
|
|
621
636
|
let expandedKey = null;
|
|
622
637
|
let lastError = null;
|
|
@@ -625,7 +640,60 @@ function mountUpdateBatchPanel(container, options) {
|
|
|
625
640
|
let inFlight = false;
|
|
626
641
|
let loaded = false;
|
|
627
642
|
let refreshing = false;
|
|
643
|
+
let confirmCancelArmed = false;
|
|
628
644
|
let mounted = true;
|
|
645
|
+
function changelogView() {
|
|
646
|
+
const out = {};
|
|
647
|
+
for (const row of rows) {
|
|
648
|
+
const cached = rowChangelog.get(row.key);
|
|
649
|
+
if (!cached || typeof cached.markdown !== "string") continue;
|
|
650
|
+
if (latestVersionOf(row) !== cached.version) continue;
|
|
651
|
+
out[row.key] = cached.markdown;
|
|
652
|
+
}
|
|
653
|
+
return out;
|
|
654
|
+
}
|
|
655
|
+
function changelogPhoneOf(row) {
|
|
656
|
+
const phones2 = isObject(row.phoneNames) ? row.phoneNames : null;
|
|
657
|
+
if (!phones2) return null;
|
|
658
|
+
const name = phones2["updateChangelog"];
|
|
659
|
+
return typeof name === "string" && name ? name : null;
|
|
660
|
+
}
|
|
661
|
+
function maybeAutoRowChangelog(key) {
|
|
662
|
+
if (!autoChangelogEnabled || !mounted || !key) return;
|
|
663
|
+
const row = rowOfKey(key);
|
|
664
|
+
if (!row || asBatchPhase(row.phase) !== "ready") return;
|
|
665
|
+
const version = latestVersionOf(row);
|
|
666
|
+
if (!version || !validReleaseVersion(version)) return;
|
|
667
|
+
try {
|
|
668
|
+
if (skipStoreFor(pluginIdOf(row)).has(version)) return;
|
|
669
|
+
} catch {
|
|
670
|
+
}
|
|
671
|
+
const cached = rowChangelog.get(key);
|
|
672
|
+
if (cached && cached.version === version) return;
|
|
673
|
+
if (rowInflight.has(key)) return;
|
|
674
|
+
if (rowFailed.get(key) === version) return;
|
|
675
|
+
const phone2 = changelogPhoneOf(row);
|
|
676
|
+
if (!phone2) return;
|
|
677
|
+
rowInflight.add(key);
|
|
678
|
+
const seq = rowAutoSeq;
|
|
679
|
+
void Promise.resolve().then(() => call(phone2, { version })).then(
|
|
680
|
+
(reply) => {
|
|
681
|
+
rowInflight.delete(key);
|
|
682
|
+
if (!mounted || seq !== rowAutoSeq) return;
|
|
683
|
+
if (!isObject(reply) || reply["ok"] !== true) {
|
|
684
|
+
rowFailed.set(key, version);
|
|
685
|
+
return;
|
|
686
|
+
}
|
|
687
|
+
const md = reply["markdown"];
|
|
688
|
+
rowChangelog.set(key, { version, markdown: typeof md === "string" ? md : null });
|
|
689
|
+
if (typeof md === "string") render();
|
|
690
|
+
},
|
|
691
|
+
() => {
|
|
692
|
+
rowInflight.delete(key);
|
|
693
|
+
if (mounted && seq === rowAutoSeq) rowFailed.set(key, version);
|
|
694
|
+
}
|
|
695
|
+
);
|
|
696
|
+
}
|
|
629
697
|
function render() {
|
|
630
698
|
if (!mounted) return;
|
|
631
699
|
container.innerHTML = renderBatchPanelHTML({
|
|
@@ -639,7 +707,9 @@ function mountUpdateBatchPanel(container, options) {
|
|
|
639
707
|
skippedVersions: skippedVersionsOf(),
|
|
640
708
|
inFlight,
|
|
641
709
|
loaded,
|
|
642
|
-
titles
|
|
710
|
+
titles,
|
|
711
|
+
confirmCancel: confirmCancelArmed,
|
|
712
|
+
changelogs: changelogView()
|
|
643
713
|
});
|
|
644
714
|
}
|
|
645
715
|
function rowOfKey(key) {
|
|
@@ -717,6 +787,7 @@ function mountUpdateBatchPanel(container, options) {
|
|
|
717
787
|
refreshing = false;
|
|
718
788
|
}
|
|
719
789
|
render();
|
|
790
|
+
maybeAutoRowChangelog(expandedKey);
|
|
720
791
|
}
|
|
721
792
|
async function phone(name, args, busyRowKey = null) {
|
|
722
793
|
if (!mounted || inFlight) return;
|
|
@@ -731,6 +802,7 @@ function mountUpdateBatchPanel(container, options) {
|
|
|
731
802
|
return;
|
|
732
803
|
}
|
|
733
804
|
applyReply(reply);
|
|
805
|
+
rowFailed.clear();
|
|
734
806
|
} catch {
|
|
735
807
|
if (!mounted) return;
|
|
736
808
|
lastError = "check-failed";
|
|
@@ -738,9 +810,14 @@ function mountUpdateBatchPanel(container, options) {
|
|
|
738
810
|
inFlight = false;
|
|
739
811
|
if (mounted) render();
|
|
740
812
|
}
|
|
813
|
+
maybeAutoRowChangelog(expandedKey);
|
|
741
814
|
}
|
|
742
815
|
async function act(kind, key) {
|
|
743
816
|
if (!mounted) return;
|
|
817
|
+
if (kind !== "cancel" && confirmCancelArmed) {
|
|
818
|
+
confirmCancelArmed = false;
|
|
819
|
+
render();
|
|
820
|
+
}
|
|
744
821
|
switch (kind) {
|
|
745
822
|
case "check":
|
|
746
823
|
return phone(phones.check, {});
|
|
@@ -757,7 +834,10 @@ function mountUpdateBatchPanel(container, options) {
|
|
|
757
834
|
render();
|
|
758
835
|
return;
|
|
759
836
|
}
|
|
837
|
+
// 程序调用(controller.act)即执行:调它就是明确意图,不上膛。
|
|
838
|
+
// 鼠标误触的防护在 onClick 那一层(第一次点击只上膛)。
|
|
760
839
|
case "cancel": {
|
|
840
|
+
confirmCancelArmed = false;
|
|
761
841
|
await phone(phones.cancel, {});
|
|
762
842
|
if (!mounted) return;
|
|
763
843
|
say("\u5DF2\u53D6\u6D88\u8FD9\u4E00\u6279\uFF1A\u5269\u4E0B\u7684\u4E0D\u518D\u63A8\u8FDB\uFF1B\u8981\u91CD\u6765\u70B9\u300C\u68C0\u67E5\u66F4\u65B0\u300D\u3002");
|
|
@@ -833,6 +913,7 @@ function mountUpdateBatchPanel(container, options) {
|
|
|
833
913
|
if (typeof key !== "string" || !key) return;
|
|
834
914
|
expandedKey = expandedKey === key ? null : key;
|
|
835
915
|
render();
|
|
916
|
+
maybeAutoRowChangelog(expandedKey);
|
|
836
917
|
return;
|
|
837
918
|
}
|
|
838
919
|
// 「重启宿主」:宿主没有重启自己的电话,只做入口——调用方给了 onRestartRequested 就交给它,
|
|
@@ -859,6 +940,14 @@ function mountUpdateBatchPanel(container, options) {
|
|
|
859
940
|
return;
|
|
860
941
|
}
|
|
861
942
|
}
|
|
943
|
+
function onKeyDown(ev) {
|
|
944
|
+
try {
|
|
945
|
+
const e = ev;
|
|
946
|
+
if (!mounted || mode !== "dialog" || !e || e.key !== "Escape") return;
|
|
947
|
+
unmount();
|
|
948
|
+
} catch {
|
|
949
|
+
}
|
|
950
|
+
}
|
|
862
951
|
function setTheme(next) {
|
|
863
952
|
if (next !== "default" && next !== "d5-paper") {
|
|
864
953
|
throw new Error("[dsh-plugin-update] \u4E3B\u9898\u975E\u6CD5\uFF1A\u53EA\u6536 default \u6216 d5-paper\uFF08\u6536\u5230 " + JSON.stringify(next) + "\uFF09");
|
|
@@ -879,6 +968,13 @@ function mountUpdateBatchPanel(container, options) {
|
|
|
879
968
|
const btn = t?.target && typeof t.target.closest === "function" ? t.target.closest("[data-act]") : null;
|
|
880
969
|
const kind = btn?.getAttribute ? btn.getAttribute("data-act") : null;
|
|
881
970
|
if (!kind) return;
|
|
971
|
+
if (kind === "cancel" && !confirmCancelArmed) {
|
|
972
|
+
confirmCancelArmed = true;
|
|
973
|
+
say("\u518D\u70B9\u4E00\u6B21\u300C\u786E\u8BA4\u53D6\u6D88\u8FD9\u4E00\u6279\u300D\u624D\u771F\u7684\u53D6\u6D88\uFF1B\u70B9\u522B\u7684\u6309\u94AE\u53EF\u64A4\u9500\u8FD9\u6B21\u786E\u8BA4\u3002");
|
|
974
|
+
render();
|
|
975
|
+
return;
|
|
976
|
+
}
|
|
977
|
+
if (kind === "cancel") confirmCancelArmed = false;
|
|
882
978
|
const key = btn?.getAttribute ? btn.getAttribute("data-key") : null;
|
|
883
979
|
void act(kind, key === null ? void 0 : key);
|
|
884
980
|
} catch {
|
|
@@ -887,6 +983,8 @@ function mountUpdateBatchPanel(container, options) {
|
|
|
887
983
|
function unmount() {
|
|
888
984
|
if (!mounted) return;
|
|
889
985
|
mounted = false;
|
|
986
|
+
rowAutoSeq++;
|
|
987
|
+
rowInflight.clear();
|
|
890
988
|
try {
|
|
891
989
|
timer.clear(handle);
|
|
892
990
|
} catch {
|
|
@@ -895,12 +993,20 @@ function mountUpdateBatchPanel(container, options) {
|
|
|
895
993
|
container.removeEventListener?.("click", onClick);
|
|
896
994
|
} catch {
|
|
897
995
|
}
|
|
996
|
+
try {
|
|
997
|
+
container.removeEventListener?.("keydown", onKeyDown);
|
|
998
|
+
} catch {
|
|
999
|
+
}
|
|
898
1000
|
}
|
|
899
1001
|
render();
|
|
900
1002
|
try {
|
|
901
1003
|
container.addEventListener?.("click", onClick);
|
|
902
1004
|
} catch {
|
|
903
1005
|
}
|
|
1006
|
+
try {
|
|
1007
|
+
container.addEventListener?.("keydown", onKeyDown);
|
|
1008
|
+
} catch {
|
|
1009
|
+
}
|
|
904
1010
|
const timer = getTimer();
|
|
905
1011
|
const handle = timer.set(() => {
|
|
906
1012
|
void refresh();
|
package/dist/panel.d.ts
CHANGED
|
@@ -43,9 +43,15 @@ export interface UpdatePanelOptions {
|
|
|
43
43
|
/**
|
|
44
44
|
* 更新日志 Markdown(#23 包内 CHANGELOG 展示):
|
|
45
45
|
* 调用方按“已装版离线读、新版按需取 tarball”备好后传入(取不到传 null/空串即中性提示);
|
|
46
|
-
*
|
|
46
|
+
* 缺日志永不挡安装、不写 blockedReason。
|
|
47
|
+
* 显式传入即赢:自动链路(见 autoChangelog)永不覆盖它。
|
|
47
48
|
*/
|
|
48
49
|
changelogMarkdown?: string | null;
|
|
50
|
+
/**
|
|
51
|
+
* 自动取日志(#38):默认开。有新版时面板按 latestVersion 调一次宿主更新日志电话,
|
|
52
|
+
* 回来经内部通道换日志节;显式传过 changelogMarkdown 或传 false 即退回手动模式。
|
|
53
|
+
*/
|
|
54
|
+
autoChangelog?: boolean;
|
|
49
55
|
}
|
|
50
56
|
/** 挂载点:只要有 innerHTML 的容器即可(浏览器元素或测试替身都行)。 */
|
|
51
57
|
export interface UpdatePanelContainer {
|
|
@@ -221,6 +227,11 @@ export interface PanelRenderInput extends PanelViewInput {
|
|
|
221
227
|
profileName?: string | null;
|
|
222
228
|
/** 宿主种类:进诊断文本;缺省显示“未知”。 */
|
|
223
229
|
hostKind?: string | null;
|
|
230
|
+
/**
|
|
231
|
+
* 在途动作(仅挂载态内部用:点下查新版/安装到回包前的那一帧,按钮置忙)。
|
|
232
|
+
* 缺省即静默(输出与旧版一字不差);只在挂载器置忙的那次 render 里传。
|
|
233
|
+
*/
|
|
234
|
+
busyAct?: 'check' | 'install' | null;
|
|
224
235
|
/**
|
|
225
236
|
* 动作面归谁:`default`(缺省)由内核画动作按钮;`none` 只画内容、不画按钮。
|
|
226
237
|
* 给「调用方自己提供动作面」的场景(如批量面板的详情:动作由批量面板经自己的通道提供)。
|
|
@@ -242,6 +253,8 @@ export declare function renderUpdatePanelHTML(input: PanelRenderInput): string;
|
|
|
242
253
|
export declare function mountUpdatePanel(container: UpdatePanelContainer, options: UpdatePanelOptions): UpdatePanelController;
|
|
243
254
|
export { buildPhoneNames as buildPanelPhoneNames } from './config.js';
|
|
244
255
|
export type { PhoneAction as PanelPhoneAction } from './config.js';
|
|
256
|
+
export { buildChangelogPhoneName as buildPanelChangelogPhoneName } from './config.js';
|
|
257
|
+
export type { ChangelogPhoneAction as PanelChangelogPhoneAction } from './config.js';
|
|
245
258
|
/** 面板轮询口径(默认 1 秒、下限 250 毫秒,与宿主侧同一套)。 */
|
|
246
259
|
export declare const PANEL_POLL: {
|
|
247
260
|
readonly defaultMs: 1000;
|
package/dist/panel.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// AUTO-GENERATED by node build.mjs — DO NOT EDIT. Source: src/panel.ts
|
|
2
|
-
import { buildPhoneNames, DEFAULT_PANEL_POLL_MS, MIN_PANEL_POLL_MS } from "./config.js";
|
|
2
|
+
import { buildChangelogPhoneName, buildPhoneNames, DEFAULT_PANEL_POLL_MS, MIN_PANEL_POLL_MS } from "./config.js";
|
|
3
3
|
import { COPY_BUDGET_CHARS, sanitizeForCopy } from "./redaction.js";
|
|
4
4
|
import { validReleaseVersion } from "./service.js";
|
|
5
5
|
import {
|
|
@@ -551,8 +551,25 @@ const UPDATE_PANEL_CSS = [
|
|
|
551
551
|
".dsh-upd-prog-bar{display:block;height:100%;background:var(--dsh-upd-primary,#2563eb);transition:width .3s}",
|
|
552
552
|
".dsh-upd-progtxt{font-size:12.5px;opacity:.75}",
|
|
553
553
|
".dsh-upd-skipline{font-size:13px;margin-top:8px}",
|
|
554
|
+
// 骨架微光:只在首帧 loading 出现;reduced-motion 下静止占位,不断语义。
|
|
555
|
+
".dsh-upd-skv{display:inline-block;min-width:64px;border-radius:3px;color:transparent !important;user-select:none;",
|
|
556
|
+
"background:linear-gradient(90deg,var(--dsh-upd-line,#e5e7eb) 25%,var(--dsh-upd-soft,#f3f4f6) 50%,var(--dsh-upd-line,#e5e7eb) 75%);",
|
|
557
|
+
"background-size:200% 100%;animation:dsh-upd-shimmer 1.2s linear infinite}",
|
|
558
|
+
"@keyframes dsh-upd-shimmer{to{background-position:-200% 0}}",
|
|
554
559
|
".dsh-upd-tag{display:inline-block;border:1px dashed currentColor;border-radius:3px;padding:1px 8px;margin-right:8px;font-family:Consolas,Menlo,monospace;font-size:12px}",
|
|
555
560
|
".dsh-upd-err{font-size:13px;margin:0 0 6px}",
|
|
561
|
+
// —— 全按钮交互反馈(#36:悬停/按下/过渡/在途忙态;浅深双主题通用写法,不碰上面的既有串)——
|
|
562
|
+
".dsh-upd button{transition:background-color .15s ease,border-color .15s ease,color .15s ease,transform .06s ease}",
|
|
563
|
+
".dsh-upd button:hover:not(:disabled){border-color:var(--dsh-upd-focus,#2563eb)}",
|
|
564
|
+
'.dsh-upd button[data-primary="1"]:hover:not(:disabled){filter:brightness(.93)}',
|
|
565
|
+
".dsh-upd button:active:not(:disabled){transform:translateY(1px)}",
|
|
566
|
+
'.dsh-upd button[aria-busy="true"]{cursor:wait;animation:dsh-upd-pulse 1s ease-in-out infinite}',
|
|
567
|
+
"@keyframes dsh-upd-pulse{0%,100%{opacity:1}50%{opacity:.55}}",
|
|
568
|
+
// 在途转圈:纯 CSS ::after,不加 DOM 节点(内核 DOM 冻结);转的是边框缺口,不是 emoji。
|
|
569
|
+
'.dsh-upd button[aria-busy="true"]::after{content:"";display:inline-block;width:11px;height:11px;margin-left:8px;vertical-align:-1px;',
|
|
570
|
+
"border:2px solid currentColor;border-top-color:transparent;border-radius:50%;animation:dsh-upd-spin .8s linear infinite}",
|
|
571
|
+
"@keyframes dsh-upd-spin{to{transform:rotate(360deg)}}",
|
|
572
|
+
'@media (prefers-reduced-motion: reduce){.dsh-upd button{transition:none}.dsh-upd button:active:not(:disabled){transform:none}.dsh-upd button[aria-busy="true"]{animation:none}.dsh-upd-skv{animation:none}}',
|
|
556
573
|
"@media (prefers-color-scheme: dark){.dsh-upd{--dsh-upd-fg:#e5e7eb;--dsh-upd-bg:#111827;--dsh-upd-line:#374151;",
|
|
557
574
|
"--dsh-upd-btn:#1f2937;--dsh-upd-soft:#1f2937;--dsh-upd-primary:#3b82f6;--dsh-upd-focus:#93c5fd;",
|
|
558
575
|
// 横幅深色覆盖:底色用低透明度同色系(不是浅色原值),边线提亮,保证「深底浅字」可读。
|
|
@@ -681,6 +698,11 @@ function chapterOf(index, inner, note = "") {
|
|
|
681
698
|
const title = CHAPTER_TITLES[index - 1];
|
|
682
699
|
return `<section class="dsh-upd-chapter" data-chapter="${no}"><div class="dsh-upd-chap-head"><span class="dsh-upd-chap-no">${no}</span><h3 class="dsh-upd-chap-title">${escapeHtml(title)}</h3><span class="dsh-upd-chap-rule"></span>${note}</div>${inner}</section>`;
|
|
683
700
|
}
|
|
701
|
+
function skeletonStrip(loading) {
|
|
702
|
+
if (!loading) return "";
|
|
703
|
+
const cell = (k) => `<div><span class="dsh-upd-strip-k">${escapeHtml(k)}</span><span class="dsh-upd-strip-v dsh-upd-skv" aria-hidden="true">\u2026</span></div>`;
|
|
704
|
+
return `<div class="dsh-upd-strip" aria-hidden="true">` + cell("\u8FD0\u884C") + cell("\u78C1\u76D8") + cell("\u8FDC\u7AEF") + `</div>`;
|
|
705
|
+
}
|
|
684
706
|
function versionStrip(snapshot) {
|
|
685
707
|
const cell = (k, v) => `<div><span class="dsh-upd-strip-k">${escapeHtml(k)}</span><span class="dsh-upd-strip-v">${escapeHtml(v ?? "\u672A\u77E5")}</span></div>`;
|
|
686
708
|
if (!snapshot) return "";
|
|
@@ -712,31 +734,34 @@ function renderUpdatePanelKernel(input, view) {
|
|
|
712
734
|
parts.push(`<div><strong>${escapeHtml(b.title)}</strong></div>`);
|
|
713
735
|
if (b.action) parts.push(`<div>${escapeHtml(b.action)}</div>`);
|
|
714
736
|
parts.push("</div>");
|
|
715
|
-
parts.push(versionStrip(snapshot));
|
|
737
|
+
parts.push(snapshot ? versionStrip(snapshot) : skeletonStrip(view.banner.kind === "loading"));
|
|
716
738
|
const showActions = input.actions !== "none";
|
|
717
739
|
const actions = [];
|
|
718
740
|
if (showActions) {
|
|
741
|
+
const busyAct = input.busyAct;
|
|
742
|
+
const checkBusy = busyAct === "check";
|
|
743
|
+
const installBusy = busyAct === "install";
|
|
719
744
|
actions.push('<div class="dsh-upd-actions">');
|
|
720
745
|
actions.push(
|
|
721
|
-
`<button type="button" data-action="check">\u67E5\u65B0\u7248</button
|
|
746
|
+
(checkBusy ? `<button type="button" data-action="check" disabled aria-busy="true" title="\u6B63\u5728\u5411\u5B98\u65B9\u6E90\u67E5\u8BE2\uFF0C\u8BF7\u7A0D\u5019">\u6B63\u5728\u67E5\u65B0\u7248\u2026</button>` : `<button type="button" data-action="check" title="\u91CD\u65B0\u5411\u5B98\u65B9\u6E90\u67E5\u4E00\u6B21\u65B0\u7248\uFF08\u53EA\u8BFB\uFF0C\u4E0D\u5B89\u88C5\uFF09">\u67E5\u65B0\u7248</button>`) + (installBusy ? `<button type="button" data-action="install" data-primary="1" disabled aria-busy="true" title="\u6B63\u5728\u5B89\u88C5\uFF0C\u8BF7\u7A0D\u5019">\u6B63\u5728\u5B89\u88C5\u2026</button>` : `<button type="button" data-action="install" data-primary="1" title="\u7528\u7CBE\u786E\u7248\u672C\u5B89\u88C5\uFF1B\u540C\u4E00\u4F7F\u7528\u8303\u56F4\u540C\u65F6\u53EA\u88C5\u4E00\u4E2A"${view.installEnabled ? "" : " disabled"}>${escapeHtml(view.installLabel)}</button>`)
|
|
722
747
|
);
|
|
723
748
|
if (snapshot?.latestVersion && !view.skippedLatest && view.banner.kind === "update") {
|
|
724
|
-
actions.push(`<button type="button" data-action="skip">\u8DF3\u8FC7\u8BE5\u7248\u672C</button>`);
|
|
749
|
+
actions.push(`<button type="button" data-action="skip" title="\u8BE5\u7248\u672C\u4E0D\u518D\u63D0\u9192\uFF1B\u6709\u66F4\u65B0\u7684\u65B0\u7248\u672C\u7167\u5E38\u63D0\u9192">\u8DF3\u8FC7\u8BE5\u7248\u672C</button>`);
|
|
725
750
|
}
|
|
726
751
|
if (view.showReset && snapshot?.latestVersion) {
|
|
727
|
-
actions.push(`<button type="button" data-action="reset-skip">\u6062\u590D\uFF08${escapeHtml(snapshot.latestVersion)}\uFF09</button>`);
|
|
752
|
+
actions.push(`<button type="button" data-action="reset-skip" title="\u64A4\u9500\u8DF3\u8FC7\uFF0C\u8BE5\u7248\u672C\u91CD\u65B0\u63D0\u9192">\u6062\u590D\uFF08${escapeHtml(snapshot.latestVersion)}\uFF09</button>`);
|
|
728
753
|
}
|
|
729
754
|
if (view.showManual && manual) {
|
|
730
|
-
actions.push(`<button type="button" data-action="copy-manual">\u590D\u5236\u624B\u5DE5\u547D\u4EE4</button>`);
|
|
755
|
+
actions.push(`<button type="button" data-action="copy-manual" title="\u590D\u5236\u624B\u5DE5\u547D\u4EE4\uFF0C\u7C98\u5230\u7EC8\u7AEF\u6574\u884C\u6267\u884C">\u590D\u5236\u624B\u5DE5\u547D\u4EE4</button>`);
|
|
731
756
|
}
|
|
732
757
|
if (b.kind === "restart") {
|
|
733
|
-
actions.push(`<button type="button" data-action="restart-hint" data-primary="1">\u91CD\u542F\u5BBF\u4E3B</button>`);
|
|
758
|
+
actions.push(`<button type="button" data-action="restart-hint" data-primary="1" title="\u5BBF\u4E3B\u6CA1\u6709\u81EA\u91CD\u542F\u7535\u8BDD\uFF1A\u8BF7\u624B\u52A8\u91CD\u542F\u5BBF\u4E3B">\u91CD\u542F\u5BBF\u4E3B</button>`);
|
|
734
759
|
}
|
|
735
760
|
if (snapshot) {
|
|
736
|
-
actions.push(`<button type="button" data-action="copy-diag">\u590D\u5236\u8BCA\u65AD</button>`);
|
|
761
|
+
actions.push(`<button type="button" data-action="copy-diag" title="\u590D\u5236\u5DF2\u8131\u654F\u8BCA\u65AD\uFF0C\u76F4\u63A5\u7C98\u7ED9\u63D2\u4EF6\u4F5C\u8005">\u590D\u5236\u8BCA\u65AD</button>`);
|
|
737
762
|
}
|
|
738
763
|
if (mode === "dialog") {
|
|
739
|
-
actions.push(`<button type="button" data-action="close-view">\u5173\u95ED</button>`);
|
|
764
|
+
actions.push(`<button type="button" data-action="close-view" title="\u5173\u95ED\u9762\u677F\uFF08\u5B89\u88C5\u5728\u5BBF\u4E3B\u4FA7\u7EE7\u7EED\u8DD1\uFF0C\u53EF\u91CD\u5F00\u6062\u590D\u663E\u793A\uFF09">\u5173\u95ED</button>`);
|
|
740
765
|
}
|
|
741
766
|
actions.push("</div>");
|
|
742
767
|
}
|
|
@@ -918,6 +943,13 @@ function mountUpdatePanel(container, options) {
|
|
|
918
943
|
}
|
|
919
944
|
const prefix = options.prefix === void 0 ? "wf" : options.prefix;
|
|
920
945
|
const phoneNames = buildPhoneNames(prefix);
|
|
946
|
+
const changelogPhone = buildChangelogPhoneName(prefix);
|
|
947
|
+
const autoChangelogEnabled = typeof options.changelogMarkdown !== "string" && options.autoChangelog !== false;
|
|
948
|
+
let manualChangelogOverride = typeof options.changelogMarkdown === "string";
|
|
949
|
+
const changelogCache = /* @__PURE__ */ new Map();
|
|
950
|
+
const changelogInflight = /* @__PURE__ */ new Set();
|
|
951
|
+
const changelogFailed = /* @__PURE__ */ new Set();
|
|
952
|
+
let autoSeq = 0;
|
|
921
953
|
const pollMs = options.pollMs === void 0 ? DEFAULT_PANEL_POLL_MS : options.pollMs;
|
|
922
954
|
if (typeof pollMs !== "number" || !Number.isFinite(pollMs) || pollMs < MIN_PANEL_POLL_MS) {
|
|
923
955
|
throw new Error(`[dsh-plugin-update] \u9762\u677F\u8F6E\u8BE2\u95F4\u9694\u975E\u6CD5\uFF1A\u4E0D\u5F97\u5C0F\u4E8E 250 \u6BEB\u79D2\uFF08\u6536\u5230 ${JSON.stringify(options.pollMs)}\uFF09`);
|
|
@@ -948,20 +980,36 @@ function mountUpdatePanel(container, options) {
|
|
|
948
980
|
let lastErrorKind = null;
|
|
949
981
|
let lastDiag = null;
|
|
950
982
|
let copyNotice = null;
|
|
983
|
+
let noticeExpiresAt = 0;
|
|
984
|
+
let busyAct = null;
|
|
951
985
|
let mounted = true;
|
|
952
986
|
let envProfileName = null;
|
|
953
987
|
let envHostKind = null;
|
|
988
|
+
function sayCopy(text) {
|
|
989
|
+
copyNotice = text;
|
|
990
|
+
try {
|
|
991
|
+
noticeExpiresAt = Date.now() + 5e3;
|
|
992
|
+
} catch {
|
|
993
|
+
noticeExpiresAt = 0;
|
|
994
|
+
}
|
|
995
|
+
}
|
|
954
996
|
function queueArgs() {
|
|
955
997
|
return { includeQueue: true, includeEnv: true, showOthers, ...requestId ? { requestId } : {} };
|
|
956
998
|
}
|
|
957
999
|
function render() {
|
|
958
1000
|
if (!mounted) return;
|
|
1001
|
+
if (!copyNotice) noticeExpiresAt = 0;
|
|
1002
|
+
else if (noticeExpiresAt && Date.now() > noticeExpiresAt) {
|
|
1003
|
+
copyNotice = null;
|
|
1004
|
+
noticeExpiresAt = 0;
|
|
1005
|
+
}
|
|
959
1006
|
const latest = snapshot?.latestVersion ?? null;
|
|
960
1007
|
const skippedLatest = !!latest && validReleaseVersion(latest) && skipStore.has(latest);
|
|
961
1008
|
container.innerHTML = renderUpdatePanelHTML({
|
|
962
1009
|
snapshot,
|
|
963
1010
|
manual,
|
|
964
1011
|
queue,
|
|
1012
|
+
busyAct,
|
|
965
1013
|
skippedLatest,
|
|
966
1014
|
lastError,
|
|
967
1015
|
errorKind: lastErrorKind,
|
|
@@ -1003,6 +1051,44 @@ function mountUpdatePanel(container, options) {
|
|
|
1003
1051
|
lastDiag = Object.prototype.hasOwnProperty.call(reply, "diag") ? reply["diag"] : null;
|
|
1004
1052
|
}
|
|
1005
1053
|
}
|
|
1054
|
+
function pendingAutoChangelogVersion() {
|
|
1055
|
+
if (!autoChangelogEnabled || manualChangelogOverride || !mounted) return null;
|
|
1056
|
+
const v = snapshot?.latestVersion ?? null;
|
|
1057
|
+
if (typeof v !== "string" || !validReleaseVersion(v)) return null;
|
|
1058
|
+
if (!snapshot || snapshot.canInstall !== true) return null;
|
|
1059
|
+
try {
|
|
1060
|
+
if (skipStore.has(v)) return null;
|
|
1061
|
+
} catch {
|
|
1062
|
+
}
|
|
1063
|
+
if (changelogCache.has(v) || changelogInflight.has(v) || changelogFailed.has(v)) return null;
|
|
1064
|
+
return v;
|
|
1065
|
+
}
|
|
1066
|
+
function maybeAutoChangelog() {
|
|
1067
|
+
const v = pendingAutoChangelogVersion();
|
|
1068
|
+
if (v === null) return;
|
|
1069
|
+
changelogInflight.add(v);
|
|
1070
|
+
const seq = autoSeq;
|
|
1071
|
+
void Promise.resolve().then(() => call(changelogPhone, { version: v })).then(
|
|
1072
|
+
(reply) => {
|
|
1073
|
+
changelogInflight.delete(v);
|
|
1074
|
+
if (!mounted || seq !== autoSeq) return;
|
|
1075
|
+
if (!reply || typeof reply !== "object" || reply["ok"] !== true) {
|
|
1076
|
+
changelogFailed.add(v);
|
|
1077
|
+
return;
|
|
1078
|
+
}
|
|
1079
|
+
const md = reply["markdown"];
|
|
1080
|
+
changelogCache.set(v, typeof md === "string" ? md : null);
|
|
1081
|
+
if (typeof md === "string") {
|
|
1082
|
+
changelogMarkdown = md;
|
|
1083
|
+
render();
|
|
1084
|
+
}
|
|
1085
|
+
},
|
|
1086
|
+
() => {
|
|
1087
|
+
changelogInflight.delete(v);
|
|
1088
|
+
if (mounted && seq === autoSeq) changelogFailed.add(v);
|
|
1089
|
+
}
|
|
1090
|
+
);
|
|
1091
|
+
}
|
|
1006
1092
|
async function refresh() {
|
|
1007
1093
|
if (!mounted) return;
|
|
1008
1094
|
try {
|
|
@@ -1016,26 +1102,40 @@ function mountUpdatePanel(container, options) {
|
|
|
1016
1102
|
lastDiag = null;
|
|
1017
1103
|
}
|
|
1018
1104
|
render();
|
|
1105
|
+
maybeAutoChangelog();
|
|
1019
1106
|
}
|
|
1020
1107
|
async function act(kind, arg) {
|
|
1021
1108
|
if (!mounted) return;
|
|
1022
1109
|
copyNotice = null;
|
|
1023
1110
|
switch (kind) {
|
|
1024
1111
|
case "check": {
|
|
1112
|
+
if (busyAct) return;
|
|
1113
|
+
busyAct = "check";
|
|
1114
|
+
copyNotice = "\u6B63\u5728\u67E5\u65B0\u7248\u2026";
|
|
1115
|
+
render();
|
|
1025
1116
|
try {
|
|
1026
1117
|
const reply = await call(phoneNames.updateCheck, queueArgs());
|
|
1027
1118
|
if (!mounted) return;
|
|
1028
1119
|
applyStatusReply(reply);
|
|
1120
|
+
changelogFailed.clear();
|
|
1029
1121
|
} catch {
|
|
1030
1122
|
if (!mounted) return;
|
|
1031
1123
|
lastError = "check-failed";
|
|
1032
1124
|
lastErrorKind = null;
|
|
1033
1125
|
lastDiag = null;
|
|
1126
|
+
} finally {
|
|
1127
|
+
busyAct = null;
|
|
1128
|
+
if (copyNotice === "\u6B63\u5728\u67E5\u65B0\u7248\u2026") copyNotice = null;
|
|
1034
1129
|
}
|
|
1035
1130
|
render();
|
|
1131
|
+
maybeAutoChangelog();
|
|
1036
1132
|
return;
|
|
1037
1133
|
}
|
|
1038
1134
|
case "install": {
|
|
1135
|
+
if (busyAct) return;
|
|
1136
|
+
busyAct = "install";
|
|
1137
|
+
copyNotice = "\u6B63\u5728\u5B89\u88C5\u2026";
|
|
1138
|
+
render();
|
|
1039
1139
|
try {
|
|
1040
1140
|
if (!receipt) {
|
|
1041
1141
|
const checked = await call(phoneNames.updateCheck, queueArgs());
|
|
@@ -1063,8 +1163,12 @@ function mountUpdatePanel(container, options) {
|
|
|
1063
1163
|
lastError = "check-failed";
|
|
1064
1164
|
lastErrorKind = null;
|
|
1065
1165
|
lastDiag = null;
|
|
1166
|
+
} finally {
|
|
1167
|
+
busyAct = null;
|
|
1168
|
+
if (copyNotice === "\u6B63\u5728\u5B89\u88C5\u2026") copyNotice = null;
|
|
1066
1169
|
}
|
|
1067
1170
|
render();
|
|
1171
|
+
maybeAutoChangelog();
|
|
1068
1172
|
return;
|
|
1069
1173
|
}
|
|
1070
1174
|
case "skip": {
|
|
@@ -1090,9 +1194,9 @@ function mountUpdatePanel(container, options) {
|
|
|
1090
1194
|
if (manual) {
|
|
1091
1195
|
try {
|
|
1092
1196
|
await copyText(manual);
|
|
1093
|
-
|
|
1197
|
+
sayCopy("\u624B\u5DE5\u547D\u4EE4\u5DF2\u590D\u5236\uFF0C\u7C98\u5230\u7EC8\u7AEF\u6574\u884C\u6267\u884C\u5373\u53EF\u3002");
|
|
1094
1198
|
} catch {
|
|
1095
|
-
|
|
1199
|
+
sayCopy("\u590D\u5236\u5931\u8D25\uFF0C\u8BF7\u624B\u52A8\u9009\u4E2D\u4E0A\u9762\u7684\u547D\u4EE4\u3002");
|
|
1096
1200
|
}
|
|
1097
1201
|
}
|
|
1098
1202
|
render();
|
|
@@ -1123,9 +1227,9 @@ function mountUpdatePanel(container, options) {
|
|
|
1123
1227
|
});
|
|
1124
1228
|
try {
|
|
1125
1229
|
await copyText(text);
|
|
1126
|
-
|
|
1230
|
+
sayCopy("\u8BCA\u65AD\u5DF2\u590D\u5236\uFF0C\u76F4\u63A5\u7C98\u7ED9\u63D2\u4EF6\u4F5C\u8005\u5373\u53EF\uFF08\u5DF2\u8131\u654F\uFF09\u3002");
|
|
1127
1231
|
} catch {
|
|
1128
|
-
|
|
1232
|
+
sayCopy("\u590D\u5236\u5931\u8D25\uFF0C\u8BF7\u624B\u52A8\u9009\u4E2D\u4E0A\u9762\u7684\u4FE1\u606F\u3002");
|
|
1129
1233
|
}
|
|
1130
1234
|
render();
|
|
1131
1235
|
return;
|
|
@@ -1141,12 +1245,12 @@ function mountUpdatePanel(container, options) {
|
|
|
1141
1245
|
try {
|
|
1142
1246
|
if (typeof onRestartRequested === "function") {
|
|
1143
1247
|
await onRestartRequested();
|
|
1144
|
-
|
|
1248
|
+
sayCopy("\u5DF2\u6309\u8C03\u7528\u65B9\u7684\u91CD\u542F\u6D41\u7A0B\u5904\u7406\uFF1B\u91CD\u542F\u540E\u65B0\u7248\u751F\u6548\u3002");
|
|
1145
1249
|
} else {
|
|
1146
|
-
|
|
1250
|
+
sayCopy("\u672C\u5BBF\u4E3B\u672A\u63D0\u4F9B\u91CD\u542F\u5165\u53E3\uFF1A\u8BF7\u624B\u52A8\u91CD\u542F\u5BBF\u4E3B\uFF0C\u91CD\u542F\u540E\u65B0\u7248\u751F\u6548\u3002");
|
|
1147
1251
|
}
|
|
1148
1252
|
} catch {
|
|
1149
|
-
|
|
1253
|
+
sayCopy("\u91CD\u542F\u5165\u53E3\u8C03\u7528\u5931\u8D25\uFF1A\u8BF7\u624B\u52A8\u91CD\u542F\u5BBF\u4E3B\uFF0C\u91CD\u542F\u540E\u65B0\u7248\u751F\u6548\u3002");
|
|
1150
1254
|
}
|
|
1151
1255
|
render();
|
|
1152
1256
|
return;
|
|
@@ -1185,13 +1289,24 @@ function mountUpdatePanel(container, options) {
|
|
|
1185
1289
|
} catch {
|
|
1186
1290
|
}
|
|
1187
1291
|
}
|
|
1292
|
+
function onKeyDown(ev) {
|
|
1293
|
+
try {
|
|
1294
|
+
const e = ev;
|
|
1295
|
+
if (!mounted || mode !== "dialog" || !e || e.key !== "Escape") return;
|
|
1296
|
+
unmount();
|
|
1297
|
+
} catch {
|
|
1298
|
+
}
|
|
1299
|
+
}
|
|
1188
1300
|
function setChangelogMarkdown(markdown) {
|
|
1189
1301
|
changelogMarkdown = typeof markdown === "string" ? markdown : null;
|
|
1302
|
+
if (typeof markdown === "string") manualChangelogOverride = true;
|
|
1190
1303
|
render();
|
|
1191
1304
|
}
|
|
1192
1305
|
function unmount() {
|
|
1193
1306
|
if (!mounted) return;
|
|
1194
1307
|
mounted = false;
|
|
1308
|
+
autoSeq++;
|
|
1309
|
+
changelogInflight.clear();
|
|
1195
1310
|
try {
|
|
1196
1311
|
timer.clear(handle);
|
|
1197
1312
|
} catch {
|
|
@@ -1200,12 +1315,20 @@ function mountUpdatePanel(container, options) {
|
|
|
1200
1315
|
container.removeEventListener?.("click", onClick);
|
|
1201
1316
|
} catch {
|
|
1202
1317
|
}
|
|
1318
|
+
try {
|
|
1319
|
+
container.removeEventListener?.("keydown", onKeyDown);
|
|
1320
|
+
} catch {
|
|
1321
|
+
}
|
|
1203
1322
|
}
|
|
1204
1323
|
render();
|
|
1205
1324
|
try {
|
|
1206
1325
|
container.addEventListener?.("click", onClick);
|
|
1207
1326
|
} catch {
|
|
1208
1327
|
}
|
|
1328
|
+
try {
|
|
1329
|
+
container.addEventListener?.("keydown", onKeyDown);
|
|
1330
|
+
} catch {
|
|
1331
|
+
}
|
|
1209
1332
|
const timer = getTimer();
|
|
1210
1333
|
const handle = timer.set(() => {
|
|
1211
1334
|
void refresh();
|
|
@@ -1219,6 +1342,7 @@ function mountUpdatePanel(container, options) {
|
|
|
1219
1342
|
return { refresh, act, setMode, setTheme, setShowOthers, setChangelogMarkdown, unmount };
|
|
1220
1343
|
}
|
|
1221
1344
|
import { buildPhoneNames as buildPhoneNames2 } from "./config.js";
|
|
1345
|
+
import { buildChangelogPhoneName as buildChangelogPhoneName2 } from "./config.js";
|
|
1222
1346
|
const PANEL_POLL = {
|
|
1223
1347
|
defaultMs: DEFAULT_PANEL_POLL_MS,
|
|
1224
1348
|
minMs: MIN_PANEL_POLL_MS
|
|
@@ -1270,6 +1394,7 @@ export {
|
|
|
1270
1394
|
UPDATE_PANEL_D5_CSS,
|
|
1271
1395
|
blockedCopy,
|
|
1272
1396
|
buildDiagnosticText,
|
|
1397
|
+
buildChangelogPhoneName2 as buildPanelChangelogPhoneName,
|
|
1273
1398
|
buildPhoneNames2 as buildPanelPhoneNames,
|
|
1274
1399
|
buildUpdateDiagCopy,
|
|
1275
1400
|
changelogForUpdate2 as changelogForUpdate,
|
package/dist/service.d.ts
CHANGED
|
@@ -69,4 +69,18 @@ export declare function fetchNpmRelease(fetchImpl: FetchImpl, timeoutMs?: number
|
|
|
69
69
|
registryUrl?: string;
|
|
70
70
|
releaseChannel?: ReleaseChannel;
|
|
71
71
|
}): Promise<ReleaseInfo>;
|
|
72
|
+
/**
|
|
73
|
+
* 按版本号取发行信息(#38 更新日志电话用:面板说要哪版就取哪版)。
|
|
74
|
+
*
|
|
75
|
+
* 与 fetchNpmRelease 同一信任根:只接受名字对得上、版本与请求完全一致且发行合法、
|
|
76
|
+
* 包地址与完整性校验全合规的返回,否则按版本信息无效处理。通道门禁同样复用
|
|
77
|
+
* (stable 只要纯三段,prerelease 才收预发布)。取的是版本文档(与 latest 文档同量级),
|
|
78
|
+
* 不是全量包元数据。
|
|
79
|
+
*/
|
|
80
|
+
export declare function fetchNpmVersionRelease(fetchImpl: FetchImpl, timeoutMs: number | undefined, opts: {
|
|
81
|
+
targetPackageName?: string;
|
|
82
|
+
registryUrl?: string;
|
|
83
|
+
releaseChannel?: ReleaseChannel;
|
|
84
|
+
version: string;
|
|
85
|
+
}): Promise<ReleaseInfo>;
|
|
72
86
|
export declare function createUpdateCore(ports: UpdatePorts): UpdateCore;
|