dsh-plugin-update 0.4.0 → 0.5.1
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 +18 -0
- package/README.md +11 -8
- package/dist/changelog-io.d.ts +5 -0
- package/dist/changelog.d.ts +66 -3
- package/dist/changelog.js +412 -35
- package/dist/entry.d.ts +8 -3
- package/dist/entry.js +26 -15
- package/dist/host.d.ts +2 -2
- package/dist/host.js +57 -7
- package/dist/panel-batch.js +46 -11
- package/dist/panel.d.ts +17 -3
- package/dist/panel.js +91 -18
- package/package.json +1 -1
package/dist/host.js
CHANGED
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
} from "./config.js";
|
|
12
12
|
import { manualCommand } from "./commands.js";
|
|
13
13
|
import { fetchReleaseChangelogText } from "./changelog-io.js";
|
|
14
|
+
import { shouldFetchChangelog } from "./changelog.js";
|
|
14
15
|
import { buildDiag } from "./diag.js";
|
|
15
16
|
import { fetchNpmVersionRelease, isVersionAllowedInChannel, updateError, validReleaseVersion, validRequestId } from "./service.js";
|
|
16
17
|
import { createUpdateDiskPorts, createUpdateExecutor, createUpdateQueuePorts } from "./store.js";
|
|
@@ -73,14 +74,24 @@ import {
|
|
|
73
74
|
CHANGELOG_MUST_SHOW,
|
|
74
75
|
CHANGELOG_NEUTRAL_HINT,
|
|
75
76
|
CHANGELOG_NEUTRAL_LINE,
|
|
77
|
+
BREAKING_BADGE_TEXT,
|
|
78
|
+
CHANGELOG_POLL_BACKOFF_MS,
|
|
76
79
|
changelogForUpdate,
|
|
80
|
+
countsOf,
|
|
77
81
|
hasVisibleSections,
|
|
82
|
+
isBreakingChangelogItem,
|
|
78
83
|
isUnreleasedVersion,
|
|
79
84
|
parseChangelog,
|
|
80
85
|
renderChangelogHTML,
|
|
86
|
+
renderChangelogItem,
|
|
81
87
|
renderChangelogNeutral,
|
|
82
88
|
renderChangelogSection,
|
|
83
|
-
selectChangelogEntries
|
|
89
|
+
selectChangelogEntries,
|
|
90
|
+
shouldFetchChangelog as shouldFetchChangelog2,
|
|
91
|
+
splitBreakingPrefix,
|
|
92
|
+
truncatedNoteHTML,
|
|
93
|
+
validateChangelog,
|
|
94
|
+
yankedBannerHTML
|
|
84
95
|
} from "./changelog.js";
|
|
85
96
|
import {
|
|
86
97
|
CHANGELOG_DEFAULT_REGISTRY,
|
|
@@ -578,12 +589,24 @@ function createHostUpdate(deps = {}, configInput) {
|
|
|
578
589
|
const readerOverrides = { ...deps.readerOverrides ?? {}, ctx, ...deps.pluginManager ? { pluginManager: deps.pluginManager } : {} };
|
|
579
590
|
const phoneNames = buildPhoneNames(config.prefix);
|
|
580
591
|
const changelogCache = /* @__PURE__ */ new Map();
|
|
592
|
+
const changelogFailedAt = /* @__PURE__ */ new Map();
|
|
581
593
|
async function readChangelog(args) {
|
|
582
594
|
const raw = args ? args["version"] : void 0;
|
|
583
595
|
if (!validReleaseVersion(raw)) throw updateError("invalid-release");
|
|
584
596
|
const version = raw;
|
|
585
597
|
if (!isVersionAllowedInChannel(version, config.releaseChannel)) throw updateError("invalid-release");
|
|
586
598
|
if (changelogCache.has(version)) return { version, markdown: changelogCache.get(version) ?? null };
|
|
599
|
+
try {
|
|
600
|
+
let nowMs = 0;
|
|
601
|
+
try {
|
|
602
|
+
nowMs = Date.now();
|
|
603
|
+
} catch {
|
|
604
|
+
nowMs = 0;
|
|
605
|
+
}
|
|
606
|
+
const failedAt = changelogFailedAt.has(version) ? changelogFailedAt.get(version) : null;
|
|
607
|
+
void shouldFetchChangelog({ hasCache: false, failedAt, now: nowMs, isManual: true });
|
|
608
|
+
} catch {
|
|
609
|
+
}
|
|
587
610
|
const fetchImpl = readerOverrides.fetchImpl ?? globalThis.fetch;
|
|
588
611
|
const release = await fetchNpmVersionRelease(fetchImpl, config.checkTimeoutMs, {
|
|
589
612
|
targetPackageName: config.targetPackageName,
|
|
@@ -591,12 +614,29 @@ function createHostUpdate(deps = {}, configInput) {
|
|
|
591
614
|
releaseChannel: config.releaseChannel,
|
|
592
615
|
version
|
|
593
616
|
});
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
617
|
+
let markdown;
|
|
618
|
+
try {
|
|
619
|
+
markdown = await fetchReleaseChangelogText(
|
|
620
|
+
fetchImpl,
|
|
621
|
+
{ tarball: release.tarball, integrity: release.integrity, version },
|
|
622
|
+
{ targetPackageName: config.targetPackageName, registryUrl: config.registryUrl, timeoutMs: config.checkTimeoutMs }
|
|
623
|
+
);
|
|
624
|
+
} catch (err) {
|
|
625
|
+
try {
|
|
626
|
+
changelogFailedAt.set(version, Date.now());
|
|
627
|
+
} catch {
|
|
628
|
+
try {
|
|
629
|
+
changelogFailedAt.set(version, 0);
|
|
630
|
+
} catch {
|
|
631
|
+
}
|
|
632
|
+
}
|
|
633
|
+
throw err;
|
|
634
|
+
}
|
|
599
635
|
changelogCache.set(version, markdown);
|
|
636
|
+
try {
|
|
637
|
+
changelogFailedAt.delete(version);
|
|
638
|
+
} catch {
|
|
639
|
+
}
|
|
600
640
|
return { version, markdown };
|
|
601
641
|
}
|
|
602
642
|
async function readStatus(args) {
|
|
@@ -713,6 +753,7 @@ function __resetSharedUpdateReaderForTests() {
|
|
|
713
753
|
sharedDesktopPnpm = null;
|
|
714
754
|
}
|
|
715
755
|
export {
|
|
756
|
+
BREAKING_BADGE_TEXT,
|
|
716
757
|
CHANGELOG_ALL_CATEGORIES,
|
|
717
758
|
CHANGELOG_DEFAULT_REGISTRY,
|
|
718
759
|
CHANGELOG_FETCH_MAX_BYTES,
|
|
@@ -725,6 +766,7 @@ export {
|
|
|
725
766
|
CHANGELOG_MUST_SHOW,
|
|
726
767
|
CHANGELOG_NEUTRAL_HINT,
|
|
727
768
|
CHANGELOG_NEUTRAL_LINE,
|
|
769
|
+
CHANGELOG_POLL_BACKOFF_MS,
|
|
728
770
|
CHANGELOG_TARBALL_MAX_BYTES,
|
|
729
771
|
CHANGELOG_TAR_MAX_BYTES,
|
|
730
772
|
COPY_BUDGET_CHARS,
|
|
@@ -764,6 +806,7 @@ export {
|
|
|
764
806
|
compareReleaseVersions,
|
|
765
807
|
compareVersions,
|
|
766
808
|
containingPackage,
|
|
809
|
+
countsOf,
|
|
767
810
|
createHostUpdate,
|
|
768
811
|
createSkipDiskPorts,
|
|
769
812
|
createUpdateDiskPorts2 as createUpdateDiskPorts,
|
|
@@ -782,6 +825,7 @@ export {
|
|
|
782
825
|
extractChangelogFromTar,
|
|
783
826
|
fetchReleaseChangelogText2 as fetchReleaseChangelogText,
|
|
784
827
|
hasVisibleSections,
|
|
828
|
+
isBreakingChangelogItem,
|
|
785
829
|
isHeadOfQueue2 as isHeadOfQueue,
|
|
786
830
|
isPrereleaseVersion,
|
|
787
831
|
isUnreleasedVersion,
|
|
@@ -800,6 +844,7 @@ export {
|
|
|
800
844
|
registrySpec,
|
|
801
845
|
releaseOwnerInQueue2 as releaseOwnerInQueue,
|
|
802
846
|
renderChangelogHTML,
|
|
847
|
+
renderChangelogItem,
|
|
803
848
|
renderChangelogNeutral,
|
|
804
849
|
renderChangelogSection,
|
|
805
850
|
resolveCliEntry,
|
|
@@ -810,9 +855,14 @@ export {
|
|
|
810
855
|
sanitizeForCopy,
|
|
811
856
|
selectChangelogEntries,
|
|
812
857
|
setOwnerIfFree2 as setOwnerIfFree,
|
|
858
|
+
shouldFetchChangelog2 as shouldFetchChangelog,
|
|
813
859
|
skipKey,
|
|
860
|
+
splitBreakingPrefix,
|
|
814
861
|
truncateToWordBoundary,
|
|
862
|
+
truncatedNoteHTML,
|
|
815
863
|
validReleaseVersion2 as validReleaseVersion,
|
|
816
864
|
validVersion,
|
|
817
|
-
|
|
865
|
+
validateChangelog,
|
|
866
|
+
visibleQueueFor2 as visibleQueueFor,
|
|
867
|
+
yankedBannerHTML
|
|
818
868
|
};
|
package/dist/panel-batch.js
CHANGED
|
@@ -1,6 +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
3
|
import { validReleaseVersion } from "./service.js";
|
|
4
|
+
import { shouldFetchChangelog } from "./changelog.js";
|
|
4
5
|
import {
|
|
5
6
|
isTerminalPhase,
|
|
6
7
|
normalizeBatchSession
|
|
@@ -12,6 +13,7 @@ import {
|
|
|
12
13
|
createBrowserSkipStore,
|
|
13
14
|
failureCopy,
|
|
14
15
|
isKnownFailureCode,
|
|
16
|
+
normalizePanelTheme,
|
|
15
17
|
renderUpdatePanelHTML
|
|
16
18
|
} from "./panel.js";
|
|
17
19
|
const BATCH_PANEL_POLL = {
|
|
@@ -92,7 +94,7 @@ function batchRowStatus(row, skippedVersion) {
|
|
|
92
94
|
}
|
|
93
95
|
function renderBatchPanelHTML(input) {
|
|
94
96
|
const rows = Array.isArray(input.rows) ? input.rows : [];
|
|
95
|
-
const theme = input.theme
|
|
97
|
+
const theme = normalizePanelTheme(input.theme);
|
|
96
98
|
const mode = input.mode === "dialog" ? "dialog" : "embedded";
|
|
97
99
|
const titles = input.titles && typeof input.titles === "object" ? input.titles : {};
|
|
98
100
|
const skippedVersions = input.skippedVersions && typeof input.skippedVersions === "object" ? input.skippedVersions : {};
|
|
@@ -167,7 +169,7 @@ function renderBatchPanelHTML(input) {
|
|
|
167
169
|
parts.push('<div class="dsh-upd-batch-notice" role="status">' + escapeHtml(notice) + "</div>");
|
|
168
170
|
}
|
|
169
171
|
const kernel = parts.join(String.fromCharCode(10));
|
|
170
|
-
const d5 = theme === "d5-paper";
|
|
172
|
+
const d5 = normalizePanelTheme(theme) === "d5-paper";
|
|
171
173
|
const attr = d5 ? ' data-theme="d5-paper"' : "";
|
|
172
174
|
const seal = batchSealOf(counts);
|
|
173
175
|
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>";
|
|
@@ -618,10 +620,10 @@ function mountUpdateBatchPanel(container, options) {
|
|
|
618
620
|
if (mode !== "embedded" && mode !== "dialog") {
|
|
619
621
|
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");
|
|
620
622
|
}
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
throw new Error("[dsh-plugin-update] \u4E3B\u9898\u975E\u6CD5\uFF1A\u53EA\u6536 default \u6216 d5-paper\uFF08\u6536\u5230 " + JSON.stringify(options.theme) + "\uFF09");
|
|
623
|
+
if (options.theme !== void 0 && options.theme !== "default" && options.theme !== "archive" && options.theme !== "d5-paper") {
|
|
624
|
+
throw new Error("[dsh-plugin-update] \u4E3B\u9898\u975E\u6CD5\uFF1A\u53EA\u6536 default \u6216 archive\uFF08d5-paper \u4E3A\u65E7\u522B\u540D\u4ECD\u53EF\u7528\uFF09\uFF08\u6536\u5230 " + JSON.stringify(options.theme) + "\uFF09");
|
|
624
625
|
}
|
|
626
|
+
let theme = normalizePanelTheme(options.theme ?? "default");
|
|
625
627
|
const call = options.call;
|
|
626
628
|
const titles = options.titles && typeof options.titles === "object" ? options.titles : {};
|
|
627
629
|
const onRestartRequested = options.onRestartRequested;
|
|
@@ -630,7 +632,7 @@ function mountUpdateBatchPanel(container, options) {
|
|
|
630
632
|
const autoChangelogEnabled = options.autoChangelog !== false;
|
|
631
633
|
const rowChangelog = /* @__PURE__ */ new Map();
|
|
632
634
|
const rowInflight = /* @__PURE__ */ new Set();
|
|
633
|
-
const
|
|
635
|
+
const rowFailedAt = /* @__PURE__ */ new Map();
|
|
634
636
|
let rowAutoSeq = 0;
|
|
635
637
|
let rows = [];
|
|
636
638
|
let expandedKey = null;
|
|
@@ -671,7 +673,19 @@ function mountUpdateBatchPanel(container, options) {
|
|
|
671
673
|
const cached = rowChangelog.get(key);
|
|
672
674
|
if (cached && cached.version === version) return;
|
|
673
675
|
if (rowInflight.has(key)) return;
|
|
674
|
-
|
|
676
|
+
try {
|
|
677
|
+
const failKey = key + "\0" + version;
|
|
678
|
+
const hasCache = false;
|
|
679
|
+
const failedAt = rowFailedAt.has(failKey) ? rowFailedAt.get(failKey) : null;
|
|
680
|
+
let nowMs = 0;
|
|
681
|
+
try {
|
|
682
|
+
nowMs = Date.now();
|
|
683
|
+
} catch {
|
|
684
|
+
nowMs = 0;
|
|
685
|
+
}
|
|
686
|
+
if (!shouldFetchChangelog({ hasCache, failedAt, now: nowMs, isManual: false })) return;
|
|
687
|
+
} catch {
|
|
688
|
+
}
|
|
675
689
|
const phone2 = changelogPhoneOf(row);
|
|
676
690
|
if (!phone2) return;
|
|
677
691
|
rowInflight.add(key);
|
|
@@ -681,7 +695,14 @@ function mountUpdateBatchPanel(container, options) {
|
|
|
681
695
|
rowInflight.delete(key);
|
|
682
696
|
if (!mounted || seq !== rowAutoSeq) return;
|
|
683
697
|
if (!isObject(reply) || reply["ok"] !== true) {
|
|
684
|
-
|
|
698
|
+
try {
|
|
699
|
+
rowFailedAt.set(key + "\0" + version, Date.now());
|
|
700
|
+
} catch {
|
|
701
|
+
try {
|
|
702
|
+
rowFailedAt.set(key + "\0" + version, 0);
|
|
703
|
+
} catch {
|
|
704
|
+
}
|
|
705
|
+
}
|
|
685
706
|
return;
|
|
686
707
|
}
|
|
687
708
|
const md = reply["markdown"];
|
|
@@ -690,13 +711,23 @@ function mountUpdateBatchPanel(container, options) {
|
|
|
690
711
|
},
|
|
691
712
|
() => {
|
|
692
713
|
rowInflight.delete(key);
|
|
693
|
-
if (mounted && seq === rowAutoSeq)
|
|
714
|
+
if (mounted && seq === rowAutoSeq) {
|
|
715
|
+
try {
|
|
716
|
+
rowFailedAt.set(key + "\0" + version, Date.now());
|
|
717
|
+
} catch {
|
|
718
|
+
try {
|
|
719
|
+
rowFailedAt.set(key + "\0" + version, 0);
|
|
720
|
+
} catch {
|
|
721
|
+
}
|
|
722
|
+
}
|
|
723
|
+
}
|
|
694
724
|
}
|
|
695
725
|
);
|
|
696
726
|
}
|
|
727
|
+
let lastHTML = "";
|
|
697
728
|
function render() {
|
|
698
729
|
if (!mounted) return;
|
|
699
|
-
|
|
730
|
+
const nextHTML = renderBatchPanelHTML({
|
|
700
731
|
rows,
|
|
701
732
|
theme,
|
|
702
733
|
mode,
|
|
@@ -711,6 +742,10 @@ function mountUpdateBatchPanel(container, options) {
|
|
|
711
742
|
confirmCancel: confirmCancelArmed,
|
|
712
743
|
changelogs: changelogView()
|
|
713
744
|
});
|
|
745
|
+
if (nextHTML !== lastHTML) {
|
|
746
|
+
lastHTML = nextHTML;
|
|
747
|
+
container.innerHTML = nextHTML;
|
|
748
|
+
}
|
|
714
749
|
}
|
|
715
750
|
function rowOfKey(key) {
|
|
716
751
|
return rows.find((row) => row.key === key) ?? null;
|
|
@@ -802,7 +837,7 @@ function mountUpdateBatchPanel(container, options) {
|
|
|
802
837
|
return;
|
|
803
838
|
}
|
|
804
839
|
applyReply(reply);
|
|
805
|
-
|
|
840
|
+
rowFailedAt.clear();
|
|
806
841
|
} catch {
|
|
807
842
|
if (!mounted) return;
|
|
808
843
|
lastError = "check-failed";
|
package/dist/panel.d.ts
CHANGED
|
@@ -2,8 +2,17 @@ import { type VisibleQueue } from './queue.js';
|
|
|
2
2
|
import type { BlockedReason, UpdateSnapshot } from './ports.js';
|
|
3
3
|
/** 摆放形态:默认内嵌,切弹窗走同一参数。 */
|
|
4
4
|
export type UpdatePanelMode = 'embedded' | 'dialog';
|
|
5
|
-
/** 面板主题:默认最小可用样式;`d5-paper`
|
|
6
|
-
|
|
5
|
+
/** 面板主题:默认最小可用样式;`archive` 为档案卷纸面浅色(只换肤,不换 DOM 顺序;`d5-paper` 为旧别名)。 */
|
|
6
|
+
/**
|
|
7
|
+
* 面板主题:`default` 最小可用深色;`archive` 档案卷纸面浅色(原型敲定的案卷风格,只换肤)。
|
|
8
|
+
* `d5-paper` 是 archive 的旧别名(历史取值),仍可用,渲染逐字相同。
|
|
9
|
+
*/
|
|
10
|
+
export type UpdatePanelTheme = 'default' | 'archive' | 'd5-paper';
|
|
11
|
+
/**
|
|
12
|
+
* 主题归一:archive 与旧别名 d5-paper 走同一套渲染(DOM 属性仍为 d5-paper,既有覆盖样式不断);
|
|
13
|
+
* 其余一律回 default(纯渲染函数永不抛;挂载/setTheme 的非法值另行抛错)。
|
|
14
|
+
*/
|
|
15
|
+
export declare function normalizePanelTheme(value: unknown): 'default' | 'd5-paper';
|
|
7
16
|
/** 与宿主通话的传输函数:面板只认这个签名,不认任何宿主对象的具体形状。 */
|
|
8
17
|
export type UpdatePanelCall = (phoneName: string, args: Record<string, unknown>) => Promise<Record<string, unknown>>;
|
|
9
18
|
/** 复制文本的出口:不传即尝试浏览器剪贴板,都没有则只留“已生成、请手动复制”提示。 */
|
|
@@ -17,7 +26,7 @@ export interface UpdatePanelOptions {
|
|
|
17
26
|
prefix?: string;
|
|
18
27
|
/** 摆放形态:默认内嵌。 */
|
|
19
28
|
mode?: UpdatePanelMode;
|
|
20
|
-
/** 面板主题:默认 `default`(最小可用样式,一字不动);传 `d5-paper`
|
|
29
|
+
/** 面板主题:默认 `default`(最小可用样式,一字不动);传 `archive` 切档案卷(`d5-paper` 为旧别名)。 */
|
|
21
30
|
theme?: UpdatePanelTheme;
|
|
22
31
|
/** 是否看他人排队明细:默认只看自己的(他人仅露正忙占位,位置照给)。 */
|
|
23
32
|
showOthers?: boolean;
|
|
@@ -52,6 +61,11 @@ export interface UpdatePanelOptions {
|
|
|
52
61
|
* 回来经内部通道换日志节;显式传过 changelogMarkdown 或传 false 即退回手动模式。
|
|
53
62
|
*/
|
|
54
63
|
autoChangelog?: boolean;
|
|
64
|
+
/**
|
|
65
|
+
* 弹窗关闭的落地:只在 dialog 下点「关闭」/按 Esc 时调用;调用方在此撤掉弹窗 DOM。
|
|
66
|
+
* 不传则回退为只停轮询(unmount),DOM 留给调用方处理。入口件打开的 dialog 已内置(收 dialog + 还原按钮)。
|
|
67
|
+
*/
|
|
68
|
+
onCloseRequested?: () => void | Promise<void>;
|
|
55
69
|
}
|
|
56
70
|
/** 挂载点:只要有 innerHTML 的容器即可(浏览器元素或测试替身都行)。 */
|
|
57
71
|
export interface UpdatePanelContainer {
|
package/dist/panel.js
CHANGED
|
@@ -5,8 +5,13 @@ import { validReleaseVersion } from "./service.js";
|
|
|
5
5
|
import {
|
|
6
6
|
changelogForUpdate,
|
|
7
7
|
parseChangelog,
|
|
8
|
-
renderChangelogHTML
|
|
8
|
+
renderChangelogHTML,
|
|
9
|
+
shouldFetchChangelog,
|
|
10
|
+
yankedBannerHTML
|
|
9
11
|
} from "./changelog.js";
|
|
12
|
+
function normalizePanelTheme(value) {
|
|
13
|
+
return value === "d5-paper" || value === "archive" ? "d5-paper" : "default";
|
|
14
|
+
}
|
|
10
15
|
const BLOCKED_COPY = {
|
|
11
16
|
"unknown-profile": {
|
|
12
17
|
title: "\u4F7F\u7528\u8303\u56F4\u6216\u63D2\u4EF6\u4F4D\u7F6E\u8BA4\u4E0D\u51FA",
|
|
@@ -513,6 +518,12 @@ const UPDATE_PANEL_CSS = [
|
|
|
513
518
|
".dsh-upd-changelog li{margin:2px 0}",
|
|
514
519
|
".dsh-upd-changelog-fold{margin:4px 0}",
|
|
515
520
|
".dsh-upd-changelog-fold>summary{cursor:pointer}",
|
|
521
|
+
".dsh-upd-changelog-count{font-size:12px;opacity:.7;margin:2px 0 4px}",
|
|
522
|
+
".dsh-upd-changelog-yanked{border-left:4px solid var(--dsh-upd-warn-line,#d97706);background:var(--dsh-upd-warn-bg,#fffbeb);padding:6px 10px;margin:6px 0;font-size:13px}",
|
|
523
|
+
".dsh-upd-breaking-badge{display:inline-block;font-size:11px;font-weight:700;border:1px solid currentColor;border-radius:3px;padding:0 5px;margin-right:6px;vertical-align:baseline}",
|
|
524
|
+
".dsh-upd-changelog-security-more{margin:4px 0 6px}",
|
|
525
|
+
".dsh-upd-changelog-security-more>summary{cursor:pointer;font-size:12px;opacity:.8}",
|
|
526
|
+
".dsh-upd-changelog-more-note{font-size:12px;opacity:.7;margin:2px 0 4px}",
|
|
516
527
|
".dsh-upd-changelog-neutral{color:inherit;opacity:.8}",
|
|
517
528
|
".dsh-upd-overlay{position:fixed;inset:0;background:rgba(0,0,0,.35);display:flex;align-items:center;justify-content:center;z-index:9999}",
|
|
518
529
|
".dsh-upd-overlay .dsh-upd{background:var(--dsh-upd-bg,#ffffff);max-height:85vh;overflow:auto}",
|
|
@@ -590,7 +601,8 @@ const UPDATE_PANEL_D5_CSS = [
|
|
|
590
601
|
"--d5-shadow:0 1px 2px rgba(60,40,20,.08),0 12px 32px rgba(60,40,20,.10);",
|
|
591
602
|
"font-family:var(--d5-sans);color:var(--d5-ink);background:var(--d5-card);",
|
|
592
603
|
"border:1px solid var(--d5-line-strong);border-radius:4px;box-shadow:var(--d5-shadow)}",
|
|
593
|
-
|
|
604
|
+
// 按钮脸自己不透明(宿主底色未知时也读得出;卡片上渲染与 transparent 逐字同色)。
|
|
605
|
+
'.dsh-upd[data-theme="d5-paper"] button{border-color:var(--d5-line-strong);background:var(--d5-card);color:var(--d5-ink);border-radius:3px;font-family:var(--d5-sans)}',
|
|
594
606
|
'.dsh-upd[data-theme="d5-paper"] button:hover:not(:disabled){border-color:var(--d5-accent);color:var(--d5-accent)}',
|
|
595
607
|
'.dsh-upd[data-theme="d5-paper"] button[data-primary="1"]{background:var(--d5-accent);border-color:var(--d5-accent);color:#fff}',
|
|
596
608
|
'.dsh-upd[data-theme="d5-paper"] button[data-primary="1"]:hover:not(:disabled){background:var(--d5-accent-deep);color:#fff}',
|
|
@@ -601,6 +613,10 @@ const UPDATE_PANEL_D5_CSS = [
|
|
|
601
613
|
'.dsh-upd[data-theme="d5-paper"] .dsh-upd-banner[data-kind="restart"]{border-color:var(--d5-warn);background:var(--d5-warn-bg);font-family:var(--d5-serif);border-width:2px}',
|
|
602
614
|
'.dsh-upd[data-theme="d5-paper"] .dsh-upd-banner[data-kind="failed"],.dsh-upd[data-theme="d5-paper"] .dsh-upd-banner[data-kind="blocked"]{border-color:var(--d5-bad);background:var(--d5-bad-bg)}',
|
|
603
615
|
'.dsh-upd[data-theme="d5-paper"] .dsh-upd-banner[data-kind="done"]{border-color:var(--d5-ok);background:var(--d5-ok-bg)}',
|
|
616
|
+
'.dsh-upd[data-theme="d5-paper"] .dsh-upd-changelog-yanked{border-color:var(--d5-warn);background:var(--d5-warn-bg);color:var(--d5-ink)}',
|
|
617
|
+
'.dsh-upd[data-theme="d5-paper"] .dsh-upd-breaking-badge{color:var(--d5-accent);border-color:var(--d5-accent)}',
|
|
618
|
+
'.dsh-upd[data-theme="d5-paper"] .dsh-upd-changelog-count{color:var(--d5-muted)}',
|
|
619
|
+
'.dsh-upd[data-theme="d5-paper"] .dsh-upd-changelog-more-note{color:var(--d5-muted)}',
|
|
604
620
|
// —— 大印章(原型 :206 `.seal`:右上 88px、旋转 -7°、双细框;内容与色调来自根属性,不加节点)——
|
|
605
621
|
'.dsh-upd[data-theme="d5-paper"]{position:relative;padding:22px 26px 20px}',
|
|
606
622
|
'.dsh-upd[data-theme="d5-paper"]::before{content:attr(data-seal);position:absolute;top:20px;right:24px;width:88px;height:88px;',
|
|
@@ -788,7 +804,22 @@ function renderUpdatePanelKernel(input, view) {
|
|
|
788
804
|
const fromText = String(snapshot.runningVersion ?? "");
|
|
789
805
|
const toText = String(snapshot.latestVersion ?? "");
|
|
790
806
|
const rangeTitle = fromText && toText ? `\u66F4\u65B0\u8BF4\u660E\uFF08${fromText} \u2192 ${toText}\uFF09\uFF1A` : "\u66F4\u65B0\u8BF4\u660E\uFF1A";
|
|
791
|
-
|
|
807
|
+
let yankedBanner = "";
|
|
808
|
+
try {
|
|
809
|
+
const toEntry = Array.isArray(ranged) ? ranged.find(function(e) {
|
|
810
|
+
try {
|
|
811
|
+
return e && e.version === toText;
|
|
812
|
+
} catch {
|
|
813
|
+
return false;
|
|
814
|
+
}
|
|
815
|
+
}) : null;
|
|
816
|
+
if (toEntry && toEntry.yanked === true && toText) {
|
|
817
|
+
yankedBanner = yankedBannerHTML(toText);
|
|
818
|
+
}
|
|
819
|
+
} catch {
|
|
820
|
+
yankedBanner = "";
|
|
821
|
+
}
|
|
822
|
+
inner = `<div class="dsh-upd-changelog-wrap"><div>${escapeHtml(rangeTitle)}</div>${yankedBanner}
|
|
792
823
|
${changelogHTML}
|
|
793
824
|
</div>`;
|
|
794
825
|
} catch {
|
|
@@ -863,7 +894,7 @@ ${changelogHTML}
|
|
|
863
894
|
function renderUpdatePanelHTML(input) {
|
|
864
895
|
const view = panelViewModel(input);
|
|
865
896
|
const kernel = renderUpdatePanelKernel(input, view);
|
|
866
|
-
const d5 = input.theme === "d5-paper";
|
|
897
|
+
const d5 = normalizePanelTheme(input.theme) === "d5-paper";
|
|
867
898
|
const attr = d5 ? ' data-theme="d5-paper"' : "";
|
|
868
899
|
const sealAttr = ` data-seal="${escapeHtml(view.seal.text)}" data-seal-tone="${view.seal.tone}"`;
|
|
869
900
|
const body = input.mode === "dialog" ? `<div class="dsh-upd-overlay" data-mode="dialog"><div class="dsh-upd" data-mode="dialog" data-plugin="${escapeHtml(input.pluginId)}"${sealAttr}${attr}>
|
|
@@ -948,7 +979,7 @@ function mountUpdatePanel(container, options) {
|
|
|
948
979
|
let manualChangelogOverride = typeof options.changelogMarkdown === "string";
|
|
949
980
|
const changelogCache = /* @__PURE__ */ new Map();
|
|
950
981
|
const changelogInflight = /* @__PURE__ */ new Set();
|
|
951
|
-
const
|
|
982
|
+
const changelogFailedAt = /* @__PURE__ */ new Map();
|
|
952
983
|
let autoSeq = 0;
|
|
953
984
|
const pollMs = options.pollMs === void 0 ? DEFAULT_PANEL_POLL_MS : options.pollMs;
|
|
954
985
|
if (typeof pollMs !== "number" || !Number.isFinite(pollMs) || pollMs < MIN_PANEL_POLL_MS) {
|
|
@@ -958,13 +989,15 @@ function mountUpdatePanel(container, options) {
|
|
|
958
989
|
if (mode !== "embedded" && mode !== "dialog") {
|
|
959
990
|
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`);
|
|
960
991
|
}
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
throw new Error(`[dsh-plugin-update] \u4E3B\u9898\u975E\u6CD5\uFF1A\u53EA\u6536 default \u6216 d5-paper\uFF08\u6536\u5230 ${JSON.stringify(options.theme)}\uFF09`);
|
|
992
|
+
if (options.theme !== void 0 && options.theme !== "default" && options.theme !== "archive" && options.theme !== "d5-paper") {
|
|
993
|
+
throw new Error(`[dsh-plugin-update] \u4E3B\u9898\u975E\u6CD5\uFF1A\u53EA\u6536 default \u6216 archive\uFF08d5-paper \u4E3A\u65E7\u522B\u540D\u4ECD\u53EF\u7528\uFF09\uFF08\u6536\u5230 ${JSON.stringify(options.theme)}\uFF09`);
|
|
964
994
|
}
|
|
995
|
+
let theme = normalizePanelTheme(options.theme ?? "default");
|
|
965
996
|
let showOthers = options.showOthers === true;
|
|
966
997
|
const call = options.call;
|
|
967
998
|
const onRestartRequested = options.onRestartRequested;
|
|
999
|
+
const onCloseRequested = typeof options.onCloseRequested === "function" ? options.onCloseRequested : null;
|
|
1000
|
+
let lastHTML = "";
|
|
968
1001
|
const copyText = options.copyText ?? defaultCopyText;
|
|
969
1002
|
const skipStore = options.skipStore ?? createBrowserSkipStore(pluginId);
|
|
970
1003
|
const hostKind = typeof options.hostKind === "string" && options.hostKind ? options.hostKind : null;
|
|
@@ -1005,7 +1038,7 @@ function mountUpdatePanel(container, options) {
|
|
|
1005
1038
|
}
|
|
1006
1039
|
const latest = snapshot?.latestVersion ?? null;
|
|
1007
1040
|
const skippedLatest = !!latest && validReleaseVersion(latest) && skipStore.has(latest);
|
|
1008
|
-
|
|
1041
|
+
const nextHTML = renderUpdatePanelHTML({
|
|
1009
1042
|
snapshot,
|
|
1010
1043
|
manual,
|
|
1011
1044
|
queue,
|
|
@@ -1023,6 +1056,10 @@ function mountUpdatePanel(container, options) {
|
|
|
1023
1056
|
profileName: profileNameOption ?? envProfileName,
|
|
1024
1057
|
hostKind: hostKind ?? envHostKind
|
|
1025
1058
|
});
|
|
1059
|
+
if (nextHTML !== lastHTML) {
|
|
1060
|
+
lastHTML = nextHTML;
|
|
1061
|
+
container.innerHTML = nextHTML;
|
|
1062
|
+
}
|
|
1026
1063
|
}
|
|
1027
1064
|
function applyStatusReply(reply) {
|
|
1028
1065
|
if (!isObject(reply)) return;
|
|
@@ -1060,7 +1097,16 @@ function mountUpdatePanel(container, options) {
|
|
|
1060
1097
|
if (skipStore.has(v)) return null;
|
|
1061
1098
|
} catch {
|
|
1062
1099
|
}
|
|
1063
|
-
if (
|
|
1100
|
+
if (changelogInflight.has(v)) return null;
|
|
1101
|
+
const hasCache = changelogCache.has(v);
|
|
1102
|
+
const failedAt = changelogFailedAt.has(v) ? changelogFailedAt.get(v) : null;
|
|
1103
|
+
let nowMs = 0;
|
|
1104
|
+
try {
|
|
1105
|
+
nowMs = Date.now();
|
|
1106
|
+
} catch {
|
|
1107
|
+
nowMs = 0;
|
|
1108
|
+
}
|
|
1109
|
+
if (!shouldFetchChangelog({ hasCache, failedAt, now: nowMs, isManual: false })) return null;
|
|
1064
1110
|
return v;
|
|
1065
1111
|
}
|
|
1066
1112
|
function maybeAutoChangelog() {
|
|
@@ -1073,7 +1119,14 @@ function mountUpdatePanel(container, options) {
|
|
|
1073
1119
|
changelogInflight.delete(v);
|
|
1074
1120
|
if (!mounted || seq !== autoSeq) return;
|
|
1075
1121
|
if (!reply || typeof reply !== "object" || reply["ok"] !== true) {
|
|
1076
|
-
|
|
1122
|
+
try {
|
|
1123
|
+
changelogFailedAt.set(v, Date.now());
|
|
1124
|
+
} catch {
|
|
1125
|
+
try {
|
|
1126
|
+
changelogFailedAt.set(v, 0);
|
|
1127
|
+
} catch {
|
|
1128
|
+
}
|
|
1129
|
+
}
|
|
1077
1130
|
return;
|
|
1078
1131
|
}
|
|
1079
1132
|
const md = reply["markdown"];
|
|
@@ -1085,7 +1138,16 @@ function mountUpdatePanel(container, options) {
|
|
|
1085
1138
|
},
|
|
1086
1139
|
() => {
|
|
1087
1140
|
changelogInflight.delete(v);
|
|
1088
|
-
if (mounted && seq === autoSeq)
|
|
1141
|
+
if (mounted && seq === autoSeq) {
|
|
1142
|
+
try {
|
|
1143
|
+
changelogFailedAt.set(v, Date.now());
|
|
1144
|
+
} catch {
|
|
1145
|
+
try {
|
|
1146
|
+
changelogFailedAt.set(v, 0);
|
|
1147
|
+
} catch {
|
|
1148
|
+
}
|
|
1149
|
+
}
|
|
1150
|
+
}
|
|
1089
1151
|
}
|
|
1090
1152
|
);
|
|
1091
1153
|
}
|
|
@@ -1117,7 +1179,7 @@ function mountUpdatePanel(container, options) {
|
|
|
1117
1179
|
const reply = await call(phoneNames.updateCheck, queueArgs());
|
|
1118
1180
|
if (!mounted) return;
|
|
1119
1181
|
applyStatusReply(reply);
|
|
1120
|
-
|
|
1182
|
+
changelogFailedAt.clear();
|
|
1121
1183
|
} catch {
|
|
1122
1184
|
if (!mounted) return;
|
|
1123
1185
|
lastError = "check-failed";
|
|
@@ -1256,7 +1318,7 @@ function mountUpdatePanel(container, options) {
|
|
|
1256
1318
|
return;
|
|
1257
1319
|
}
|
|
1258
1320
|
case "close-view": {
|
|
1259
|
-
|
|
1321
|
+
await requestDialogClose();
|
|
1260
1322
|
return;
|
|
1261
1323
|
}
|
|
1262
1324
|
}
|
|
@@ -1269,10 +1331,10 @@ function mountUpdatePanel(container, options) {
|
|
|
1269
1331
|
render();
|
|
1270
1332
|
}
|
|
1271
1333
|
async function setTheme(next) {
|
|
1272
|
-
if (next !== "default" && next !== "d5-paper") {
|
|
1273
|
-
throw new Error(`[dsh-plugin-update] \u4E3B\u9898\u975E\u6CD5\uFF1A\u53EA\u6536 default \u6216
|
|
1334
|
+
if (next !== "default" && next !== "archive" && next !== "d5-paper") {
|
|
1335
|
+
throw new Error(`[dsh-plugin-update] \u4E3B\u9898\u975E\u6CD5\uFF1A\u53EA\u6536 default \u6216 archive\uFF08d5-paper \u4E3A\u65E7\u522B\u540D\u4ECD\u53EF\u7528\uFF09\uFF08\u6536\u5230 ${JSON.stringify(next)}\uFF09`);
|
|
1274
1336
|
}
|
|
1275
|
-
theme = next;
|
|
1337
|
+
theme = normalizePanelTheme(next);
|
|
1276
1338
|
render();
|
|
1277
1339
|
}
|
|
1278
1340
|
async function setShowOthers(show) {
|
|
@@ -1289,11 +1351,21 @@ function mountUpdatePanel(container, options) {
|
|
|
1289
1351
|
} catch {
|
|
1290
1352
|
}
|
|
1291
1353
|
}
|
|
1354
|
+
async function requestDialogClose() {
|
|
1355
|
+
if (!mounted || mode !== "dialog") return;
|
|
1356
|
+
if (onCloseRequested) {
|
|
1357
|
+
try {
|
|
1358
|
+
await onCloseRequested();
|
|
1359
|
+
} catch {
|
|
1360
|
+
}
|
|
1361
|
+
}
|
|
1362
|
+
unmount();
|
|
1363
|
+
}
|
|
1292
1364
|
function onKeyDown(ev) {
|
|
1293
1365
|
try {
|
|
1294
1366
|
const e = ev;
|
|
1295
1367
|
if (!mounted || mode !== "dialog" || !e || e.key !== "Escape") return;
|
|
1296
|
-
|
|
1368
|
+
void requestDialogClose();
|
|
1297
1369
|
} catch {
|
|
1298
1370
|
}
|
|
1299
1371
|
}
|
|
@@ -1409,6 +1481,7 @@ export {
|
|
|
1409
1481
|
isQueueBusy,
|
|
1410
1482
|
isUnreleasedVersion,
|
|
1411
1483
|
mountUpdatePanel,
|
|
1484
|
+
normalizePanelTheme,
|
|
1412
1485
|
normalizeQueueState,
|
|
1413
1486
|
panelViewModel,
|
|
1414
1487
|
parseChangelog2 as parseChangelog,
|