dsh-mpkg-wallpaper 3.15.6 → 3.15.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/lib/client.js +83 -7
- package/package.json +1 -1
package/lib/client.js
CHANGED
|
@@ -1479,6 +1479,17 @@ function sectionSigNow() {
|
|
|
1479
1479
|
} catch (e) {}
|
|
1480
1480
|
return "";
|
|
1481
1481
|
}
|
|
1482
|
+
/* ②(2026-10-05 真机残留复核) `sceneKey` 是**粘性源字段**之一:换档/自愈之后它可能还挂着
|
|
1483
|
+
上一个场景的值(真机现场:`converted="mp4"` 的 mpkg 档里仍留着 `scene|probe|…/scene.pkg`)。
|
|
1484
|
+
今天它无害(挂载只在 `converted === "scene"` 时看它),但它是"哪天被别的分支读到就翻盘"的
|
|
1485
|
+
典型地雷 ⇒ 自愈写回时**显式删掉**(`null` 是唯一会被 sticky 护栏尊重的删除语义)。 */
|
|
1486
|
+
function mpwStripForeignSceneKey(sec) {
|
|
1487
|
+
try {
|
|
1488
|
+
const out = Object.assign({}, sec || {});
|
|
1489
|
+
if (String(out.converted || "") !== "scene" && out.sceneKey) out.sceneKey = null;
|
|
1490
|
+
return out;
|
|
1491
|
+
} catch (e) { return sec }
|
|
1492
|
+
}
|
|
1482
1493
|
/** 档里是不是"只剩 image token、身份/类型全空"(真机那条半残档的形状)。 */
|
|
1483
1494
|
function mpwIdentityMissing(s) {
|
|
1484
1495
|
try {
|
|
@@ -2553,7 +2564,7 @@ function mpwThumbFail(el, why) {
|
|
|
2553
2564
|
if (MPW_HEAL.last && MPW_HEAL.last.ok && MPW_HEAL.last.key === key && mpwVal(cur, "image") !== void 0) return false;
|
|
2554
2565
|
const bak = mpwBackupSrc();
|
|
2555
2566
|
if (bak && MPW_SRC_KEYS.some((sk) => typeof bak[sk] === "string" && bak[sk])) {
|
|
2556
|
-
const next = mpwMergeSection(cur, bak);
|
|
2567
|
+
const next = mpwStripForeignSceneKey(mpwMergeSection(cur, bak));
|
|
2557
2568
|
writeSection(next, true);
|
|
2558
2569
|
changed = true;
|
|
2559
2570
|
MPW_HEAL.attempted++;
|
|
@@ -2573,7 +2584,7 @@ function mpwThumbFail(el, why) {
|
|
|
2573
2584
|
try { nowKey = String(readSection().mpkgKey || "") } catch {}
|
|
2574
2585
|
if (nowKey !== key) { try { console.warn("[dsh-mpkg-wallpaper] 自愈完成时壁纸已切换,丢弃迟到结果:", key); } catch {} return }
|
|
2575
2586
|
if (found) {
|
|
2576
|
-
writeSection(mpwMergeSection(readSection(), found), true);
|
|
2587
|
+
writeSection(mpwStripForeignSceneKey(mpwMergeSection(readSection(), found)), true);
|
|
2577
2588
|
MPW_HEAL.healed++;
|
|
2578
2589
|
MPW_HEAL.last = { key, ok: true, from: "derive", at: Date.now() };
|
|
2579
2590
|
mpwTrace("settings:heal", { key, from: "derive" });
|
|
@@ -11811,6 +11822,7 @@ function mpwThumbFail(el, why) {
|
|
|
11811
11822
|
keyFromImageToken: (img) => mpwKeyFromImageToken(img),
|
|
11812
11823
|
healState: () => { try { return Object.assign({}, MPW_HEAL) } catch (e) { return {} } },
|
|
11813
11824
|
identityMissing: (s) => mpwIdentityMissing(s || readSection()),
|
|
11825
|
+
stripForeignSceneKey: (s) => mpwStripForeignSceneKey(s || readSection()),
|
|
11814
11826
|
deriveFromKey: (key) => mpwDeriveSourceFromKey(key || readSection().mpkgKey),
|
|
11815
11827
|
heal: () => { try { return mpwHealHalfArchive() } catch (e) { return String(e && e.message || e) } },
|
|
11816
11828
|
healState: () => Object.assign({}, MPW_HEAL, { last: MPW_HEAL.last ? Object.assign({}, MPW_HEAL.last) : null, sig: mpwHealSig }),
|
|
@@ -18102,6 +18114,10 @@ ${popSurfaceSel} {
|
|
|
18102
18114
|
有宿主玻璃的弹层(标题栏子代理展开框 / VS Code 菜单 / 模型选择…)一个像素都不动。
|
|
18103
18115
|
独立 token:--mpw-pop-surface(-dark)(不再共用面板表面 token --mpw-surface-pop)。 */
|
|
18104
18116
|
html body [data-mpw-pop-bg] { background-color: var(--mpw-pop-surface) !important; }
|
|
18117
|
+
/* ②(2026-10-05) 弹层处在一个"自己有底的玻璃祖先"里面(backdrop root 被截断 ⇒ 我们糊不到页面背后):
|
|
18118
|
+
与其"半透明却没模糊"(真机被读成"只有白色滤镜"),不如**做实在**——表面不透明度抬到 88%,
|
|
18119
|
+
并把 backdrop-filter 撤掉(白算一遍)。注意:只动我们自己的标记属性,宿主元素一个都不碰。 */
|
|
18120
|
+
html body [data-mpw-pop-trunc] { background-color: color-mix(in srgb, var(--dsw-specific-sidebar-fill) 88%, transparent) !important; backdrop-filter: none !important; -webkit-backdrop-filter: none !important; }
|
|
18105
18121
|
html body[data-ds-dark-theme] [data-mpw-pop-bg] { background-color: var(--mpw-pop-surface-dark) !important; }
|
|
18106
18122
|
[role="menu"] [class*="card"],
|
|
18107
18123
|
[role="tooltip"] [class*="card"] {
|
|
@@ -24666,11 +24682,37 @@ body[data-mpw-modal] [role="dialog"] {
|
|
|
24666
24682
|
getAnimations 只读动画表、不触发布局,闸门本身廉价。 */
|
|
24667
24683
|
let mpwHeavyRecheckTimer = 0;
|
|
24668
24684
|
const mpwHeavyPending = new Map();
|
|
24685
|
+
/* ②(2026-10-05 真机回归修复) 闸门的判据必须是"**真的在跑、而且会跑完**的动画":
|
|
24686
|
+
旧写法 `document.getAnimations().length > 0` 把**任何**留在动画表里的条目都算成"在动画",
|
|
24687
|
+
包括 `playState === 'finished'`(CSS 动画带 fill: forwards 会一直留着)与
|
|
24688
|
+
`iterations === Infinity`(光标闪烁/转圈这类**永不结束**的动画)⇒ 真机上只要页面里有
|
|
24689
|
+
一个循环动画,闸门就**永久**登记、永不放行 ⇒ 弹层兜底底标记/右栏最外层标记/侧栏抑制
|
|
24690
|
+
这些活全被饿死(真机读数:四个弹层都不再带 data-mpw-pop-bg,只剩宿主自己的不透明白底
|
|
24691
|
+
+ 我们的 blur = "白色滤镜、没有玻璃")。
|
|
24692
|
+
现在:① 只认 `running`;② 跳过无限循环动画(它们不会结束,不能拿它们当"稍后再跑"的理由);
|
|
24693
|
+
③ 兜底——连续推迟超过 MPW_HEAVY_MAX_DEFER 次就**无条件放行一次**(宁可多跑一次重活,
|
|
24694
|
+
也不能让功能被永久饿死)。 */
|
|
24695
|
+
const MPW_HEAVY_MAX_DEFER = 3;
|
|
24696
|
+
let mpwHeavyDeferStreak = 0;
|
|
24669
24697
|
function mpwHeavyAnimRunning() {
|
|
24670
|
-
try {
|
|
24698
|
+
try {
|
|
24699
|
+
if (!document.getAnimations) return false;
|
|
24700
|
+
const list = document.getAnimations();
|
|
24701
|
+
for (const a of list) {
|
|
24702
|
+
try {
|
|
24703
|
+
if (!a || a.playState !== "running") continue; // finished/paused/idle 一律不算
|
|
24704
|
+
const t = a.effect && a.effect.getTiming ? a.effect.getTiming() : null;
|
|
24705
|
+
if (t && t.iterations === Infinity) continue; // 永不结束的循环动画:不能当等待理由
|
|
24706
|
+
return true;
|
|
24707
|
+
} catch (e) { /* 单个动画读不到就跳过它 */ }
|
|
24708
|
+
}
|
|
24709
|
+
return false;
|
|
24710
|
+
} catch (e) { return false }
|
|
24671
24711
|
}
|
|
24672
24712
|
function mpwHeavyGate(name, fn) {
|
|
24673
|
-
if (!mpwHeavyAnimRunning()) return true;
|
|
24713
|
+
if (!mpwHeavyAnimRunning()) { mpwHeavyDeferStreak = 0; return true; }
|
|
24714
|
+
if (mpwHeavyDeferStreak >= MPW_HEAVY_MAX_DEFER) { mpwHeavyDeferStreak = 0; return true; }
|
|
24715
|
+
mpwHeavyDeferStreak++;
|
|
24674
24716
|
mpwHeavyPending.set(name, fn);
|
|
24675
24717
|
if (!mpwHeavyRecheckTimer) {
|
|
24676
24718
|
mpwHeavyRecheckTimer = setTimeout(() => {
|
|
@@ -24949,24 +24991,39 @@ body[data-mpw-modal] [role="dialog"] {
|
|
|
24949
24991
|
try {
|
|
24950
24992
|
const surfaces = document.querySelectorAll("[data-mpw-pop-bg]");
|
|
24951
24993
|
const targets = new Set();
|
|
24994
|
+
const truncated = new Set();
|
|
24952
24995
|
for (let i = 0; i < surfaces.length; i++) {
|
|
24953
24996
|
const el = surfaces[i];
|
|
24954
24997
|
let cs = null;
|
|
24955
24998
|
try { cs = getComputedStyle(el) } catch (e) {}
|
|
24956
24999
|
/* 硬前提(与 mpwTagPopoverBg 同口径):我们真的给了模糊才值得摘祖先的截断 */
|
|
24957
25000
|
if (!cs || !cs.backdropFilter || String(cs.backdropFilter).indexOf("blur") < 0) continue;
|
|
25001
|
+
let blockedByGlass = false;
|
|
24958
25002
|
for (let p = el.parentElement, n = 0; p && p !== document.body && p !== document.documentElement && n < 12; p = p.parentElement, n++) {
|
|
24959
25003
|
let acs = null;
|
|
24960
25004
|
try { acs = getComputedStyle(p) } catch (e) { break }
|
|
24961
|
-
|
|
25005
|
+
const ablur = acs && acs.backdropFilter && acs.backdropFilter !== "none" && String(acs.backdropFilter).indexOf("blur") >= 0;
|
|
25006
|
+
if (!ablur) continue;
|
|
25007
|
+
/* ②(2026-10-05 真机回归) **祖先自己是"看得见的玻璃板"时绝不动它**:
|
|
25008
|
+
它是用户能看到的那层模糊(真机现场:子代理展开框/输入框卡片被我们摘掉 blur 之后
|
|
25009
|
+
"模糊背景没有了"——正是之前夸过的那处效果)。判据 = 它有可见底色(α ≥ 0.05)。
|
|
25010
|
+
这种情况下改为把**弹层自己的表面做实在**(不能糊到页面背后,就别假装是玻璃)。 */
|
|
25011
|
+
if (mpwColorAlpha(acs.backgroundColor) >= 0.05) { blockedByGlass = true; break }
|
|
25012
|
+
targets.add(p);
|
|
25013
|
+
break;
|
|
24962
25014
|
}
|
|
25015
|
+
if (blockedByGlass) truncated.add(el);
|
|
24963
25016
|
}
|
|
24964
25017
|
const stale = document.querySelectorAll("[data-mpw-pop-untrunc]");
|
|
24965
25018
|
for (let i = 0; i < stale.length; i++) { const el = stale[i]; if (!targets.has(el)) { try { el.removeAttribute("data-mpw-pop-untrunc") } catch (e) {} } }
|
|
24966
25019
|
for (const el of targets) { if (!el.hasAttribute("data-mpw-pop-untrunc")) { try { el.setAttribute("data-mpw-pop-untrunc", "") } catch (e) {} } }
|
|
25020
|
+
/* 被"有底的玻璃祖先"挡住的那批:标记在**弹层自己**身上(绝不碰宿主元素),由 CSS 给实底 */
|
|
25021
|
+
const staleT = document.querySelectorAll("[data-mpw-pop-trunc]");
|
|
25022
|
+
for (let i = 0; i < staleT.length; i++) { const el = staleT[i]; if (!truncated.has(el)) { try { el.removeAttribute("data-mpw-pop-trunc") } catch (e) {} } }
|
|
25023
|
+
for (const el of truncated) { if (!el.hasAttribute("data-mpw-pop-trunc")) { try { el.setAttribute("data-mpw-pop-trunc", "") } catch (e) {} } }
|
|
24967
25024
|
if (targets.size) mpwPopUntruncStyle();
|
|
24968
25025
|
else if (popUntruncStyleEl && popUntruncStyleEl.parentElement) { try { popUntruncStyleEl.remove() } catch (e) {} popUntruncStyleEl = null; }
|
|
24969
|
-
return targets.size;
|
|
25026
|
+
return targets.size + truncated.size * 1000; // 千位段 = 被"有底玻璃祖先"挡住、改为实底的弹层数
|
|
24970
25027
|
} catch (e) { return 0 }
|
|
24971
25028
|
}
|
|
24972
25029
|
/* ①(P3) 判据出口(tools/popover-untrunc-test.mjs 直接调 sync 断言 打标/还原/硬前提/首截断者)。 */
|
|
@@ -24977,6 +25034,24 @@ body[data-mpw-modal] [role="dialog"] {
|
|
|
24977
25034
|
};
|
|
24978
25035
|
} catch (e) {}
|
|
24979
25036
|
|
|
25037
|
+
/* ②(2026-10-05) 探针/判据出口:弹层兜底底标记与"摘截断"两件事可被**手动触发并读回**——
|
|
25038
|
+
真机排障要能区分"根本没跑"(调度被饿死、observer 没接上)与"跑了但条件不满足"(宿主
|
|
25039
|
+
自己画了不透明白底/面积超阈值…)。只读+幂等,不改变任何语义。 */
|
|
25040
|
+
try {
|
|
25041
|
+
globalThis.__mpwPopTagTest = {
|
|
25042
|
+
run: () => { try { return mpwTagPopoverBg() } catch (e) { return -1 } },
|
|
25043
|
+
untrunc: () => { try { return mpwPopUntruncSync() } catch (e) { return -1 } },
|
|
25044
|
+
state: (sel) => {
|
|
25045
|
+
try {
|
|
25046
|
+
const el = document.querySelector(sel || "[data-mpw-pop-bg]");
|
|
25047
|
+
if (!el) return null;
|
|
25048
|
+
const cs = getComputedStyle(el);
|
|
25049
|
+
return { cls: String(el.className).slice(0, 60), tag: el.hasAttribute("data-mpw-pop-bg"), bg: cs.backgroundColor, bf: cs.backdropFilter, display: cs.display, vis: cs.visibility };
|
|
25050
|
+
} catch (e) { return null }
|
|
25051
|
+
},
|
|
25052
|
+
};
|
|
25053
|
+
} catch (e) {}
|
|
25054
|
+
|
|
24980
25055
|
function setupPopTagWatch() {
|
|
24981
25056
|
if (popTagWatch !== null) return;
|
|
24982
25057
|
let praf = 0;
|
|
@@ -25069,7 +25144,8 @@ body[data-mpw-modal] [role="dialog"] {
|
|
|
25069
25144
|
动画停 ⇒ 补跑执行、账目清空)。 */
|
|
25070
25145
|
try {
|
|
25071
25146
|
globalThis.__mpwHeavyTest = {
|
|
25072
|
-
state: () => ({ pending: Array.from(mpwHeavyPending.keys()), timer: !!mpwHeavyRecheckTimer }),
|
|
25147
|
+
state: () => ({ pending: Array.from(mpwHeavyPending.keys()), timer: !!mpwHeavyRecheckTimer, streak: mpwHeavyDeferStreak }),
|
|
25148
|
+
animRunning: () => mpwHeavyAnimRunning(),
|
|
25073
25149
|
gate: (name, fn) => mpwHeavyGate(name, fn),
|
|
25074
25150
|
flushNow: () => {
|
|
25075
25151
|
if (mpwHeavyRecheckTimer) { try { clearTimeout(mpwHeavyRecheckTimer) } catch (e) {} mpwHeavyRecheckTimer = 0; }
|
package/package.json
CHANGED