@mrrisega/dsh-remote 0.6.0-beta.4 → 0.6.0-beta.5
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.
|
@@ -15,11 +15,27 @@
|
|
|
15
15
|
* 1) ≤820px 强制三列轨宽为 0 / 1fr / 0,内容区全宽;侧栏/详情改造成离屏浮层(off-canvas),
|
|
16
16
|
* 顶部放一个小鲸鱼/菜单按钮,点击 = 程序化点击官方 toggle(aria-label 打开/关闭侧边栏),
|
|
17
17
|
* 不复制官方状态,数据属性仍是唯一真源;
|
|
18
|
-
* 2) 设置面板(
|
|
19
|
-
* content 154px 左右并排)→
|
|
18
|
+
* 2) 设置面板(实测挂载在侧栏 .hHd-Xa_settingsArea 子树里的 fixed 弹层;panel 内
|
|
19
|
+
* nav 188px + content 154px 左右并排)→ 手机改为上下堆叠:顶部 tab 行(横向滚动)置顶,
|
|
20
|
+
* 下方内容区全高滚动。fix2:官方模块 CSS 运行期才注入 head(晚于本 <style>),普通规则
|
|
21
|
+
* 被官方同特异性后加载规则覆盖(nav 是 <nav>,圆1 的 div.VOzbGW_nav 从未命中;overlay
|
|
22
|
+
* 被官方 min(800px,84vw) 钉成左靠 328px 抽屉感)→ 本版设置区全部用 [class~=...] 精确类
|
|
23
|
+
* + 几何 !important;并把侧栏/详情浮层的 will-change:transform 去掉(transform 祖先会让
|
|
24
|
+
* 侧栏子树里的 fixed 设置弹层以侧栏为 containing block,被压到 84vw——fix2 设置窄的根因);
|
|
25
|
+
* 顶部 tab 字号 ≤13px、行宽拉满可横向滚动,当前项自动滚入可视;
|
|
20
26
|
* 3) 输入控件字号 ≥16px 防 iOS 聚焦缩放;hero 的工作区/模式座位行允许换行,防 212px 座位
|
|
21
27
|
* 右缘伸出视口(实测 cubgiG_seat right=409 > 390);
|
|
22
|
-
* 4) html/body overflow-x 防护、safe-area inset、触控目标友好;配色只用官方 CSS
|
|
28
|
+
* 4) html/body overflow-x 防护、safe-area inset、触控目标友好;配色只用官方 CSS 变量;
|
|
29
|
+
* 5) 鲸鱼余额挂件(用户另装的第三方 dsh-whale-widget,浮动 .dshwv-root,z-index:9999):
|
|
30
|
+
* fix2 实测它的窄屏“卡左上角盖标题”与“拖不动”均为其自身缺陷的放大:
|
|
31
|
+
* - 拖不动:触屏上 pointer 拖拽被页面滚动抢占(pointercancel,坐标归 0 → 挂件被“瞬移”),
|
|
32
|
+
* 鼠标路径正常 → 适配层在鲸鱼实体像素的 touchstart 上 preventDefault(仅 ≤820),
|
|
33
|
+
* 让浏览器不抢滚动,挂件原生拖拽在手机上恢复;
|
|
34
|
+
* - 默认位置:它把锚点记忆存 localStorage(dshw-pos),一旦曾落在「左+上」就每次载入
|
|
35
|
+
* 盖住左上会话标题 → 适配层在页面解析期(挂件 widget.js 是 defer,晚于本脚本)清掉
|
|
36
|
+
* left+top 陈旧锚点,默认回到右下;再兜底一次“卡左上角”检测(合成鼠标事件走它自己
|
|
37
|
+
* 的拖拽收尾,state/localStorage 由它自洽)。
|
|
38
|
+
* 仅对 ≤820 且锚点命中 left+top 干预;透明区点击/滚动仍穿透,与桌面语义一致。
|
|
23
39
|
*
|
|
24
40
|
* 宿主特征门(防误注入其它 html):
|
|
25
41
|
* - 注入前:content-type 必须 text/html 且含 </head> 且原文含官方标记
|
|
@@ -55,7 +71,10 @@ const STYLE = `
|
|
|
55
71
|
/* 侧栏/详情已移出 grid 流(fixed),唯一在流的中心列须显式落到 1fr 轨道,否则自动放置会被塞进 0px 轨 */
|
|
56
72
|
div.pI_x6G_centerCol, div.dsh-ma-center { grid-column: 2; min-width: 0; width: auto; }
|
|
57
73
|
|
|
58
|
-
/* --- 侧栏 / 详情:离屏浮层(off-canvas),展开态滑入 ---
|
|
74
|
+
/* --- 侧栏 / 详情:离屏浮层(off-canvas),展开态滑入 ---
|
|
75
|
+
注意:不能给浮层设 will-change:transform / 持久 transform —— 官方把设置面板等
|
|
76
|
+
fixed 弹层的 DOM 挂在侧栏子树里,transform 祖先会成为 fixed 的 containing block,
|
|
77
|
+
导致弹层被限制在 84vw 侧栏宽内(实测 328px“抽屉感”,fix2 根因之一)。 */
|
|
59
78
|
div.pI_x6G_sidebarCol, div.dsh-ma-sidebar {
|
|
60
79
|
position: fixed; left: 0; top: 0; bottom: 0; margin: 0;
|
|
61
80
|
width: min(84vw, 340px); max-width: 92vw;
|
|
@@ -64,7 +83,6 @@ const STYLE = `
|
|
|
64
83
|
box-shadow: 0 10px 44px rgba(0,0,0,.26);
|
|
65
84
|
transform: translateX(-103%);
|
|
66
85
|
transition: transform .22s var(--ds-ease-in-out, ease);
|
|
67
|
-
will-change: transform;
|
|
68
86
|
}
|
|
69
87
|
html.dsh-ma-sidebar-open div.pI_x6G_sidebarCol,
|
|
70
88
|
html.dsh-ma-sidebar-open div.dsh-ma-sidebar { transform: none; }
|
|
@@ -77,7 +95,6 @@ const STYLE = `
|
|
|
77
95
|
box-shadow: 0 10px 44px rgba(0,0,0,.26);
|
|
78
96
|
transform: translateX(103%);
|
|
79
97
|
transition: transform .22s var(--ds-ease-in-out, ease);
|
|
80
|
-
will-change: transform;
|
|
81
98
|
}
|
|
82
99
|
html.dsh-ma-details-open div.pI_x6G_detailsCol,
|
|
83
100
|
html.dsh-ma-details-open div.dsh-ma-details { transform: none; }
|
|
@@ -121,38 +138,81 @@ const STYLE = `
|
|
|
121
138
|
div.wSkVaW_heroWorkspaceRow > * { max-width: calc(100vw - 32px); }
|
|
122
139
|
div.wSkVaW_composerStack, div.wSkVaW_composerHero, div.uV2eYG_card { min-width: 0; }
|
|
123
140
|
|
|
124
|
-
/* --- 设置面板(
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
141
|
+
/* --- 设置面板(fix2 硬化版;实测 390×844:官方模块 CSS 运行期注入在适配层之后,
|
|
142
|
+
普通规则会被官方后加载样式覆盖——nav 是 <nav> 而非 div,圆1 的 div.VOzbGW_nav
|
|
143
|
+
从未命中;overlay 被官方宽度 min(800px,84vw) 钉在左侧 328px,呈“抽屉感”。
|
|
144
|
+
故本版全部用 [class~=...] 精确类 + 几何 !important,官方前缀变化则整段静默失效) --- */
|
|
145
|
+
[class~="VOzbGW_overlay"] {
|
|
146
|
+
position: fixed !important;
|
|
147
|
+
inset: 0 !important;
|
|
148
|
+
width: auto !important; max-width: none !important;
|
|
149
|
+
height: auto !important; max-height: none !important;
|
|
150
|
+
margin: 0 !important; padding: 0 !important;
|
|
151
|
+
border-radius: 0 !important;
|
|
152
|
+
box-sizing: border-box;
|
|
153
|
+
justify-content: center; align-items: stretch;
|
|
132
154
|
}
|
|
133
|
-
|
|
155
|
+
[class~="VOzbGW_panel"] {
|
|
134
156
|
box-sizing: border-box;
|
|
135
|
-
width: 100% !important;
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
157
|
+
width: 100% !important; max-width: 100% !important;
|
|
158
|
+
height: 100% !important; max-height: 100% !important;
|
|
159
|
+
margin: 0 !important; border-radius: 0 !important;
|
|
160
|
+
flex-direction: column !important;
|
|
161
|
+
}
|
|
162
|
+
/* 顶部 tab 行:整行铺满,字号调小(≤13px),横向可滚动 */
|
|
163
|
+
[class~="VOzbGW_nav"] {
|
|
164
|
+
box-sizing: border-box;
|
|
165
|
+
flex: none;
|
|
166
|
+
width: 100% !important;
|
|
167
|
+
flex-direction: row !important;
|
|
168
|
+
align-items: center;
|
|
169
|
+
gap: 4px;
|
|
170
|
+
padding: max(4px, env(safe-area-inset-top)) 4px 0;
|
|
171
|
+
overflow: visible;
|
|
139
172
|
}
|
|
140
|
-
|
|
141
|
-
|
|
173
|
+
[class~="VOzbGW_navTitle"] {
|
|
174
|
+
flex: none;
|
|
175
|
+
font-size: 13px !important; line-height: 1.2;
|
|
176
|
+
padding: 0 4px 0 8px;
|
|
177
|
+
white-space: nowrap;
|
|
178
|
+
}
|
|
179
|
+
[class~="VOzbGW_navList"] {
|
|
142
180
|
box-sizing: border-box;
|
|
143
181
|
flex: 1 1 auto; min-width: 0;
|
|
144
182
|
flex-direction: row !important;
|
|
145
|
-
gap:
|
|
146
|
-
|
|
183
|
+
gap: 4px;
|
|
184
|
+
overflow-x: auto; overflow-y: hidden;
|
|
185
|
+
-webkit-overflow-scrolling: touch;
|
|
186
|
+
scrollbar-width: none;
|
|
187
|
+
padding: 0 0 6px;
|
|
147
188
|
}
|
|
148
|
-
|
|
149
|
-
|
|
189
|
+
[class~="VOzbGW_navList"]::-webkit-scrollbar { display: none; }
|
|
190
|
+
[class~="VOzbGW_navCell"] {
|
|
191
|
+
flex: none; min-width: max-content;
|
|
192
|
+
box-sizing: border-box;
|
|
193
|
+
font-size: 13px !important;
|
|
194
|
+
height: 32px !important;
|
|
195
|
+
padding: 0 12px !important;
|
|
150
196
|
}
|
|
151
|
-
|
|
152
|
-
|
|
197
|
+
/* 内容区:全宽拉满,收敛内边距,最大化有效宽度 */
|
|
198
|
+
[class~="VOzbGW_content"] {
|
|
199
|
+
box-sizing: border-box;
|
|
200
|
+
width: 100% !important; max-width: none !important;
|
|
201
|
+
flex: 1 1 auto; min-width: 0; min-height: 0;
|
|
202
|
+
}
|
|
203
|
+
[class~="VOzbGW_header"] {
|
|
204
|
+
box-sizing: border-box;
|
|
205
|
+
flex: none;
|
|
206
|
+
min-height: 40px;
|
|
207
|
+
padding: 6px 8px 4px 14px !important;
|
|
208
|
+
align-items: center;
|
|
209
|
+
}
|
|
210
|
+
[class~="VOzbGW_close"] { width: 32px; height: 32px; }
|
|
211
|
+
[class~="VOzbGW_options"] {
|
|
212
|
+
box-sizing: border-box;
|
|
153
213
|
flex: 1 1 auto; min-height: 0; overflow-y: auto;
|
|
154
214
|
-webkit-overflow-scrolling: touch;
|
|
155
|
-
padding
|
|
215
|
+
padding: 2px 14px calc(14px + env(safe-area-inset-bottom)) !important;
|
|
156
216
|
}
|
|
157
217
|
}
|
|
158
218
|
|
|
@@ -168,6 +228,192 @@ const SCRIPT = `(() => {
|
|
|
168
228
|
HOST_RE.test(document.documentElement.outerHTML.slice(0, 200000)) ||
|
|
169
229
|
!!document.querySelector("[data-shell-overlay], [data-sidebar-collapsed], [data-details-collapsed]");
|
|
170
230
|
|
|
231
|
+
/* —— 鲸鱼余额挂件(dsh-whale-widget,第三方插件的浮动组件)窄屏协同 ——
|
|
232
|
+
若挂件记忆的锚点是「左+上」(实测会盖住左上角会话标题/左上菜单按钮),在页面解析期
|
|
233
|
+
(鲸鱼 widget.js 是 defer 脚本,一定晚于本脚本执行)清掉该陈旧锚点 → 挂件回到自身
|
|
234
|
+
默认右下角。仅窄屏 & 仅命中 left+top 组合,不影响其它自定义位置。 */
|
|
235
|
+
try {
|
|
236
|
+
if (window.innerWidth <= 820 && window.localStorage) {
|
|
237
|
+
const rawPos = window.localStorage.getItem("dshw-pos");
|
|
238
|
+
if (rawPos) {
|
|
239
|
+
const pos = JSON.parse(rawPos);
|
|
240
|
+
if (pos && pos.hAnchor === "left" && pos.vAnchor === "top") {
|
|
241
|
+
window.localStorage.removeItem("dshw-pos");
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
} catch (e3) { /* 私有模式/配额等:忽略 */ }
|
|
246
|
+
|
|
247
|
+
/* ================= 鲸鱼挂件手机辅助(仅 ≤820 生效;挂件类名 .dshwv-* 稳定) ========= */
|
|
248
|
+
let whaleGuardsOn = false;
|
|
249
|
+
let whaleHitMap = null;
|
|
250
|
+
let whaleUnstuckDone = false;
|
|
251
|
+
|
|
252
|
+
const WHALE_IMG = () => document.querySelector(".dshwv-img");
|
|
253
|
+
const WHALE_ROOT = () => document.querySelector(".dshwv-root");
|
|
254
|
+
|
|
255
|
+
/* 命中测试与挂件自身一致:鲸鱼图按 610×610 采样 alpha>10;贴左(镜像)时水平翻转。 */
|
|
256
|
+
function whaleBodyAt(x, y) {
|
|
257
|
+
const img = WHALE_IMG();
|
|
258
|
+
const root = WHALE_ROOT();
|
|
259
|
+
if (!img || !root) return false;
|
|
260
|
+
const flip = root.classList.contains("dshwv-left");
|
|
261
|
+
const r = img.getBoundingClientRect();
|
|
262
|
+
if (!r || r.width <= 0 || r.height <= 0) return false;
|
|
263
|
+
const lx0 = ((x - r.left) / r.width) * 610;
|
|
264
|
+
const ly0 = ((y - r.top) / r.height) * 610;
|
|
265
|
+
if (lx0 < 0 || ly0 < 0 || lx0 >= 610 || ly0 >= 610) return false;
|
|
266
|
+
const key = img.currentSrc || img.src || "";
|
|
267
|
+
if (!whaleHitMap || whaleHitMap.key !== key) {
|
|
268
|
+
if (!img.complete || !img.naturalWidth || img.naturalWidth === 0) return false; /* 图未就绪→不挡 */
|
|
269
|
+
try {
|
|
270
|
+
const cv = document.createElement("canvas");
|
|
271
|
+
cv.width = 610; cv.height = 610;
|
|
272
|
+
const ctx = cv.getContext("2d");
|
|
273
|
+
if (!ctx) return false;
|
|
274
|
+
ctx.drawImage(img, 0, 0, 610, 610);
|
|
275
|
+
whaleHitMap = { key: key, data: ctx.getImageData(0, 0, 610, 610).data };
|
|
276
|
+
} catch (e4) { whaleHitMap = null; return false; }
|
|
277
|
+
}
|
|
278
|
+
const lx = flip ? 610 - lx0 : lx0;
|
|
279
|
+
const ix = Math.min(609, Math.max(0, Math.floor(lx)));
|
|
280
|
+
const iy = Math.min(609, Math.max(0, Math.floor(ly0)));
|
|
281
|
+
return whaleHitMap.data[(iy * 610 + ix) * 4 + 3] > 10;
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
/* 手机上挂件自身拖拽被滚动抢占:触摸点在鲸鱼实体上时浏览器默认滚动 → pointercancel,
|
|
285
|
+
挂件 pointermove 收不到且把它“瞬移”到取消点(实测拖到左上角)。鼠标路径无此问题。
|
|
286
|
+
在 document capture 阶段对鲸鱼实体像素的 touchstart preventDefault → 浏览器不抢滚动,
|
|
287
|
+
挂件原生的 pointer 拖拽在触屏上随之恢复;透明区仍穿透(与桌面一致)。仅窄屏注册。 */
|
|
288
|
+
function onWhaleTouchStart(ev) {
|
|
289
|
+
try {
|
|
290
|
+
if (!NARROW()) return;
|
|
291
|
+
const t = ev.touches && ev.touches[0];
|
|
292
|
+
if (!t) return;
|
|
293
|
+
const tg = ev.target;
|
|
294
|
+
if (tg && tg.closest && tg.closest(".dshwv-menu, .dshwv-menu-btn, .dshwv-bubble")) return;
|
|
295
|
+
if (whaleBodyAt(t.clientX, t.clientY)) ev.preventDefault();
|
|
296
|
+
} catch (e5) { /* 忽略 */ }
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
function whaleHookInit() {
|
|
300
|
+
if (whaleGuardsOn || !NARROW() || !WHALE_ROOT()) return;
|
|
301
|
+
whaleGuardsOn = true;
|
|
302
|
+
try { document.addEventListener("touchstart", onWhaleTouchStart, { capture: true, passive: false }); } catch (e6) {}
|
|
303
|
+
/* 兜底:极端时序下挂件若仍以 (0,0) 卡在左上(如解析期清锚点被竞态错过),settle 完再扶正一次 */
|
|
304
|
+
[1000, 3500].forEach(function (ms) {
|
|
305
|
+
setTimeout(function () { try { whaleUnstickIfStuck(); } catch (e7) {} }, ms);
|
|
306
|
+
});
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
function safeInsetSides() {
|
|
310
|
+
const ins = { right: 0, bottom: 0 };
|
|
311
|
+
try {
|
|
312
|
+
const p = document.createElement("div");
|
|
313
|
+
p.style.cssText = "position:fixed;top:0;left:0;width:10px;height:10px;visibility:hidden;pointer-events:none";
|
|
314
|
+
document.body.appendChild(p);
|
|
315
|
+
p.style.bottom = "env(safe-area-inset-bottom, 0px)";
|
|
316
|
+
p.style.top = "auto"; p.style.left = "0px"; p.style.right = "auto";
|
|
317
|
+
let r = p.getBoundingClientRect();
|
|
318
|
+
ins.bottom = Math.max(0, Math.round(window.innerHeight - r.top - 10));
|
|
319
|
+
p.style.bottom = "auto"; p.style.top = "0px";
|
|
320
|
+
p.style.right = "env(safe-area-inset-right, 0px)"; p.style.left = "auto";
|
|
321
|
+
r = p.getBoundingClientRect();
|
|
322
|
+
ins.right = Math.max(0, Math.round(window.innerWidth - r.left - 10));
|
|
323
|
+
p.remove();
|
|
324
|
+
} catch (e8) { /* 忽略 */ }
|
|
325
|
+
return ins;
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
function whaleBodyPoint() {
|
|
329
|
+
const img = WHALE_IMG();
|
|
330
|
+
if (!img) return null;
|
|
331
|
+
const r = img.getBoundingClientRect();
|
|
332
|
+
if (!r || r.width <= 0 || r.height <= 0) return null;
|
|
333
|
+
const cands = [[0.5, 0.5], [0.62, 0.64], [0.5, 0.72], [0.72, 0.6], [0.35, 0.58], [0.8, 0.68]];
|
|
334
|
+
for (let i = 0; i < cands.length; i++) {
|
|
335
|
+
const x = r.left + cands[i][0] * r.width;
|
|
336
|
+
const y = r.top + cands[i][1] * r.height;
|
|
337
|
+
if (whaleBodyAt(x, y)) return { x: Math.round(x), y: Math.round(y) };
|
|
338
|
+
}
|
|
339
|
+
return { x: Math.round(r.left + r.width * 0.62), y: Math.round(r.top + r.height * 0.66) };
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
function dispatchWhalePointer(type, x, y) {
|
|
343
|
+
try {
|
|
344
|
+
document.dispatchEvent(new PointerEvent(type, {
|
|
345
|
+
bubbles: true, cancelable: true, composed: true, pointerType: "mouse",
|
|
346
|
+
pointerId: 61001, isPrimary: true,
|
|
347
|
+
button: type === "pointerup" ? -1 : 0,
|
|
348
|
+
buttons: type === "pointerup" ? 0 : 1,
|
|
349
|
+
clientX: x, clientY: y
|
|
350
|
+
}));
|
|
351
|
+
} catch (e9) { /* 不支持 PointerEvent 的环境:跳过 */ }
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
/* 走挂件自己(鼠标路径)的拖拽把它送回右下:state/localStorage 全部由挂件收尾,我们只发合成事件。 */
|
|
355
|
+
function whaleNativeDragToBottomRight() {
|
|
356
|
+
const root = WHALE_ROOT();
|
|
357
|
+
if (!root || root.classList.contains("dshwv-dragging")) return false;
|
|
358
|
+
const start = whaleBodyPoint();
|
|
359
|
+
if (!start) return false;
|
|
360
|
+
const rect = root.getBoundingClientRect();
|
|
361
|
+
const w = rect.width || 122;
|
|
362
|
+
const h = rect.height || 122;
|
|
363
|
+
const ins = safeInsetSides();
|
|
364
|
+
const cx = window.innerWidth - w / 2 - Math.max(ins.right, 10);
|
|
365
|
+
const cy = window.innerHeight - h / 2 - Math.max(ins.bottom, 10);
|
|
366
|
+
if (cx < 0 || cy < 0 || cx < window.innerWidth * 0.5 || cy < window.innerHeight * 0.5) return false;
|
|
367
|
+
dispatchWhalePointer("pointerdown", start.x, start.y);
|
|
368
|
+
let started = false;
|
|
369
|
+
try { started = root.classList.contains("dshwv-dragging"); } catch (e10) {}
|
|
370
|
+
if (!started) { try { dispatchWhalePointer("pointerup", start.x, start.y); } catch (e11) {} return false; }
|
|
371
|
+
const N = 14;
|
|
372
|
+
for (let i = 1; i <= N; i++) {
|
|
373
|
+
const x = Math.round(start.x + ((cx - start.x) * i) / N);
|
|
374
|
+
const y = Math.round(start.y + ((cy - start.y) * i) / N);
|
|
375
|
+
dispatchWhalePointer("pointermove", x, y);
|
|
376
|
+
}
|
|
377
|
+
dispatchWhalePointer("pointerup", cx, cy);
|
|
378
|
+
return true;
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
function whaleUnstickIfStuck() {
|
|
382
|
+
if (!NARROW() || whaleUnstuckDone) return;
|
|
383
|
+
const root = WHALE_ROOT();
|
|
384
|
+
if (!root || root.classList.contains("dshwv-dragging")) return;
|
|
385
|
+
const rect = root.getBoundingClientRect();
|
|
386
|
+
if (rect.top > 20 || rect.left > 20) return; /* 只扶“真卡左上角”的,用户自己放的位置不动 */
|
|
387
|
+
whaleUnstuckDone = true;
|
|
388
|
+
try { if (window.localStorage) window.localStorage.removeItem("dshw-pos"); } catch (e12) {}
|
|
389
|
+
whaleNativeDragToBottomRight();
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
/* 设置面板打开时,把当前 tab 滚进横向可视区(顶部 tab 行手机横向滚动) */
|
|
393
|
+
let settingsWatchOn = false;
|
|
394
|
+
let settingsTick = 0;
|
|
395
|
+
function scrollActiveSettingsTab() {
|
|
396
|
+
const act = document.querySelector(
|
|
397
|
+
'[class~="VOzbGW_navCell"].VOzbGW_active, [class~="VOzbGW_navCell"][aria-current="true"]'
|
|
398
|
+
);
|
|
399
|
+
if (act && act.scrollIntoView) {
|
|
400
|
+
try { act.scrollIntoView({ block: "nearest", inline: "nearest" }); } catch (e13) {
|
|
401
|
+
try { act.scrollIntoView(); } catch (e14) {}
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
function watchSettings() {
|
|
406
|
+
if (settingsWatchOn || !NARROW()) return;
|
|
407
|
+
settingsWatchOn = true;
|
|
408
|
+
try {
|
|
409
|
+
const ob = new MutationObserver(function () {
|
|
410
|
+
clearTimeout(settingsTick);
|
|
411
|
+
settingsTick = setTimeout(function () { if (NARROW()) scrollActiveSettingsTab(); }, 140);
|
|
412
|
+
});
|
|
413
|
+
ob.observe(document.body, { childList: true, subtree: true });
|
|
414
|
+
} catch (e15) {}
|
|
415
|
+
}
|
|
416
|
+
|
|
171
417
|
let done = false;
|
|
172
418
|
const boot = () => {
|
|
173
419
|
if (done || !NARROW() || !HOSTISH()) return;
|
|
@@ -231,11 +477,15 @@ const SCRIPT = `(() => {
|
|
|
231
477
|
new MutationObserver(sync).observe(frame, { attributes: true, attributeFilter: ["data-sidebar-collapsed", "data-details-collapsed"] });
|
|
232
478
|
} catch (e2) { /* 退化:仅在下次 boot 同步 */ }
|
|
233
479
|
sync();
|
|
480
|
+
whaleHookInit();
|
|
481
|
+
watchSettings();
|
|
234
482
|
};
|
|
235
483
|
|
|
236
484
|
if (document.readyState === "loading") document.addEventListener("DOMContentLoaded", boot); else boot();
|
|
237
|
-
/* 官方模块系统异步挂载 UI,晚一点再补几次(幂等,done 守卫) */
|
|
238
|
-
[700, 1600, 3200, 7000, 12000].forEach((ms) =>
|
|
485
|
+
/* 官方模块系统异步挂载 UI,晚一点再补几次(幂等,done 守卫);同时等鲸鱼/设置弹层就位 */
|
|
486
|
+
[700, 1600, 3200, 7000, 12000].forEach((ms) =>
|
|
487
|
+
setTimeout(() => { try { boot(); whaleHookInit(); watchSettings(); } catch (e) { /* 幂等重试 */ } }, ms)
|
|
488
|
+
);
|
|
239
489
|
} catch (e) { if (window.console) console.warn("[dsh-mobile-adapter]", e && e.message); }
|
|
240
490
|
})();`;
|
|
241
491
|
|
|
@@ -100,3 +100,25 @@ test("maybeInjectMobileAdapter:非 html / 空 body / 非 UTF-8 原样", () => {
|
|
|
100
100
|
test("适配层文本不含口令类敏感标记(仅结构提示)", () => {
|
|
101
101
|
assert.ok(!/password|secret|token\s*=/i.test(mod.ADAPTER_TAG + "")); // ADAPTER_TAG 只是 id 常量
|
|
102
102
|
});
|
|
103
|
+
|
|
104
|
+
test("fix2:设置区用精确类+小字号,浮层不再持久 will-change,鲸鱼协同 JS 载荷存在", () => {
|
|
105
|
+
const r = injectMobileAdapter(OFFICIAL_HTML);
|
|
106
|
+
const css = r.html.slice(r.html.indexOf('<style id="dsh-mobile-adapter-css"'), r.html.indexOf("</style>"));
|
|
107
|
+
const js = r.html.slice(r.html.indexOf('<script id="dsh-mobile-adapter-js"'));
|
|
108
|
+
// 设置面板:全屏/精确类/顶部 tab 字号 ≤13px/内容拉满
|
|
109
|
+
assert.match(css, /\[class~="VOzbGW_overlay"\]/);
|
|
110
|
+
assert.match(css, /\[class~="VOzbGW_panel"\]/);
|
|
111
|
+
assert.match(css, /\[class~="VOzbGW_navCell"\]/);
|
|
112
|
+
assert.match(css, /font-size:\s*13px\s*!important/);
|
|
113
|
+
assert.match(css, /\[class~="VOzbGW_options"\]/);
|
|
114
|
+
// 浮层规则不应再携带会被 fixed 弹层当作 containing block 的持久 will-change(见文件注释)
|
|
115
|
+
assert.ok(!/(^|})\s*will-change:\s*transform\s*;/m.test(css), "CSS 规则不应再有 will-change: transform 声明(注释里的字样不算)");
|
|
116
|
+
// 鲸鱼挂件(dsh-whale-widget)窄屏协同载荷:锚点清理 + touch 拖动护栏 + 卡左上兜底
|
|
117
|
+
assert.match(js, /dshw-pos/);
|
|
118
|
+
assert.match(js, /\.dshwv-root/);
|
|
119
|
+
assert.match(js, /touchstart/);
|
|
120
|
+
assert.match(js, /whaleUnstickIfStuck|whaleNativeDragToBottomRight/);
|
|
121
|
+
// 上述 CSS/JS 都只能落在 ≤820px 运行时:CSS 规则整体在 media 内;JS 执行由 NARROW() 把关
|
|
122
|
+
assert.ok(css.indexOf("@media (max-width: 820px)") !== -1);
|
|
123
|
+
assert.match(js, /NARROW\s*=\s*\(\)\s*=>\s*window\.innerWidth\s*<=\s*820/);
|
|
124
|
+
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mrrisega/dsh-remote",
|
|
3
|
-
"version": "0.6.0-beta.
|
|
3
|
+
"version": "0.6.0-beta.5",
|
|
4
4
|
"description": "手机远程控制 DeepSeek Harness · Remote control DeepSeek Harness (dsh web) from any phone browser — 100% 全功能 App 级体验:发消息、看工具执行、审批权限、改设置、管凭据,含特权操作,免内网穿透。一条命令安装 npx @mrrisega/dsh-remote。Mobile remote control for DSH, self-host or SaaS, no server needed on LAN.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"deepseek-harness",
|
|
@@ -946,7 +946,7 @@ const PLUGIN_ID = "dsh-remote-web";
|
|
|
946
946
|
const PLUGIN_LEGACY_IDS = ["dsh-remote-ui"];
|
|
947
947
|
const PLUGIN_ALL_IDS = [PLUGIN_ID, ...PLUGIN_LEGACY_IDS];
|
|
948
948
|
/** 插件自身发布版本(与 dsh-remote 根包同步递增)。 */
|
|
949
|
-
const PLUGIN_VERSION = "0.6.0-beta.
|
|
949
|
+
const PLUGIN_VERSION = "0.6.0-beta.5";
|
|
950
950
|
const UPDATE_LOG = ".dsh-update.log";
|
|
951
951
|
const UPDATE_MARKER = ".dsh-update-running";
|
|
952
952
|
|