@mrrisega/dsh-remote 0.6.0-beta.9 → 0.6.0
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/README.md +10 -3
- package/clients/dsh-remote/dsh-bridge.mjs +30 -0
- package/clients/dsh-remote/e2ee-client.mjs +17 -0
- package/clients/dsh-remote/e2ee-shim-script.js +43 -3
- package/clients/dsh-remote/e2ee-shim.mjs +5 -0
- package/clients/dsh-remote/mobile-adapter.mjs +56 -2
- package/clients/dsh-remote/test/e2ee-client.test.mjs +13 -0
- package/package.json +1 -1
- package/packages/dsh-remote-web/lib/client.js +322 -187
- package/packages/dsh-remote-web/lib/index.js +46 -7
- package/packages/dsh-remote-web/test/feedback-proxy.test.mjs +2 -1
- package/packages/dsh-remote-web/test/password-reset.test.mjs +430 -0
- package/packages/dsh-remote-web/test/remote-access-ui.test.mjs +1 -1
- package/packages/dsh-remote-web/test/settings-entry.test.mjs +43 -61
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// dsh-remote-web 浏览器半回归(2026-09 前名 dsh-remote-ui):面板入口迁移进「设置」页 settings.section 官方扩展点。
|
|
2
|
-
// 覆盖:栏目注册(id/order/label
|
|
3
|
-
//
|
|
2
|
+
// 覆盖:栏目注册(id/order/label)、侧边栏入口与浮动面板移除(不再向官方侧栏注入任何按钮/点击机器)、
|
|
3
|
+
// 账号区无「切换账号」、「关于 dsh-remote」说明卡片、退出登录/切换连接账号清理反馈线程凭据、首次安装红点引导。
|
|
4
4
|
import assert from "node:assert/strict";
|
|
5
5
|
import { readFileSync } from "node:fs";
|
|
6
6
|
import test from "node:test";
|
|
@@ -98,7 +98,6 @@ function loadPlugin(opts = {}) {
|
|
|
98
98
|
},
|
|
99
99
|
querySelectorAll(sel) {
|
|
100
100
|
if (sel === "button") return opts.navCells || [];
|
|
101
|
-
if (typeof opts.navQuery === "function") return opts.navQuery(sel);
|
|
102
101
|
return [];
|
|
103
102
|
},
|
|
104
103
|
};
|
|
@@ -158,7 +157,6 @@ function loadPlugin(opts = {}) {
|
|
|
158
157
|
return {
|
|
159
158
|
registered, metas, injects, requests, removed, states, localStorage,
|
|
160
159
|
intervals,
|
|
161
|
-
navWindow: sandbox.window,
|
|
162
160
|
lastObserver: () => lastObserver,
|
|
163
161
|
renderSection() { hook = 0; return registered.get("dsh-remote")({ close() {} }); },
|
|
164
162
|
};
|
|
@@ -284,59 +282,50 @@ test("红点已看过(localStorage 有 key)时不注入,重启 DSH Web 不
|
|
|
284
282
|
assert.equal(navCell.children.length, 0, "已看过时不应再注入红点");
|
|
285
283
|
});
|
|
286
284
|
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
_attrs: {},
|
|
297
|
-
_clicked: 0,
|
|
298
|
-
getAttribute(k) { return k in this._attrs ? this._attrs[k] : null; },
|
|
299
|
-
setAttribute(k, v) { this._attrs[k] = String(v); },
|
|
300
|
-
click() { this._clicked++; },
|
|
301
|
-
};
|
|
302
|
-
if (aria) node._attrs["aria-label"] = aria;
|
|
303
|
-
if (role) node._attrs.role = role;
|
|
304
|
-
return node;
|
|
305
|
-
}
|
|
285
|
+
test("红点只挂在设置页「远程访问」栏目导航(navCell):普通按钮即使文本含「远程访问」也不注入,不遮挡官方入口", () => {
|
|
286
|
+
const navCells = [];
|
|
287
|
+
const officialCell = makeEl("button");
|
|
288
|
+
officialCell.className = "VOzbGW_navCell"; // shell hashed 类名(含 navCell 子串)=设置页栏目导航
|
|
289
|
+
officialCell.textContent = "📱 远程访问";
|
|
290
|
+
const plainBtn = makeEl("button");
|
|
291
|
+
plainBtn.className = "some-other-btn"; // 非 navCell(官方侧栏/内容区按钮):即使含「远程访问」也不得注入
|
|
292
|
+
plainBtn.textContent = "远程访问";
|
|
293
|
+
const plugin = loadPlugin({ navCells });
|
|
306
294
|
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
plugin.navWindow.__dshRemoteNav.open();
|
|
314
|
-
assert.equal(remoteCell._clicked, 1, "应命中「远程访问」栏目项(aria-label 亦可读)");
|
|
315
|
-
assert.equal(remoteCell.getAttribute("data-dru-remote"), "1", "命中后应打 data-dru-remote 标记(加速二次命中)");
|
|
316
|
-
assert.equal(injected._clicked, 0, "不得点击注入的侧栏项自身(防递归)");
|
|
317
|
-
assert.equal(settingsNav._clicked, 0, "栏目已存在时无需退化点「设置」");
|
|
318
|
-
assert.equal(plugin.intervals.filter((x) => x.ms === 150).length, 0, "直接命中后不应启动轮询");
|
|
295
|
+
navCells.push(officialCell, plainBtn);
|
|
296
|
+
plugin.lastObserver().cb([]);
|
|
297
|
+
|
|
298
|
+
assert.equal(officialCell.children.length, 1, "官方设置页「远程访问」栏目按钮应注入红点");
|
|
299
|
+
assert.equal(officialCell.children[0].className, "dru-reddot");
|
|
300
|
+
assert.equal(plainBtn.children.length, 0, "非栏目导航按钮不得注入红点(不遮挡官方按钮)");
|
|
319
301
|
});
|
|
320
302
|
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
assert.
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
assert.
|
|
337
|
-
assert.
|
|
338
|
-
|
|
339
|
-
assert.
|
|
303
|
+
// ---------- 侧栏「远程访问」快捷入口(2026-09 恢复注入:与官方「设置」共存、不遮挡) ----------
|
|
304
|
+
// 用户要求:左侧官方「设置」按钮旁保留「📱 远程访问」快捷按钮。实现要点(防 Bug A 复发):
|
|
305
|
+
// - 独立 <button id=dru-nav-remote>(绝不 cloneNode → 不继承官方事件委托/点击热区),
|
|
306
|
+
// 插在官方「设置」按钮之前;
|
|
307
|
+
// - 候选限定官方导航(class 含 navCell 或位于导航容器)+ 短文本/aria 精确匹配;
|
|
308
|
+
// - 命中排除自身(防递归)与“菜单/更多”语义节点;不点工作区会话行;
|
|
309
|
+
// - openRemoteSettings:栏目已开直接点;未开先点官方「设置」再 ≤3s 轮询补点;
|
|
310
|
+
// - 红点(.dru-reddot / .dru-nav-remote-dot)用同一 dsh-remote-seen-dot key,点击即收起。
|
|
311
|
+
|
|
312
|
+
test("源码约束:侧栏注入「远程访问」按钮与官方「设置」共存;独立按钮非克隆;导航点击安全", () => {
|
|
313
|
+
// 注入存在:入口 id / 挂载函数 / 打开函数 / 心跳保证
|
|
314
|
+
assert.match(SOURCE, /dru-nav-remote/);
|
|
315
|
+
assert.match(SOURCE, /navEnsureStart/);
|
|
316
|
+
assert.match(SOURCE, /openRemoteSettings/);
|
|
317
|
+
assert.match(SOURCE, /__dshRemoteNav/);
|
|
318
|
+
assert.match(SOURCE, /data-dru-remote/);
|
|
319
|
+
assert.match(SOURCE, /NAV_ENTRY_ID/);
|
|
320
|
+
// 安全设计:绝不克隆官方按钮;候选限定 navCell/导航容器 + 短文本;排除自身;排除菜单语义
|
|
321
|
+
assert.doesNotMatch(SOURCE, /cloneNode/);
|
|
322
|
+
assert.match(SOURCE, /navCell/);
|
|
323
|
+
assert.match(SOURCE, /NAV_TEXT_MAX/);
|
|
324
|
+
assert.match(SOURCE, /el\.id === NAV_ENTRY_ID/);
|
|
325
|
+
assert.match(SOURCE, /NAV_BAD_RE/);
|
|
326
|
+
// 红点仍在(官方栏目 navCell + 快捷按钮首用同 key)
|
|
327
|
+
assert.match(SOURCE, /dru-reddot/);
|
|
328
|
+
assert.match(SOURCE, /dsh-remote-seen-dot/);
|
|
340
329
|
});
|
|
341
330
|
|
|
342
331
|
test("源码约束:无侧边栏入口/浮动面板/切换账号;命名统一为「远程访问」;新增访问密钥/设备路由", () => {
|
|
@@ -356,13 +345,6 @@ test("源码约束:无侧边栏入口/浮动面板/切换账号;命名统一
|
|
|
356
345
|
assert.match(SOURCE, /dsh-remote\/access-key/);
|
|
357
346
|
assert.match(SOURCE, /dsh-remote\/mobile-sessions/);
|
|
358
347
|
assert.match(SOURCE, /order: 30/);
|
|
359
|
-
// 侧栏入口导航加固:aria-label/role 扫描、data-dru-remote 标记、排除注入项防递归、进设置后轮询
|
|
360
|
-
assert.match(SOURCE, /data-dru-remote/);
|
|
361
|
-
assert.match(SOURCE, /dru-nav-remote/);
|
|
362
|
-
assert.match(SOURCE, /aria-label/);
|
|
363
|
-
assert.match(SOURCE, /remoteSectionVisible/);
|
|
364
|
-
assert.match(SOURCE, /openRemoteSettings/);
|
|
365
|
-
assert.match(SOURCE, /__dshRemoteNav/);
|
|
366
348
|
// 清理时机:退出登录成功回调内、登录账号变化时、切换自建服务时
|
|
367
349
|
assert.match(SOURCE, /post\("\/dsh-remote\/logout"\)\.then\(function \(body\) \{[\s\S]*?fbClearThreads\(\);/);
|
|
368
350
|
assert.match(SOURCE, /if \(prevPhone !== phone\.trim\(\)\) fbClearThreads\(\);/);
|