dsh-m 0.9.79 → 0.9.81
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 +14 -0
- package/lib/client.js +75 -31
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -8,6 +8,13 @@ The full release history of dsh-m, maintained bilingually: **Chinese first, Engl
|
|
|
8
8
|
|
|
9
9
|
## 中文
|
|
10
10
|
|
|
11
|
+
### 0.9.80 修复:已装页开关抖动根治 + 社区开关定位恒定 + 「已实测」徽章退役(三项 UX 修复,client-only)
|
|
12
|
+
|
|
13
|
+
- **① 已装页开关抖动根治(主人实拍:点开关整页抖、开关原地失踪、鼠标不再命中)**:CDP 实测每次点击开关发生 47px×2 卡片栅格位移 + 0.6–1.3s 命中丢失窗口(原点落到上方卡片 `.dshm-links` 外链行,误触即开浏览器标签)。根因三件:`ProgressLine`(install 专用 pnpm 进度条)对 toggle 也挂载(35px 行 + body 12px gap,插入/拔出即位移);toast/重启横幅是面板 column flex 的流内子元素(出现/消失压缩 body 39px×2);开关视觉翻转要等 5 个刷新请求落地(1.5–2.3s「点了没反应」真空期,且期间开关 `locked` 灰态)。修复:新增 `progressTarget`(仅 install/upgrade/self-upgrade 挂进度条;`activeMutateTarget` 语义不动,仍管逐行禁用);toast/横幅包进 `.dshm-banner-stack`(absolute 底部浮层,pointer-events 穿透);`pendingToggles` 乐观翻转(点击 42ms 即变,`finally` 摘除=成功收敛/失败回滚);toggle 只重取已装视图(installed+market×2+updates+external-operations → installed×1,`view-refresh.js` 未动、单测原样);`.dshm-switch::before` 热区 34×19 → 46×31(视觉不变)。CDP 回测四断言全过:位移 0、命中零丢失、翻转 42ms、body 底缘 0 位移。
|
|
14
|
+
- **② 社区目录开关钉进标题行(主人实拍:开/关后开关位置高低不同)**:开关行原是卡片 body 末行,关态 5 行元信息消失即被上提约 5 行高。移入 `.dshm-section-title` 右侧(flex 现成 + 开关自带 `margin-left:auto`;与已装卡片右上角开关同一交互语言),CDP 实测 ON/OFF 两态开关 y 恒等(135.2px,漂移 0.0);冗余「社区目录开关」行退役,语义并入开关 tooltip。
|
|
15
|
+
- **③ 「已实测」徽章退役(B 方案:byline 灰字承接)**:verified 仅覆盖精选 4/21 条且全为作者自家插件——徽章实为署名代理、区分度趋零,真载荷(实测过的 DSH 运行时清单)藏在 hover tooltip 里触屏不可达;按「卡片徽章只放例外信号(弃用/自用/可升级)」原则退役。市场卡/收藏快照卡/弹窗头三处渲染退役;市场卡 tag 行尾新增灰字 `实测 ≤{最新复验版本}`(tooltip 全量清单);详情弹窗「实测版本」行保留为唯一权威呈现;`badge.verified` 键按 0.9.76「版本无关徽章退役」先例退役;registry 数据、snapshotOf 透传与安装期 peer 兼容弹窗零触碰。
|
|
16
|
+
- **验证**:1425 项测试全绿(0.9.79 基线 1423 + 退役断言 2;U12 收藏卡契约随 ③ 改写为新契约)、typecheck 零错误;三项均 client-only,刷新页面即生效;①② 经 CDP 全程量化回测(位移/命中/翻转延迟/几何恒定)。
|
|
17
|
+
|
|
11
18
|
### 0.9.79 功能:外部操作记录——非面板通道(CLI / Agent 工具)变更直落审计日志进面板「已结束」(ADR-0018)
|
|
12
19
|
|
|
13
20
|
- **问题(审计面脱节实证)**:全局操作记录的口径 = 面板发起——quota-watch 0.1.28 经 `dshm_upgrade`(Agent 工具)升级装机成功后,面板「已结束」列表零记录,操作审计面与真实系统状态脱节。CLI 与 Agent 工具是独立进程,写不进浏览器 localStorage 的操作泵。
|
|
@@ -572,6 +579,13 @@ The full release history of dsh-m, maintained bilingually: **Chinese first, Engl
|
|
|
572
579
|
|
|
573
580
|
## English
|
|
574
581
|
|
|
582
|
+
### Fixes in 0.9.80 — installed-tab toggle jitter eliminated + community switch pinned to its title row + 已实测 badge retired (three UX fixes, client-only)
|
|
583
|
+
|
|
584
|
+
- **① Installed-tab toggle jitter eliminated (user report: clicking the switch shook the whole page, the switch vanished in place, and the cursor no longer hit it)**: CDP measurement showed a 47px×2 card-grid shift per click plus a 0.6–1.3s hit-test loss window (the cursor's fixed point landed on the card above's `.dshm-links` external-links row — a mis-click opens a browser tab). Three root causes: `ProgressLine` (the install-only pnpm progress bar) mounted for toggles too (35px row + 12px body gap — inserting/unmounting it is the shift itself); the toast/restart banners were in-flow flex children of the panel column (mount/dismiss compressed the body by 39px×2); the switch visually flipped only after five refresh requests landed (a 1.5–2.3s "nothing happened" dead window, with the switch greyed to `locked`). Fixes: a new `progressTarget` gates ProgressLine to install/upgrade/self-upgrade (`activeMutateTarget` semantics untouched — it still drives per-row disabling); toasts/banners are wrapped in `.dshm-banner-stack` (absolute bottom overlay, pointer-events pass-through); optimistic `pendingToggles` flips the switch in 42ms (cleared in `finally` — converges on success, reverts to server state on failure); toggle refreshes the installed view only (installed+market×2+updates+external-operations → installed×1; `view-refresh.js` untouched, its unit tests unchanged); `.dshm-switch::before` grows the hit area 34×19 → 46×31 (visuals unchanged). CDP re-probe passes all four assertions: zero drift, zero hit-loss, 42ms flip, stable body bottom edge.
|
|
585
|
+
- **② Community catalog switch pinned to its section title row (user report: the switch sat at different heights when on vs off)**: the switch row used to be the last child of the card body — toggling off dropped five metadata rows and yanked the switch up ~5 row heights. It now lives at the right edge of `.dshm-section-title` (flex already in place + the switch's own `margin-left:auto`; same interaction language as the installed-page card switches). CDP-measured identical Y in both states (135.2px, 0.0 drift); the redundant "社区目录开关" row is retired into the switch tooltip.
|
|
586
|
+
- **③ 已实测 (verified) badge retired (plan B: byline gray text)**: verified covers only 4/21 curated entries — all the author's own plugins — making the badge an authorship proxy with near-zero discriminating power, while its real payload (the tested DSH runtime list) lived in a hover-only tooltip. Per the "card badges only carry exceptions (deprecated / internal / outdated)" principle it is retired from the market card, the favorite snapshot card, and the modal header; the market card tag line gains a low-emphasis `verified ≤{latest re-verified runtime}` suffix (full list on hover); the detail modal's "Verified runtimes" row remains the single authoritative presentation; the `badge.verified` i18n key is retired following the 0.9.76 version-independent-badge precedent. registry data, snapshotOf passthrough, and the install-time peer-compat dialog are untouched.
|
|
587
|
+
- **Verification**: 1425 tests green (0.9.79 baseline 1423 + 2 retirement assertions; the U12 favorites-card contract rewritten for ③), typecheck clean; all three fixes are client-only — a page refresh applies them; ① and ② were quantified end-to-end with CDP probes (drift / hit-testing / flip latency / geometry stability).
|
|
588
|
+
|
|
575
589
|
### Feature in 0.9.79 — external operation records: non-panel channels (CLI / agent tools) land terminal-state audit entries into the panel's Ended list (ADR-0018)
|
|
576
590
|
|
|
577
591
|
- **Problem (audit-surface disconnect, real incident)**: the global operation records only covered panel-initiated changes — the quota-watch 0.1.28 upgrade via `dshm_upgrade` (an agent tool) installed successfully yet left zero rows in the panel's Ended list. CLI and agent tools are separate processes and cannot write the browser-localStorage operations pump.
|
package/lib/client.js
CHANGED
|
@@ -1975,8 +1975,8 @@ var ZH = {
|
|
|
1975
1975
|
"zone.favorites": "\u6536\u85CF",
|
|
1976
1976
|
"badge.deprecated": "\u5DF2\u5F03\u7528",
|
|
1977
1977
|
"sub.snapshot": "v{v}\uFF08\u76EE\u5F55\u5FEB\u7167\uFF09",
|
|
1978
|
-
"badge.verified": "\u5DF2\u5B9E\u6D4B",
|
|
1979
1978
|
"badge.internal": "\u4F5C\u8005\u81EA\u7528",
|
|
1979
|
+
"byline.verified": "\u5B9E\u6D4B \u2264{v}",
|
|
1980
1980
|
"modal.category": "\u5206\u7C7B",
|
|
1981
1981
|
"modal.added": "\u6536\u5F55\u65E5\u671F",
|
|
1982
1982
|
"modal.dlwindow": "\u4E0B\u8F7D\u91CF\uFF0830 \u5929\u7A97\u53E3\uFF09",
|
|
@@ -2274,8 +2274,8 @@ var EN = {
|
|
|
2274
2274
|
"zone.favorites": "Favorites",
|
|
2275
2275
|
"badge.deprecated": "Deprecated",
|
|
2276
2276
|
"sub.snapshot": "v{v} (catalog snapshot)",
|
|
2277
|
-
"badge.verified": "Verified",
|
|
2278
2277
|
"badge.internal": "Author's own",
|
|
2278
|
+
"byline.verified": "verified \u2264{v}",
|
|
2279
2279
|
"modal.category": "Category",
|
|
2280
2280
|
"modal.added": "Added",
|
|
2281
2281
|
"modal.dlwindow": "Downloads (30-day window)",
|
|
@@ -2578,7 +2578,7 @@ function communityLabels(data) {
|
|
|
2578
2578
|
}
|
|
2579
2579
|
var CSS = `
|
|
2580
2580
|
.dshm-overlay{position:fixed;inset:0;z-index:2147483000;background:var(--dsw-alias-bg-mask-3,rgba(15,23,42,.48));display:flex;align-items:center;justify-content:center;padding:max(24px,var(--dsh-windows-titlebar-height,0px)) 16px 24px;box-sizing:border-box}
|
|
2581
|
-
.dshm-panel{width:min(920px,100%);height:min(680px,86vh);display:flex;flex-direction:column;background:var(--dsw-alias-bg-elevated,var(--dsw-alias-bg-base,#fff));background:color-mix(in srgb,var(--dsw-alias-bg-base,#fff) 86%,transparent);backdrop-filter:blur(14px) saturate(1.3);-webkit-backdrop-filter:blur(14px) saturate(1.3);border:1px solid var(--dsw-alias-border-l2,#e5e7eb);border-radius:14px;box-shadow:0 18px 48px rgba(2,6,23,.25);overflow:hidden;font-family:inherit;color:var(--dsw-alias-label-primary,inherit)}
|
|
2581
|
+
.dshm-panel{position:relative;width:min(920px,100%);height:min(680px,86vh);display:flex;flex-direction:column;background:var(--dsw-alias-bg-elevated,var(--dsw-alias-bg-base,#fff));background:color-mix(in srgb,var(--dsw-alias-bg-base,#fff) 86%,transparent);backdrop-filter:blur(14px) saturate(1.3);-webkit-backdrop-filter:blur(14px) saturate(1.3);border:1px solid var(--dsw-alias-border-l2,#e5e7eb);border-radius:14px;box-shadow:0 18px 48px rgba(2,6,23,.25);overflow:hidden;font-family:inherit;color:var(--dsw-alias-label-primary,inherit)}
|
|
2582
2582
|
/* 0.9.70 \u8FD8\u539F\u6001\u62D6\u62FD\uFF1A.abs = \u6709\u4F4D\u7F6E\u8BB0\u5FC6\u65F6\u7684\u7EDD\u5BF9\u5B9A\u4F4D\u5F62\u6001\uFF08overlay \u4E3A inset:0 fixed\uFF0C
|
|
2583
2583
|
\u7EDD\u5BF9\u5B9A\u4F4D\u5750\u6807\u5373\u89C6\u53E3\u5750\u6807\uFF09\uFF1B\u65E0\u8BB0\u5F55\u65F6\u9762\u677F\u4ECD\u8D70 overlay flex \u5C45\u4E2D\uFF0C\u6E32\u67D3\u8DEF\u5F84\u4E0E\u65E7\u7248\u9010\u5B57\u8282\u4E00\u81F4\u3002
|
|
2584
2584
|
\u62D6\u62FD\u89C2\u611F\u4E0D\u53D8\u91CF\uFF080.9.70 \u4FEE\u8BA2\uFF0CADR-0017 v2\uFF09\uFF1A\u62D6\u62FD\u6001\u4E0E\u9759\u6B62\u6001\u540C\u73BB\u7483\u540C blur\uFF0C\u5916\u89C2\u9010\u50CF\u7D20\u4E00\u81F4
|
|
@@ -2831,6 +2831,8 @@ button.dshm-badge:hover{filter:brightness(.95)}
|
|
|
2831
2831
|
.dshm-sub{display:flex;align-items:center;gap:8px;font-size:11px;color:var(--dsw-alias-label-caption,#6b7280)}
|
|
2832
2832
|
.dshm-detail{margin-top:8px;border-top:1px dashed var(--dsw-alias-border-l2,#e5e7eb);padding-top:8px;display:flex;flex-direction:column;gap:6px;font-size:12px;color:var(--dsw-alias-label-secondary,#4b5563)}
|
|
2833
2833
|
.dshm-actions{display:flex;gap:6px;flex-wrap:wrap;margin-top:4px}
|
|
2834
|
+
.dshm-banner-stack{position:absolute;left:0;right:0;bottom:0;z-index:30;display:flex;flex-direction:column;pointer-events:none}
|
|
2835
|
+
.dshm-banner-stack .dshm-banner{pointer-events:auto}
|
|
2834
2836
|
.dshm-banner{display:flex;align-items:center;gap:10px;padding:10px 14px;border-top:1px solid var(--dsw-alias-border-l2,#e5e7eb);background:var(--dsw-alias-state-warn-tertiary,#fffbeb);color:var(--dsw-alias-state-warn-primary,#b45309);font-size:12px}
|
|
2835
2837
|
.dshm-banner.err{background:rgba(239,68,68,.13);color:var(--dsw-alias-state-error-primary,#b91c1c)}
|
|
2836
2838
|
/* 0.9.72 \u540C\u6B3E\u6EDA\u8F6E\u6CBB\u7406\uFF08\u89C1 dshm-ops-scroll \u6CE8\uFF09\uFF1A\u6A2A\u5E45\u6587\u672C\u4E0D\u6EE1 140px \u65F6\u4E0D\u5F97\u541E\u6EDA\u8F6E */
|
|
@@ -2928,6 +2930,9 @@ button.dshm-dshchip:disabled{cursor:default;opacity:.75}
|
|
|
2928
2930
|
.dshm-dot.idle{color:#9ca3af}
|
|
2929
2931
|
.dshm-dot.busy{color:#f59e0b}
|
|
2930
2932
|
.dshm-switch{position:relative;display:inline-flex;align-items:center;width:34px;height:19px;border-radius:10px;background:var(--dsw-alias-fill-secondary,#d1d5db);cursor:pointer;transition:background .15s;flex:none;margin-left:auto}
|
|
2933
|
+
/* \u70ED\u533A\u6269\u5C55\uFF082026-10-13 UX \u4FEE\u590D\uFF09\uFF1A\u89C6\u89C9 34\xD719 \u4E0D\u53D8\uFF0C\u53EF\u70B9\u9762\u79EF\u7ECF\u4F2A\u5143\u7D20\u6269\u5230 46\xD731\u2014\u2014
|
|
2934
|
+
\u5C0F\u76EE\u6807 + \u6574\u5361\u5927\u76EE\u6807\u76F8\u90BB\u7684\u8BEF\u89E6\u534A\u5F84\u6536\u655B\uFF1B\u5F00\u5173\u8DDD\u5361\u8FB9 12px\uFF0C-6px \u5916\u6EA2\u4E0D\u8D8A\u51FA\u81EA\u8EAB\u5361\u7247 */
|
|
2935
|
+
.dshm-switch::before{content:"";position:absolute;inset:-6px;border-radius:14px}
|
|
2931
2936
|
.dshm-switch input{display:none}
|
|
2932
2937
|
.dshm-switch.on{background:#22c55e}
|
|
2933
2938
|
.dshm-switch.locked{opacity:.45;cursor:not-allowed}
|
|
@@ -3746,7 +3751,6 @@ function DetailModal({ it, labels, busy, onClose, onInstall, onUpgrade, upgradeB
|
|
|
3746
3751
|
h(Icon, { entry: it }),
|
|
3747
3752
|
h("span", { className: "dshm-name" }, it.name),
|
|
3748
3753
|
it.deprecated === true ? h("span", { className: "dshm-badge warn" }, lookup("badge.deprecated")) : null,
|
|
3749
|
-
it.community !== true && Array.isArray(it.verified) && it.verified.length ? h("span", { className: "dshm-badge", title: it.verified.join("\u3001") }, lookup("badge.verified")) : null,
|
|
3750
3754
|
it.audience === "internal" ? h("span", { className: "dshm-badge" }, lookup("badge.internal")) : null,
|
|
3751
3755
|
it.installed ? h("span", { className: "dshm-badge" }, lookup("badge.installed")) : null,
|
|
3752
3756
|
it.community === true ? h("span", { className: "dshm-badge info" }, lookup("badge.community")) : null,
|
|
@@ -3843,6 +3847,7 @@ var ZONE_TABS = [
|
|
|
3843
3847
|
{ id: "primary", labelKey: "zone.primary" },
|
|
3844
3848
|
{ id: "favorites", labelKey: "zone.favorites" }
|
|
3845
3849
|
];
|
|
3850
|
+
var verifiedByline = (it) => it.community !== true && Array.isArray(it.verified) && it.verified.length ? { text: lookup("byline.verified", { v: it.verified[it.verified.length - 1] }), title: it.verified.join("\u3001") } : null;
|
|
3846
3851
|
function MarketTab({ notify, markets, onMutation, ops, favorites, profileKind, onOpenOps }) {
|
|
3847
3852
|
const [zone, setZone] = useState("community");
|
|
3848
3853
|
const market = zone === "favorites" ? null : markets[zone];
|
|
@@ -4143,7 +4148,6 @@ function MarketTab({ notify, markets, onMutation, ops, favorites, profileKind, o
|
|
|
4143
4148
|
lookup("op.status.running")
|
|
4144
4149
|
) : null,
|
|
4145
4150
|
it.deprecated === true ? h("span", { className: "dshm-badge warn", key: "dep" }, lookup("badge.deprecated")) : null,
|
|
4146
|
-
it.community !== true && Array.isArray(it.verified) && it.verified.length ? h("span", { className: "dshm-badge", key: "v", title: it.verified.join("\u3001") }, lookup("badge.verified")) : null,
|
|
4147
4151
|
it.audience === "internal" ? h("span", { className: "dshm-badge dshm-badge-internal", key: "internal" }, lookup("badge.internal")) : null,
|
|
4148
4152
|
it.outdated ? h("span", { className: "dshm-badge warn", key: "u" }, lookup("badge.update")) : null,
|
|
4149
4153
|
it.installed ? h("span", { className: "dshm-badge", key: "i" }, lookup("badge.installed")) : null,
|
|
@@ -4155,7 +4159,10 @@ function MarketTab({ notify, markets, onMutation, ops, favorites, profileKind, o
|
|
|
4155
4159
|
it.owner ? { text: `by ${it.owner}` } : null,
|
|
4156
4160
|
typeof it.downloads === "number" ? { text: `${compactCount(it.downloads)} \u2193`, title: String(it.downloads) } : null,
|
|
4157
4161
|
typeof it.stars === "number" ? { text: `${compactCount(it.stars)} \u2605`, title: String(it.stars) } : null
|
|
4158
|
-
].filter(Boolean) :
|
|
4162
|
+
].filter(Boolean) : [
|
|
4163
|
+
...(it.tags || []).map((t) => ({ text: `#${t}` })),
|
|
4164
|
+
verifiedByline(it)
|
|
4165
|
+
].filter(Boolean),
|
|
4159
4166
|
desc: browserLang() === "en" && typeof it.descriptionEn === "string" && it.descriptionEn !== "" ? it.descriptionEn : it.description,
|
|
4160
4167
|
clampLines: it.community === true ? 5 : 2,
|
|
4161
4168
|
sub: [
|
|
@@ -4325,8 +4332,11 @@ function InstalledTab({ notify, installed, updates, onMutation, ops }) {
|
|
|
4325
4332
|
const updateRows = updates && updates.data && Array.isArray(updates.data.updates) ? updates.data.updates : [];
|
|
4326
4333
|
const [openPkg, setOpenPkg] = useState(null);
|
|
4327
4334
|
const [readmePkg, setReadmePkg] = useState(null);
|
|
4335
|
+
const [pendingToggles, setPendingToggles] = useState({});
|
|
4328
4336
|
const activeMutateTarget = (ops.records.find((r) => r.kind !== "install" && (r.status === "running" || r.status === "queued" || r.status === "input")) || {}).target || null;
|
|
4337
|
+
const progressTarget = (ops.records.find((r) => (r.kind === "install" || r.kind === "upgrade" || r.kind === "self-upgrade") && (r.status === "running" || r.status === "queued" || r.status === "input")) || {}).target || null;
|
|
4329
4338
|
const doToggle = async (it, enabled) => {
|
|
4339
|
+
setPendingToggles((m) => ({ ...m, [it.pkg]: enabled }));
|
|
4330
4340
|
const call = () => api("set-enabled", { pkg: it.pkg, enabled });
|
|
4331
4341
|
try {
|
|
4332
4342
|
let res;
|
|
@@ -4340,13 +4350,19 @@ function InstalledTab({ notify, installed, updates, onMutation, ops }) {
|
|
|
4340
4350
|
const note = toggleNoticeKeys2(res);
|
|
4341
4351
|
const extra = res.warnings && res.warnings.length ? `\uFF08${res.warnings.join("\uFF1B")}\uFF09` : "";
|
|
4342
4352
|
notify({ kind: "ok", needsRestart: note.needsRestart, text: lookup(note.textKey, note.params) + extra });
|
|
4343
|
-
await
|
|
4353
|
+
await reload();
|
|
4344
4354
|
} catch (e) {
|
|
4345
4355
|
if (e && e.opSuperseded) {
|
|
4346
4356
|
notify({ kind: "ok", text: lookup("op.superseded.note", { target: it.pkg }) });
|
|
4347
4357
|
} else {
|
|
4348
4358
|
notify({ kind: "err", text: lookup("toggle.failed", { err: e && e.message || e }) });
|
|
4349
4359
|
}
|
|
4360
|
+
} finally {
|
|
4361
|
+
setPendingToggles((m) => {
|
|
4362
|
+
if (!(it.pkg in m)) return m;
|
|
4363
|
+
const { [it.pkg]: _drop, ...rest } = m;
|
|
4364
|
+
return rest;
|
|
4365
|
+
});
|
|
4350
4366
|
}
|
|
4351
4367
|
};
|
|
4352
4368
|
const doUninstall = async (it) => {
|
|
@@ -4427,13 +4443,15 @@ function InstalledTab({ notify, installed, updates, onMutation, ops }) {
|
|
|
4427
4443
|
lookup("installed.upgradeAll", { n: items.filter((x) => x && x.outdated).length })
|
|
4428
4444
|
)
|
|
4429
4445
|
) : null,
|
|
4430
|
-
|
|
4446
|
+
progressTarget ? h(ProgressLine, { key: "prog" }) : null,
|
|
4431
4447
|
h(
|
|
4432
4448
|
"div",
|
|
4433
4449
|
{ className: "dshm-cards" },
|
|
4434
4450
|
items.map((it) => {
|
|
4435
4451
|
const vm = installedViewModel2(it);
|
|
4436
|
-
const
|
|
4452
|
+
const pendingOn = pendingToggles[it.pkg];
|
|
4453
|
+
const tvm0 = toggleViewModel2(it);
|
|
4454
|
+
const tvm = pendingOn === void 0 ? tvm0 : { ...tvm0, switchOn: pendingOn, ...pendingOn === false ? { phaseDotClass: "", phaseLabelKey: null } : {} };
|
|
4437
4455
|
return Card({
|
|
4438
4456
|
key: it.pkg,
|
|
4439
4457
|
icon: h(Icon, { entry: { name: it.name, github: vm.githubRepo, icon: null } }),
|
|
@@ -4450,7 +4468,7 @@ function InstalledTab({ notify, installed, updates, onMutation, ops }) {
|
|
|
4450
4468
|
desc: it.description || "\uFF08\u65E0\u63CF\u8FF0\uFF09",
|
|
4451
4469
|
sub: [
|
|
4452
4470
|
h(PhaseDot, { key: "dot", vm: tvm }),
|
|
4453
|
-
vm.phaseKey ? lookup(vm.phaseKey) : lookup(vm.enabledLabelKey),
|
|
4471
|
+
pendingOn === void 0 ? vm.phaseKey ? lookup(vm.phaseKey) : lookup(vm.enabledLabelKey) : lookup(pendingOn ? "toggle.state.on" : "toggle.state.off"),
|
|
4454
4472
|
`v${it.version || "?"}`,
|
|
4455
4473
|
vm.sourceLabelKey ? lookup(vm.sourceLabelKey) : it.source,
|
|
4456
4474
|
vm.latestIssue ? lookup("installed.check.incomplete") : null
|
|
@@ -4628,17 +4646,10 @@ function SettingsTab({ notify, onRegistryChanged, onForceMarket, opsRecords, onO
|
|
|
4628
4646
|
}),
|
|
4629
4647
|
h("span", { className: "dshm-switch-slider" })
|
|
4630
4648
|
);
|
|
4631
|
-
const communitySwitchRow = h(
|
|
4632
|
-
"div",
|
|
4633
|
-
{ className: "dshm-kvline-row" },
|
|
4634
|
-
h("span", { className: "rl" }, lookup("settings.community.toggle")),
|
|
4635
|
-
communitySwitch
|
|
4636
|
-
);
|
|
4637
4649
|
const communityBody = communityOn === false ? h(
|
|
4638
4650
|
React.Fragment,
|
|
4639
4651
|
null,
|
|
4640
|
-
h("div", { className: "dshm-hint" }, lookup("settings.community.off"))
|
|
4641
|
-
communitySwitchRow
|
|
4652
|
+
h("div", { className: "dshm-hint" }, lookup("settings.community.off"))
|
|
4642
4653
|
) : h(
|
|
4643
4654
|
"div",
|
|
4644
4655
|
{ className: "dshm-kvlines" },
|
|
@@ -4651,17 +4662,16 @@ function SettingsTab({ notify, onRegistryChanged, onForceMarket, opsRecords, onO
|
|
|
4651
4662
|
kvlineRow("settings.community.version", communityLive ? communitySummary.version || "\u2014" : "\u2014"),
|
|
4652
4663
|
kvlineRow("settings.community.route", communityLive ? communitySummary.route || "\u2014" : "\u2014"),
|
|
4653
4664
|
kvlineRow("settings.community.count", communityLive ? lookup("settings.community.count.v", { n: communitySummary.acceptedCount ?? 0, up: communitySummary.upstreamCount ?? "\u2014" }) : "\u2014"),
|
|
4654
|
-
kvlineRow("settings.community.displaced", communityLive ? lookup("settings.community.displaced.v", { n: communitySummary.displaced ?? 0 }) : "\u2014")
|
|
4655
|
-
communitySwitchRow
|
|
4665
|
+
kvlineRow("settings.community.displaced", communityLive ? lookup("settings.community.displaced.v", { n: communitySummary.displaced ?? 0 }) : "\u2014")
|
|
4656
4666
|
);
|
|
4657
4667
|
return h(
|
|
4658
4668
|
"div",
|
|
4659
4669
|
{ className: "dshm-settings-grid" },
|
|
4660
|
-
// ① 社区清单(awesome-dsh-plugin
|
|
4670
|
+
// ① 社区清单(awesome-dsh-plugin):左卡;开关在标题行右侧(位置恒定,2026-10-13 方案A)
|
|
4661
4671
|
h(
|
|
4662
4672
|
"div",
|
|
4663
4673
|
{ className: "dshm-section" },
|
|
4664
|
-
h("div", { className: "dshm-section-title" }, lookup("settings.community")),
|
|
4674
|
+
h("div", { className: "dshm-section-title" }, lookup("settings.community"), communitySwitch),
|
|
4665
4675
|
communityBody,
|
|
4666
4676
|
communitySummary && Array.isArray(communitySummary.errors) && communitySummary.errors.length && communityOn !== false ? h("div", { className: "dshm-err" }, communitySummary.errors.join("\uFF1B")) : null
|
|
4667
4677
|
),
|
|
@@ -4865,10 +4875,10 @@ function FavoriteZone({ favorites, onOpen }) {
|
|
|
4865
4875
|
name: s.name,
|
|
4866
4876
|
badges: [
|
|
4867
4877
|
s.deprecated === true ? h("span", { className: "dshm-badge warn", key: "dep" }, lookup("badge.deprecated")) : null,
|
|
4868
|
-
// 0.9.45 U12(R7 收窄):无 owner = 精选条目——补「精选」身份徽标;
|
|
4878
|
+
// 0.9.45 U12(R7 收窄):无 owner = 精选条目——补「精选」身份徽标;
|
|
4879
|
+
// verified 徽标已移除(2026-10-13 B 方案:卡面只留例外信号,实测信息在详情弹窗「实测版本」行);
|
|
4869
4880
|
// 受众/解耦徽标不进收藏区(DESIGN §2.7 裁决⑤「已装视图与收藏页不打标」),快照仅存字段
|
|
4870
4881
|
s.owner ? h("span", { className: "dshm-badge info", key: "c" }, lookup("badge.community")) : h("span", { className: "dshm-badge", key: "cz" }, lookup("zone.primary")),
|
|
4871
|
-
Array.isArray(s.verified) && s.verified.length && s.community !== true ? h("span", { className: "dshm-badge", key: "v", title: s.verified.join("\u3001") }, lookup("badge.verified")) : null,
|
|
4872
4882
|
h("span", { className: "dshm-badge info", key: "s" }, s.source === "npm" ? "npm" : "github"),
|
|
4873
4883
|
isStale ? h("span", { className: "dshm-badge warn", key: "st" }, lookup("favorites.stalebadge")) : null
|
|
4874
4884
|
],
|
|
@@ -5550,12 +5560,19 @@ function MarketPanel({ onClose }) {
|
|
|
5550
5560
|
}) : null
|
|
5551
5561
|
// 操作记录已整体搬迁至设置 tab 末位通宽卡(0.9.x 布局重构·第二批):底部不再常驻
|
|
5552
5562
|
),
|
|
5553
|
-
toast
|
|
5563
|
+
// toast/横幅 overlay 化(2026-10-13 UX 修复):原先是面板 column flex 的流内子元素,
|
|
5564
|
+
// 出现/消失会压缩 body(flex:1) 造成二次抖动;现挂 absolute 底部浮层(.dshm-banner-stack),
|
|
5565
|
+
// 零布局参与。stack 用 pointer-events:none 放行下层点击,banner 自身恢复 auto。
|
|
5566
|
+
toast || banner ? h(
|
|
5554
5567
|
"div",
|
|
5555
|
-
{ className:
|
|
5556
|
-
h(
|
|
5557
|
-
|
|
5558
|
-
|
|
5568
|
+
{ className: "dshm-banner-stack" },
|
|
5569
|
+
toast ? h(
|
|
5570
|
+
"div",
|
|
5571
|
+
{ className: toast.kind === "err" ? "dshm-banner err" : "dshm-banner" },
|
|
5572
|
+
h("span", { className: `dshm-banner-text${toastScrollCls}`, ref: toastTextRef }, toast.text)
|
|
5573
|
+
) : null,
|
|
5574
|
+
banner ? h(RestartBanner, { note: banner.text, onDone: () => setBanner(null), desktop: banner.desktop === true, onRestarted: reloadPing }) : null
|
|
5575
|
+
) : null
|
|
5559
5576
|
)
|
|
5560
5577
|
);
|
|
5561
5578
|
}
|
|
@@ -5599,8 +5616,17 @@ function MarketIcon() {
|
|
|
5599
5616
|
h("rect", { x: "14", y: "14", width: "7", height: "7", rx: "1", stroke: "currentColor", strokeWidth: "2" })
|
|
5600
5617
|
);
|
|
5601
5618
|
}
|
|
5619
|
+
var dshmSlotsRef = null;
|
|
5620
|
+
var shellTakeover = () => {
|
|
5621
|
+
try {
|
|
5622
|
+
return ((dshmSlotsRef && dshmSlotsRef.entries ? dshmSlotsRef.entries("sidebar.workspaces") : []) || []).some((entry) => (entry.options.priority ?? 0) < 0);
|
|
5623
|
+
} catch {
|
|
5624
|
+
return false;
|
|
5625
|
+
}
|
|
5626
|
+
};
|
|
5602
5627
|
function MarketEntry(props) {
|
|
5603
5628
|
useEffect(() => ensureCss(), []);
|
|
5629
|
+
if (shellTakeover()) return null;
|
|
5604
5630
|
const rail = !(props && props.wide);
|
|
5605
5631
|
return h(
|
|
5606
5632
|
"button",
|
|
@@ -5619,11 +5645,22 @@ function MarketEntry(props) {
|
|
|
5619
5645
|
props && props.wide ? h("span", null, lookup("market.title")) : null
|
|
5620
5646
|
);
|
|
5621
5647
|
}
|
|
5648
|
+
function safeRegister(slots, options, component) {
|
|
5649
|
+
const label = `${options.name}${options.key != null ? `:${options.key}` : options.id != null ? `#${options.id}` : ""}`;
|
|
5650
|
+
try {
|
|
5651
|
+
return slots.register(options, component);
|
|
5652
|
+
} catch (error) {
|
|
5653
|
+
if (!/already has a registration|already has an entry/.test(String(error && error.message || error))) throw error;
|
|
5654
|
+
console.warn(`[dsh-m] slot "${label}" is contested; dsh-m yields it and keeps running`, error);
|
|
5655
|
+
return () => {
|
|
5656
|
+
};
|
|
5657
|
+
}
|
|
5658
|
+
}
|
|
5622
5659
|
function registerSlot(slots, options, component) {
|
|
5623
5660
|
const next = { ...options };
|
|
5624
5661
|
if (next.id == null && next.key != null) next.id = String(next.key);
|
|
5625
5662
|
if (next.key == null && next.id != null) next.key = next.id;
|
|
5626
|
-
return slots
|
|
5663
|
+
return safeRegister(slots, next, component);
|
|
5627
5664
|
}
|
|
5628
5665
|
function ToolCardRow({ it, onInstalled }) {
|
|
5629
5666
|
const [busy, setBusy] = useState(false);
|
|
@@ -5737,6 +5774,7 @@ var inject = ["slots"];
|
|
|
5737
5774
|
function apply(ctx) {
|
|
5738
5775
|
const slots = ctx.slots;
|
|
5739
5776
|
if (!slots) return;
|
|
5777
|
+
dshmSlotsRef = slots;
|
|
5740
5778
|
ctx.effect(() => ensureCss(), "dshm-style");
|
|
5741
5779
|
ctx.inject(["locale"], (c) => {
|
|
5742
5780
|
if (!c.locale || typeof c.locale.register !== "function") return;
|
|
@@ -5751,7 +5789,13 @@ function apply(ctx) {
|
|
|
5751
5789
|
});
|
|
5752
5790
|
slots.inject(
|
|
5753
5791
|
"sidebar.footer.action",
|
|
5754
|
-
() =>
|
|
5792
|
+
() => safeRegister(
|
|
5793
|
+
slots,
|
|
5794
|
+
// 页脚 order 维持正数工具位(9):bot 视图的让位由壳接管哨兵负责(该视图
|
|
5795
|
+
// 下 MarketEntry 整行不渲染),order 只影响官方 harness 页脚的排序——那里
|
|
5796
|
+
// DS Bot 入口(-200)应在本工具行之上。2026-10-13 曾试装深负 order
|
|
5797
|
+
// (-400/-500)让 ds-bot 集群贴底,哨兵上线后该做法只剩 harness 视图副作用
|
|
5798
|
+
// (DS Bot 入口沉底),已回撤(裁定:哨兵管让位,order 管排序,各司其职)。
|
|
5755
5799
|
{ name: "sidebar.footer.action", id: "dshm-market", key: "dshm-market", order: 9, locale: "dshm", label: () => lookup("market.title") },
|
|
5756
5800
|
function DshmMarketEntry(actionProps) {
|
|
5757
5801
|
return h(MarketEntry, actionProps);
|