dsh-plugin-update 0.5.5 → 0.5.7
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 +13 -0
- package/dist/http.d.ts +6 -1
- package/dist/http.js +2 -8
- package/dist/lang.d.ts +29 -0
- package/dist/panel-batch.js +2 -0
- package/dist/panel.d.ts +8 -1
- package/dist/panel.js +93 -18
- package/package.json +4 -2
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,19 @@
|
|
|
2
2
|
|
|
3
3
|
格式为 Keep-a-Changelog 子集:`Added/Fixed/Changed` 必写,`Deprecated/Removed/Security` 有则透传,`Unreleased` 面板忽略,禁止 git-log 直倒。面板缺日志时中性提示,不挡安装。
|
|
4
4
|
|
|
5
|
+
## [0.5.7] - 2026-10-06
|
|
6
|
+
|
|
7
|
+
### Fixed
|
|
8
|
+
- 拆入口通道安装禁令(#58 真因):入口件 HTTP 直挂不再源码级禁 updateInstall(入口件核心本就没有安装代码路径,禁令只连坐入口件打开的面板;真正门禁在宿主侧核心);入口打开面板后安装电话端到端验证通过。
|
|
9
|
+
|
|
10
|
+
## [0.5.6] - 2026-10-06
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
- 弹窗分栏滚动、更新日志折叠与动效体系;双语防倒退门禁四道检查(文案源/快照/契约/零 draft)与自测(#56)。
|
|
14
|
+
|
|
15
|
+
### Fixed
|
|
16
|
+
- 用户路径抛错锁存非瞬态化(#58):查/装动作的传输抛错改为非瞬态锁存(安装抛错码为 install-failed,不再冒充查失败),轮询不再洗掉;抛错原文脱敏后进复制摘要;安装内补查失败精确归因到查阶段;轮询抛错仍瞬态自愈。
|
|
17
|
+
|
|
5
18
|
## [0.5.5] - 2026-10-06
|
|
6
19
|
|
|
7
20
|
### Added
|
package/dist/http.d.ts
CHANGED
|
@@ -102,7 +102,12 @@ export interface UpdateEntryHttpOptions extends Omit<UpdateEntryOptions, "call"
|
|
|
102
102
|
timeout?: number | HttpTimeouts;
|
|
103
103
|
timeoutMs?: number | HttpTimeouts;
|
|
104
104
|
}
|
|
105
|
-
/** 入口件 HTTP
|
|
105
|
+
/** 入口件 HTTP 直挂:调用通道与面板直挂同一条,内核复用 mountUpdateEntry。
|
|
106
|
+
*
|
|
107
|
+
* 通道层不禁安装:入口件核心没有调安装的代码路径(只查 + 打开面板,见 README 铁律),
|
|
108
|
+
* 禁令只会连坐入口件打开的面板(#58:安装键亮着但永远抛错);真正的门禁在宿主侧核心
|
|
109
|
+
*(凭证/排队/安装键/装后校验),面板安装与面板直挂走同一套,不过不少。
|
|
110
|
+
*/
|
|
106
111
|
export declare function mountUpdateEntryHttp(container: UpdatePanelContainer, options: UpdateEntryHttpOptions): UpdateEntryController;
|
|
107
112
|
export interface UpdateBatchPanelHttpOptions extends Omit<BatchPanelOptions, "call" | "prefix"> {
|
|
108
113
|
/** 批量电话前缀(与宿主侧一致;五电话名从它算出,不写字面量)。 */
|
package/dist/http.js
CHANGED
|
@@ -261,15 +261,9 @@ function mountUpdateEntryHttp(container, options) {
|
|
|
261
261
|
throw new Error("[dsh-plugin-update] \u6302 HTTP \u5165\u53E3\u4EF6\u7F3A\u5C11\u914D\u7F6E\uFF1A\u63D2\u4EF6\u6807\u8BC6 pluginId \u4E0E\u7F51\u5173\u6839 baseUrl \u5FC5\u586B");
|
|
262
262
|
}
|
|
263
263
|
const prefix = options.prefix ?? DEFAULT_PREFIX;
|
|
264
|
-
const
|
|
265
|
-
const guarded = async (name, args) => {
|
|
266
|
-
if (shortActionOf(name) === "updateInstall") {
|
|
267
|
-
throw new Error("[dsh-plugin-update] \u5165\u53E3\u4EF6\u53EA\u5141\u8BB8\u53EA\u8BFB\u7535\u8BDD\uFF0CupdateInstall \u7981\u6B62\uFF08\u6E90\u7801\u7EA7\uFF09");
|
|
268
|
-
}
|
|
269
|
-
return rawCall(name, args);
|
|
270
|
-
};
|
|
264
|
+
const call = createHttpCall({ prefix, baseUrl: options.baseUrl, routes: options.routes, fetch: options.fetch, fetchImpl: options.fetchImpl, timeout: options.timeout, timeoutMs: options.timeoutMs });
|
|
271
265
|
const { baseUrl: _b, routes: _r, fetch: _f, fetchImpl: _fi, timeout: _t, timeoutMs: _tm, prefix: _p, ...entryRest } = options;
|
|
272
|
-
return mountUpdateEntry(container, { ...entryRest, pluginId: options.pluginId, prefix, call
|
|
266
|
+
return mountUpdateEntry(container, { ...entryRest, pluginId: options.pluginId, prefix, call });
|
|
273
267
|
}
|
|
274
268
|
function mountUpdateBatchPanelHttp(container, options) {
|
|
275
269
|
if (!options || typeof options !== "object") {
|
package/dist/lang.d.ts
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/** 本包跟随的两种语言:中文(历史行为)与英文(其余语言落英文)。 */
|
|
2
|
+
export type AppLang = 'zh' | 'en';
|
|
3
|
+
/** 显式覆盖的两种形态:稳定码 'zh' | 'en',或带 getActive/subscribe 的服务对象(可注入假信号源,测试不依赖 jsdom)。 */
|
|
4
|
+
export interface LocaleService {
|
|
5
|
+
getActive(): string;
|
|
6
|
+
subscribe?(cb: () => void): () => void;
|
|
7
|
+
}
|
|
8
|
+
/** 入口件/面板/批量挂载点的语言选项:显式覆盖,不传即跟随全局信号。 */
|
|
9
|
+
export type LocaleOption = 'zh' | 'en' | LocaleService | string | null | undefined;
|
|
10
|
+
type LangCallback = (lang: AppLang) => void;
|
|
11
|
+
/**
|
|
12
|
+
* 归一语言标签:zh* → zh;形如 BCP47 的已知非中文标签 → en;空/垃圾 → zh(零回归)。
|
|
13
|
+
* 大小写不敏感,_ 视作 -。
|
|
14
|
+
*/
|
|
15
|
+
export declare function normalizeLangTag(tag: unknown): AppLang;
|
|
16
|
+
/**
|
|
17
|
+
* 解出当前语言:显式覆盖 > html[lang] > navigator.languages > zh。
|
|
18
|
+
* 纯函数(除读全局信号外无副作用);无信号永不抛,落 zh。
|
|
19
|
+
*/
|
|
20
|
+
export declare function resolveLang(override?: LocaleOption): AppLang;
|
|
21
|
+
/**
|
|
22
|
+
* 订阅语言变化:html[lang] 变化或可选服务源触发时回新语言。
|
|
23
|
+
* 模块级单例:多个挂载件共用一个 MutationObserver;返回 unsubscribe,unmount 后停订。
|
|
24
|
+
* 无 DOM 环境安全降级:没有 document/MutationObserver 时只记回调、永不触发,不抛。
|
|
25
|
+
*/
|
|
26
|
+
export declare function subscribeLang(cb: LangCallback, override?: LocaleOption): () => void;
|
|
27
|
+
/** 测试/维护用:清空全部订阅并断开单例观察者(正常业务代码不调它)。 */
|
|
28
|
+
export declare function __resetLangState(): void;
|
|
29
|
+
export {};
|
package/dist/panel-batch.js
CHANGED
|
@@ -383,6 +383,8 @@ const UPDATE_BATCH_PANEL_CSS = [
|
|
|
383
383
|
".dsh-upd-bdetail{margin:2px 0 10px;overflow:visible}",
|
|
384
384
|
".dsh-upd .dsh-upd-bdetail .dsh-upd{max-width:none}",
|
|
385
385
|
".dsh-upd-overlay .dsh-upd-bdetail .dsh-upd{max-height:none;overflow:visible}",
|
|
386
|
+
".dsh-upd-overlay .dsh-upd-bdetail .dsh-upd-body{overflow:visible}",
|
|
387
|
+
".dsh-upd-overlay .dsh-upd-bdetail .dsh-upd-body .dsh-upd-chap-head{position:static}",
|
|
386
388
|
"@media (prefers-color-scheme: dark){.dsh-upd-batch-title i{color:var(--dsh-upd-focus,#93c5fd)}}",
|
|
387
389
|
"@media (prefers-reduced-motion: reduce){.dsh-upd-batch *{transition:none !important;animation:none !important}}"
|
|
388
390
|
].join(String.fromCharCode(10));
|
package/dist/panel.d.ts
CHANGED
|
@@ -18,7 +18,7 @@ export type UpdatePanelCall = (phoneName: string, args: Record<string, unknown>)
|
|
|
18
18
|
/** 复制文本的出口:不传即尝试浏览器剪贴板,都没有则只留“已生成、请手动复制”提示。 */
|
|
19
19
|
export type UpdatePanelCopyText = (text: string) => void | Promise<void>;
|
|
20
20
|
/** 面板可点的动作(与 HTML 里 data-action 一一对应,测试走同一条路)。 */
|
|
21
|
-
export type UpdatePanelActionKind = 'check' | 'install' | 'skip' | 'reset-skip' | 'copy-manual' | 'copy-diag' | 'toggle-queue' | 'restart-hint' | 'close-view' | 'dismiss-failure';
|
|
21
|
+
export type UpdatePanelActionKind = 'check' | 'install' | 'skip' | 'reset-skip' | 'copy-manual' | 'copy-diag' | 'toggle-queue' | 'toggle-changelog' | 'restart-hint' | 'close-view' | 'dismiss-failure';
|
|
22
22
|
export interface UpdatePanelOptions {
|
|
23
23
|
/** 插件标识:必填,与宿主侧 createHostUpdate 传的 pluginId 一致。 */
|
|
24
24
|
pluginId: string;
|
|
@@ -86,6 +86,8 @@ export interface UpdatePanelController {
|
|
|
86
86
|
setTheme(theme: UpdatePanelTheme): Promise<void>;
|
|
87
87
|
/** 切换排队可见性(重查一次,位置口径不变)。 */
|
|
88
88
|
setShowOthers(show: boolean): Promise<void>;
|
|
89
|
+
/** 收起/展开更新日志(纯视图态,不调电话;轮询与换肤不丢)。 */
|
|
90
|
+
setChangelogCollapsed(collapsed: boolean): Promise<void>;
|
|
89
91
|
/**
|
|
90
92
|
* 换一版更新日志后重绘(#23:宿主侧备好新文本后调用;传 null/空串即回中性提示)。
|
|
91
93
|
* 只换日志节,安装门控只跟快照,一字不动。
|
|
@@ -258,6 +260,11 @@ export interface PanelRenderInput extends PanelViewInput {
|
|
|
258
260
|
* 只读渲染下五章内容、进度条、「已跳过」提示一字不减,只是没有动作按钮。
|
|
259
261
|
*/
|
|
260
262
|
actions?: 'default' | 'none';
|
|
263
|
+
/**
|
|
264
|
+
* 更新日志折叠(仅挂载态内部用:用户点了 02 章标题行的收起/展开)。
|
|
265
|
+
* 缺省即展开(安全日志必显、可查找;只读渲染下恒展开)。
|
|
266
|
+
*/
|
|
267
|
+
changelogCollapsed?: boolean;
|
|
261
268
|
}
|
|
262
269
|
/** 内核渲染用的失败引用(只读快照:证据仍在锁存里,这里只传展示键)。 */
|
|
263
270
|
export interface PanelFailureRef {
|
package/dist/panel.js
CHANGED
|
@@ -528,7 +528,15 @@ const UPDATE_PANEL_CSS = [
|
|
|
528
528
|
".dsh-upd-changelog-more-note{font-size:12px;opacity:.7;margin:2px 0 4px}",
|
|
529
529
|
".dsh-upd-changelog-neutral{color:inherit;opacity:.8}",
|
|
530
530
|
".dsh-upd-overlay{position:fixed;inset:0;background:rgba(0,0,0,.35);display:flex;align-items:center;justify-content:center;z-index:9999}",
|
|
531
|
-
".dsh-upd-overlay .dsh-upd{background:var(--dsh-upd-bg,#ffffff);max-height:85vh;overflow:
|
|
531
|
+
".dsh-upd-overlay .dsh-upd{background:var(--dsh-upd-bg,#ffffff);max-height:85vh;display:flex;flex-direction:column;overflow:hidden}",
|
|
532
|
+
// —— 弹窗分栏滚动:头(抬头/档案头/横幅/版本条)与尾固定,只有 01–05 章节区滚动 ——
|
|
533
|
+
".dsh-upd-body{min-height:0}",
|
|
534
|
+
".dsh-upd-overlay .dsh-upd-body{flex:1 1 auto;overflow-y:auto;overscroll-behavior:contain;scrollbar-width:thin;scrollbar-color:var(--dsh-upd-line,#e5e7eb) transparent}",
|
|
535
|
+
".dsh-upd-overlay .dsh-upd-body::-webkit-scrollbar{width:8px}",
|
|
536
|
+
".dsh-upd-overlay .dsh-upd-body::-webkit-scrollbar-thumb{background:var(--dsh-upd-line,#e5e7eb);border-radius:4px}",
|
|
537
|
+
".dsh-upd-overlay .dsh-upd-body::-webkit-scrollbar-track{background:transparent}",
|
|
538
|
+
// —— 章节标题磁吸:滚动时节标题贴顶(纯 CSS sticky;背景跟随主题,D5 另覆)——
|
|
539
|
+
".dsh-upd-overlay .dsh-upd-body .dsh-upd-chap-head{position:sticky;top:0;z-index:1;background:var(--dsh-upd-bg,#ffffff);padding-top:2px}",
|
|
532
540
|
// —— 档案头 / 版本条 / 章节 / 进度条 / 跳过行(原型 :208-245 的新结构,默认主题给最小可用样式)——
|
|
533
541
|
".dsh-upd-head{display:flex;gap:12px;align-items:baseline;flex-wrap:wrap}",
|
|
534
542
|
// 卷宗抬头「插件更新 / 更新档案 卷」:D5 档案卷才画,默认(最小)主题不画。
|
|
@@ -582,11 +590,18 @@ const UPDATE_PANEL_CSS = [
|
|
|
582
590
|
".dsh-upd button:active:not(:disabled){transform:translateY(1px)}",
|
|
583
591
|
'.dsh-upd button[aria-busy="true"]{cursor:wait;animation:dsh-upd-pulse 1s ease-in-out infinite}',
|
|
584
592
|
"@keyframes dsh-upd-pulse{0%,100%{opacity:1}50%{opacity:.55}}",
|
|
593
|
+
// —— 状态横幅淡入 + 日志折叠格动画(纯 CSS;重绘只发生在真变时;reduced-motion 下静止)——
|
|
594
|
+
".dsh-upd-banner{animation:dsh-upd-fadein .22s ease}",
|
|
595
|
+
"@keyframes dsh-upd-fadein{from{opacity:.35;transform:translateY(2px)}}",
|
|
596
|
+
".dsh-upd-changelog-foldbox{display:grid;grid-template-rows:1fr;opacity:1;transition:grid-template-rows .22s ease,opacity .18s ease}",
|
|
597
|
+
".dsh-upd-changelog-foldbox-inner{min-height:0;overflow:hidden}",
|
|
598
|
+
'.dsh-upd-changelog-foldbox[data-open="0"]{grid-template-rows:0fr;opacity:0}',
|
|
585
599
|
// 在途转圈:纯 CSS ::after,不加 DOM 节点(内核 DOM 冻结);转的是边框缺口,不是 emoji。
|
|
586
600
|
'.dsh-upd button[aria-busy="true"]::after{content:"";display:inline-block;width:11px;height:11px;margin-left:8px;vertical-align:-1px;',
|
|
587
601
|
"border:2px solid currentColor;border-top-color:transparent;border-radius:50%;animation:dsh-upd-spin .8s linear infinite}",
|
|
588
602
|
"@keyframes dsh-upd-spin{to{transform:rotate(360deg)}}",
|
|
589
|
-
'@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}}',
|
|
603
|
+
'@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}.dsh-upd-banner{animation:none}.dsh-upd-changelog-foldbox{transition:none}}',
|
|
604
|
+
"@media (forced-colors: active){.dsh-upd-overlay .dsh-upd-body .dsh-upd-chap-head{background:Canvas}}",
|
|
590
605
|
"@media (prefers-color-scheme: dark){.dsh-upd{--dsh-upd-fg:#e5e7eb;--dsh-upd-bg:#111827;--dsh-upd-line:#374151;",
|
|
591
606
|
"--dsh-upd-btn:#1f2937;--dsh-upd-soft:#1f2937;--dsh-upd-primary:#3b82f6;--dsh-upd-focus:#93c5fd;",
|
|
592
607
|
// 横幅深色覆盖:底色用低透明度同色系(不是浅色原值),边线提亮,保证「深底浅字」可读。
|
|
@@ -650,6 +665,9 @@ const UPDATE_PANEL_D5_CSS = [
|
|
|
650
665
|
'.dsh-upd[data-theme="archive"] .dsh-upd-qn{font-family:var(--d5-mono);font-size:11.5px;color:var(--d5-muted)}',
|
|
651
666
|
'.dsh-upd[data-theme="archive"] .dsh-upd-qseq{color:var(--d5-muted)}',
|
|
652
667
|
'.dsh-upd[data-theme="archive"] .dsh-upd-chap-note{color:var(--d5-muted)}',
|
|
668
|
+
'.dsh-upd[data-theme="archive"] .dsh-upd-body .dsh-upd-chap-head{background:var(--d5-card)}',
|
|
669
|
+
'.dsh-upd-overlay .dsh-upd[data-theme="archive"] .dsh-upd-body{scrollbar-color:var(--d5-line-strong) transparent}',
|
|
670
|
+
'.dsh-upd-overlay .dsh-upd[data-theme="archive"] .dsh-upd-body::-webkit-scrollbar-thumb{background:var(--d5-line-strong)}',
|
|
653
671
|
// —— 小印章(原型 :215 `.sealmini`:30px、旋转 -5°、一字)——
|
|
654
672
|
// 待重启横幅一律不画印章:那一档的标记是左侧手绘 SVG(原型 :446 的 .mark 只有 SVG)。
|
|
655
673
|
'.dsh-upd[data-theme="archive"] .dsh-upd-banner[data-kind="loading"]::before,.dsh-upd[data-theme="archive"] .dsh-upd-banner[data-kind="idle"]::before,',
|
|
@@ -805,9 +823,11 @@ function renderUpdatePanelKernel(input, view) {
|
|
|
805
823
|
`<div class="dsh-upd-skipline"><span class="dsh-upd-tag">\u5DF2\u8DF3\u8FC7 ${escapeHtml(snapshot.latestVersion)}</span>\u70B9\u300C\u6062\u590D\u300D\u53EF\u64A4\u9500\uFF0C\u4E4B\u540E\u8FD9\u4E00\u7248\u8FD8\u4F1A\u518D\u63D0\u9192\u3002</div>`
|
|
806
824
|
);
|
|
807
825
|
}
|
|
808
|
-
|
|
826
|
+
const chapters = [];
|
|
827
|
+
chapters.push(chapterOf(1, actions.join("")));
|
|
809
828
|
{
|
|
810
829
|
let inner = "";
|
|
830
|
+
let hasLog = false;
|
|
811
831
|
if (snapshot && snapshot.latestVersion) {
|
|
812
832
|
try {
|
|
813
833
|
const mdText = typeof changelogMarkdown === "string" ? changelogMarkdown : "";
|
|
@@ -837,9 +857,11 @@ function renderUpdatePanelKernel(input, view) {
|
|
|
837
857
|
} catch {
|
|
838
858
|
yankedBanner = "";
|
|
839
859
|
}
|
|
840
|
-
|
|
860
|
+
const logOpen = input.changelogCollapsed !== true;
|
|
861
|
+
inner = `<div class="dsh-upd-changelog-wrap"><div>${escapeHtml(rangeTitle)}</div><div class="dsh-upd-changelog-foldbox" data-open="${logOpen ? "1" : "0"}"><div class="dsh-upd-changelog-foldbox-inner">${yankedBanner}
|
|
841
862
|
${changelogHTML}
|
|
842
|
-
</div>`;
|
|
863
|
+
</div></div></div>`;
|
|
864
|
+
hasLog = Array.isArray(ranged) && ranged.length > 0;
|
|
843
865
|
} catch {
|
|
844
866
|
inner = "";
|
|
845
867
|
}
|
|
@@ -849,7 +871,9 @@ ${changelogHTML}
|
|
|
849
871
|
snapshot && snapshot.latestVersion ? "\u65E5\u5FD7\u8BFB\u4E0D\u51FA\u6765\uFF0C\u5B89\u88C5\u4E0D\u53D7\u5F71\u54CD\u3002" : "\u8FD8\u6CA1\u67E5\u5230\u65B0\u7248\uFF1B\u67E5\u5230\u540E\u518D\u663E\u793A\u65E5\u5FD7\u3002"
|
|
850
872
|
)}</div></div>`;
|
|
851
873
|
}
|
|
852
|
-
|
|
874
|
+
const logCollapsed = input.changelogCollapsed === true;
|
|
875
|
+
const logNote = showActions && hasLog ? `<span class="dsh-upd-chap-note"><button type="button" data-action="toggle-changelog" title="\u5C55\u5F00\u6216\u6536\u8D77\u66F4\u65B0\u65E5\u5FD7">${logCollapsed ? "\u5C55\u5F00\u66F4\u65B0\u65E5\u5FD7" : "\u6536\u8D77\u66F4\u65B0\u65E5\u5FD7"}</button></span>` : "";
|
|
876
|
+
chapters.push(chapterOf(2, inner, logNote));
|
|
853
877
|
}
|
|
854
878
|
{
|
|
855
879
|
const queued = !!queue && (queue.busy || queue.waiting.length > 0);
|
|
@@ -876,9 +900,9 @@ ${changelogHTML}
|
|
|
876
900
|
);
|
|
877
901
|
}
|
|
878
902
|
const note = showActions ? `<span class="dsh-upd-chap-note"><button type="button" data-action="toggle-queue">${reveal ? "\u9690\u85CF\u4ED6\u4EBA\u660E\u7EC6" : "\u663E\u793A\u5176\u4ED6\u63D2\u4EF6"}</button></span>` : "";
|
|
879
|
-
|
|
903
|
+
chapters.push(chapterOf(3, `<div class="dsh-upd-queue">${rows.join("")}</div>`, note));
|
|
880
904
|
} else {
|
|
881
|
-
|
|
905
|
+
chapters.push(
|
|
882
906
|
chapterOf(
|
|
883
907
|
3,
|
|
884
908
|
`<div class="dsh-upd-queue"><div class="dsh-upd-changelog-neutral">${escapeHtml(
|
|
@@ -930,14 +954,15 @@ ${changelogHTML}
|
|
|
930
954
|
}
|
|
931
955
|
}
|
|
932
956
|
if (copyNotice) errLines.push(`<div class="dsh-upd-copy" role="status">${escapeHtml(copyNotice)}</div>`);
|
|
933
|
-
|
|
957
|
+
chapters.push(chapterOf(4, errLines.join("")));
|
|
934
958
|
}
|
|
935
|
-
|
|
959
|
+
chapters.push(
|
|
936
960
|
chapterOf(
|
|
937
961
|
5,
|
|
938
962
|
view.showManual && manual ? `<div class="dsh-upd-manual"><div>\u624B\u5DE5\u515C\u5E95\u547D\u4EE4\uFF08\u590D\u5236\u6574\u884C\u6267\u884C\uFF09\uFF1A</div><code>${escapeHtml(manual)}</code></div>` : `<div class="dsh-upd-manual"><div class="dsh-upd-changelog-neutral">\u5F53\u524D\u6CA1\u6709\u53EF\u7528\u7684\u624B\u5DE5\u547D\u4EE4\uFF08\u8BA4\u4E0D\u51FA\u4F7F\u7528\u8303\u56F4\u6216\u5C5E\u6E90\u7801\u5B89\u88C5\u65F6\u4E0D\u7ED9\uFF09\u3002</div></div>`
|
|
939
963
|
)
|
|
940
964
|
);
|
|
965
|
+
parts.push('<div class="dsh-upd-body">' + chapters.join("\n") + "</div>");
|
|
941
966
|
if (showActions && mode === "dialog") {
|
|
942
967
|
parts.push(
|
|
943
968
|
`<div class="dsh-upd-footer"><span class="dsh-upd-foot-note">\u5173\u95ED\u4E0D\u5F71\u54CD\u66F4\u65B0\uFF0C\u53EF\u968F\u65F6\u56DE\u6765\u67E5\u770B</span><button type="button" data-action="close-view" title="\u5173\u95ED\u7A97\u53E3\uFF0C\u66F4\u65B0\u4E0D\u53D7\u5F71\u54CD">\u5173\u95ED</button></div>`
|
|
@@ -1056,6 +1081,7 @@ function mountUpdatePanel(container, options) {
|
|
|
1056
1081
|
}
|
|
1057
1082
|
let theme = normalizePanelTheme(options.theme ?? "default");
|
|
1058
1083
|
let showOthers = options.showOthers === true;
|
|
1084
|
+
let changelogCollapsed = false;
|
|
1059
1085
|
const call = options.call;
|
|
1060
1086
|
const onRestartRequested = options.onRestartRequested;
|
|
1061
1087
|
const onCloseRequested = typeof options.onCloseRequested === "function" ? options.onCloseRequested : null;
|
|
@@ -1158,6 +1184,38 @@ function mountUpdatePanel(container, options) {
|
|
|
1158
1184
|
atMs: latchNow()
|
|
1159
1185
|
};
|
|
1160
1186
|
}
|
|
1187
|
+
function thrownDetail(err) {
|
|
1188
|
+
try {
|
|
1189
|
+
const raw = err instanceof Error ? err.message : typeof err === "string" ? err : null;
|
|
1190
|
+
if (typeof raw !== "string") return null;
|
|
1191
|
+
const t = raw.trim();
|
|
1192
|
+
if (!t) return null;
|
|
1193
|
+
if (/^[a-z][a-z-]*$/.test(t) && t.length <= 32) return null;
|
|
1194
|
+
return redactForCopy(t) || null;
|
|
1195
|
+
} catch {
|
|
1196
|
+
return null;
|
|
1197
|
+
}
|
|
1198
|
+
}
|
|
1199
|
+
function userThrowLatch(source, err) {
|
|
1200
|
+
const env = currentEnvPair();
|
|
1201
|
+
return {
|
|
1202
|
+
code: source === "install" ? "install-failed" : "check-failed",
|
|
1203
|
+
kind: null,
|
|
1204
|
+
detail: thrownDetail(err),
|
|
1205
|
+
diag: null,
|
|
1206
|
+
requestId: source === "install" ? requestId : null,
|
|
1207
|
+
checkId: source === "install" ? receipt?.checkId ?? null : null,
|
|
1208
|
+
runningVersion: snapshot?.runningVersion ?? null,
|
|
1209
|
+
installedVersion: snapshot?.installedVersion ?? null,
|
|
1210
|
+
latestVersion: snapshot?.latestVersion ?? null,
|
|
1211
|
+
hostKind: env.hostKind,
|
|
1212
|
+
profileName: env.profileName,
|
|
1213
|
+
source,
|
|
1214
|
+
volatile: false,
|
|
1215
|
+
jobId: null,
|
|
1216
|
+
atMs: latchNow()
|
|
1217
|
+
};
|
|
1218
|
+
}
|
|
1161
1219
|
function volatileLatch(source) {
|
|
1162
1220
|
const env = currentEnvPair();
|
|
1163
1221
|
return {
|
|
@@ -1244,6 +1302,7 @@ function mountUpdatePanel(container, options) {
|
|
|
1244
1302
|
changelogMarkdown,
|
|
1245
1303
|
mode,
|
|
1246
1304
|
showOthers,
|
|
1305
|
+
changelogCollapsed,
|
|
1247
1306
|
pluginId,
|
|
1248
1307
|
copyNotice,
|
|
1249
1308
|
theme,
|
|
@@ -1404,9 +1463,9 @@ function mountUpdatePanel(container, options) {
|
|
|
1404
1463
|
if (!mounted) return;
|
|
1405
1464
|
applyStatusReply(reply, "check");
|
|
1406
1465
|
changelogFailedAt.clear();
|
|
1407
|
-
} catch {
|
|
1466
|
+
} catch (err) {
|
|
1408
1467
|
if (!mounted) return;
|
|
1409
|
-
setLatch(
|
|
1468
|
+
setLatch(userThrowLatch("check", err));
|
|
1410
1469
|
} finally {
|
|
1411
1470
|
busyAct = null;
|
|
1412
1471
|
if (copyNotice === "\u6B63\u5728\u67E5\u65B0\u7248\u2026") copyNotice = null;
|
|
@@ -1422,9 +1481,16 @@ function mountUpdatePanel(container, options) {
|
|
|
1422
1481
|
render();
|
|
1423
1482
|
try {
|
|
1424
1483
|
if (!receipt) {
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1484
|
+
try {
|
|
1485
|
+
const checked = await call(phoneNames.updateCheck, queueArgs());
|
|
1486
|
+
if (!mounted) return;
|
|
1487
|
+
applyStatusReply(checked, "check");
|
|
1488
|
+
} catch (err) {
|
|
1489
|
+
if (!mounted) return;
|
|
1490
|
+
setLatch(userThrowLatch("check", err));
|
|
1491
|
+
render();
|
|
1492
|
+
return;
|
|
1493
|
+
}
|
|
1428
1494
|
}
|
|
1429
1495
|
if (!mounted) return;
|
|
1430
1496
|
if (!receipt) {
|
|
@@ -1457,9 +1523,9 @@ function mountUpdatePanel(container, options) {
|
|
|
1457
1523
|
});
|
|
1458
1524
|
if (!mounted) return;
|
|
1459
1525
|
applyStatusReply(reply, "install");
|
|
1460
|
-
} catch {
|
|
1526
|
+
} catch (err) {
|
|
1461
1527
|
if (!mounted) return;
|
|
1462
|
-
setLatch(
|
|
1528
|
+
setLatch(userThrowLatch("install", err));
|
|
1463
1529
|
} finally {
|
|
1464
1530
|
busyAct = null;
|
|
1465
1531
|
if (copyNotice === "\u6B63\u5728\u5B89\u88C5\u2026") copyNotice = null;
|
|
@@ -1567,6 +1633,11 @@ function mountUpdatePanel(container, options) {
|
|
|
1567
1633
|
await refresh();
|
|
1568
1634
|
return;
|
|
1569
1635
|
}
|
|
1636
|
+
case "toggle-changelog": {
|
|
1637
|
+
changelogCollapsed = !changelogCollapsed;
|
|
1638
|
+
render();
|
|
1639
|
+
return;
|
|
1640
|
+
}
|
|
1570
1641
|
// 「重启宿主」:宿主没有重启自己的电话,所以只做入口——
|
|
1571
1642
|
// 调用方给了 onRestartRequested 就交给它;没给就如实说“请手动重启”,不假装。
|
|
1572
1643
|
case "restart-hint": {
|
|
@@ -1607,6 +1678,10 @@ function mountUpdatePanel(container, options) {
|
|
|
1607
1678
|
showOthers = show === true;
|
|
1608
1679
|
await refresh();
|
|
1609
1680
|
}
|
|
1681
|
+
async function setChangelogCollapsed(collapsed) {
|
|
1682
|
+
changelogCollapsed = collapsed === true;
|
|
1683
|
+
render();
|
|
1684
|
+
}
|
|
1610
1685
|
function onClick(ev) {
|
|
1611
1686
|
try {
|
|
1612
1687
|
const t = ev;
|
|
@@ -1683,7 +1758,7 @@ function mountUpdatePanel(container, options) {
|
|
|
1683
1758
|
} catch {
|
|
1684
1759
|
}
|
|
1685
1760
|
})();
|
|
1686
|
-
return { refresh, act, setMode, setTheme, setShowOthers, setChangelogMarkdown, unmount };
|
|
1761
|
+
return { refresh, act, setMode, setTheme, setShowOthers, setChangelogCollapsed, setChangelogMarkdown, unmount };
|
|
1687
1762
|
}
|
|
1688
1763
|
import { buildPhoneNames as buildPhoneNames2 } from "./config.js";
|
|
1689
1764
|
import { buildChangelogPhoneName as buildChangelogPhoneName2 } from "./config.js";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-plugin-update",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.7",
|
|
4
4
|
"description": "可复用的更新系统装成的 npm 包:任何 DSH 插件照文档能集成检查更新等功能(地图 #579)",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "王辰浩",
|
|
@@ -65,7 +65,9 @@
|
|
|
65
65
|
"build": "node build.mjs",
|
|
66
66
|
"prepack": "npm run build",
|
|
67
67
|
"pretest": "npm run build",
|
|
68
|
-
"test": "node --test tests/*.test.mjs"
|
|
68
|
+
"test": "node --test tests/*.test.mjs",
|
|
69
|
+
"gate:bilingual": "node scripts/bilingual-gate.mjs",
|
|
70
|
+
"gate:bilingual:release": "node scripts/bilingual-gate.mjs --release"
|
|
69
71
|
},
|
|
70
72
|
"devDependencies": {
|
|
71
73
|
"esbuild": "^0.28.2",
|