dsh-mobile 0.3.10 → 0.3.12
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 +10 -0
- package/README.en.md +9 -7
- package/README.md +9 -7
- package/lib/client.js +104 -5
- package/lib/client.js.map +1 -1
- package/lib/index.d.mts +31 -2
- package/lib/index.mjs +91 -5
- package/lib/index.mjs.map +1 -1
- package/lib/mobile-layout.js +8 -0
- package/lib/mobile-layout.js.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,16 @@
|
|
|
3
3
|
Notable changes to DSH Mobile are recorded here. GitHub Releases remain the source for downloadable packages and complete generated commit notes.
|
|
4
4
|
|
|
5
5
|
|
|
6
|
+
## 0.3.12 - 2026-09-07
|
|
7
|
+
|
|
8
|
+
- Document remote notification limits: browser permission is per origin, OS toasts stay on the computer, and server-side channels (e.g. dsh-messager webhooks) are the reliable push path to the phone (thanks @idoall for reporting #46). No code change since 0.3.11.
|
|
9
|
+
|
|
10
|
+
## 0.3.11 - 2026-09-07
|
|
11
|
+
|
|
12
|
+
- Sync the browser tab title with the current session on the dedicated layout, matching the stock behavior (thanks @idoall for reporting #45).
|
|
13
|
+
- Allow installed plugins' WebSocket endpoints through the gateway via admin-approved exact paths (e.g. `/sidebar/ws/terminal`), managed in the remote panel behind local-admin trust; built-in DSH paths keep working and everything else stays blocked (thanks @idoall for reporting #47).
|
|
14
|
+
- Document remote notification limits: browser permission is per origin, OS toasts stay on the computer, and server-side channels (e.g. dsh-messager webhooks) are the reliable push path to the phone (thanks @idoall for reporting #46).
|
|
15
|
+
|
|
6
16
|
## 0.3.10 - 2026-09-07
|
|
7
17
|
|
|
8
18
|
- Keep the workspace sidebar open on desktop-sized viewports (≥900px): the dedicated layout docks it as a persistent panel that survives reconnects and no longer auto-closes after selecting a session, and the dimming scrim only covers the narrow overlay drawer and details panel. Narrow screens keep the overlay drawer behavior unchanged (thanks @idoall for reporting #42).
|
package/README.en.md
CHANGED
|
@@ -19,14 +19,14 @@
|
|
|
19
19
|
|
|
20
20
|
> DSH Mobile is a DeepSeek Harness community plugin; the native app supports Android only.
|
|
21
21
|
>
|
|
22
|
-
> **0.3.
|
|
22
|
+
> **0.3.12 update**: remote notification limits documented (#46, docs only, no code change). [Details](CHANGELOG.md).
|
|
23
23
|
>
|
|
24
|
-
> **Upgrade reminder**: Windows DSH Desktop users should update to plugin 0.3.
|
|
24
|
+
> **Upgrade reminder**: Windows DSH Desktop users should update to plugin 0.3.12. Existing 0.3.3-0.3.11 apps and paired devices remain compatible without re-pairing. [Compatibility notes](#compatibility).
|
|
25
25
|
|
|
26
26
|
<p align="center">
|
|
27
|
-
<a href="https://github.com/saya-ch/dsh-mobile/releases/download/v0.3.
|
|
28
|
-
<a href="https://github.com/saya-ch/dsh-mobile/releases/download/v0.3.
|
|
29
|
-
<sub><a href="https://github.com/saya-ch/dsh-mobile/releases/tag/v0.3.
|
|
27
|
+
<a href="https://github.com/saya-ch/dsh-mobile/releases/download/v0.3.12/dsh-mobile-android-v0.3.12.apk"><img src="assets/brand/app-icon-rounded.svg" alt="DSH Mobile Android app icon" width="72" height="72"></a><br>
|
|
28
|
+
<a href="https://github.com/saya-ch/dsh-mobile/releases/download/v0.3.12/dsh-mobile-android-v0.3.12.apk"><strong>Download Android app 0.3.12</strong></a><br>
|
|
29
|
+
<sub><a href="https://github.com/saya-ch/dsh-mobile/releases/tag/v0.3.12">Release notes and checksums</a></sub>
|
|
30
30
|
</p>
|
|
31
31
|
|
|
32
32
|
DSH Mobile is a DeepSeek Harness plugin that lets a mobile browser or the Android app connect over a protected LAN or an optional Tailscale Funnel, cpolar, or self-hosted FRP remote path. Local and remote access keep the same sessions, Workspaces, messages, and tools while using separate switches and paired-device stores without modifying DeepSeek Harness source.
|
|
@@ -118,6 +118,8 @@ Remote providers may impose bandwidth and connection limits: the [cpolar Free pl
|
|
|
118
118
|
3. In the Android app, open **Remote access** and scan the QR code to create its separate pairing.
|
|
119
119
|
4. The app keeps device trust and reconnects automatically. Disable remote access when it is not needed; LAN access remains unchanged.
|
|
120
120
|
|
|
121
|
+
> **Remote notifications**: browser notification permission is granted per origin, so allow it separately for the remote address; OS-level toasts only appear on the computer, never on the phone. To push task completion to the phone, use a third-party channel (e.g. dsh-messager's Feishu/WeCom/Telegram push), which is delivered server-side and unaffected by the gateway.
|
|
122
|
+
|
|
121
123
|
Tailscale Funnel has broad reach but may be unreliable from mainland China. Its runtime ties the public listener to the parent process and a bounded control channel; parent exit, channel closure, or an explicit stop ends the current generation and cleans up its resources. cpolar is better suited to mainland networks, while self-hosted FRP fits users who already have a VPS and want to avoid public-provider bandwidth quotas. An unregistered domain on a mainland-China VPS may be intercepted by the cloud provider; public IPv4 mode avoids that dependency. The plugin validates pinned on-demand components, stores their configuration and programs entirely under `$DSH_HOME/mobile-access/`, and can remove them completely from the panel.
|
|
122
124
|
|
|
123
125
|
Self-hosted FRP generates only one HTTP vhost to the DSH loopback gateway. It exposes no arbitrary FRP configuration, TCP/UDP proxy, or FRP plugin. The VPS plaintext vhost must bind to `127.0.0.1`, with Caddy providing public HTTPS; the plugin rejects a publicly reachable plaintext port and reports readiness only after public discovery identifies the current computer.
|
|
@@ -198,14 +200,14 @@ The table below lists, for each plugin version, the DeepSeek Harness version it
|
|
|
198
200
|
|
|
199
201
|
| DSH Mobile plugin | Verified DeepSeek Harness version |
|
|
200
202
|
| --- | --- |
|
|
201
|
-
| `0.3.10` | `0.1.3-alpha.1` |
|
|
203
|
+
| `0.3.10`-`0.3.12` | `0.1.3-alpha.1` |
|
|
202
204
|
| `0.3.9` | `0.1.3-alpha.1` |
|
|
203
205
|
| `0.3.6`-`0.3.8` | `0.1.2-rc.1` |
|
|
204
206
|
| `0.3.4`, `0.3.5` | `0.1.2-alpha.2` |
|
|
205
207
|
| `0.3.0`-`0.3.3` | `0.1.2-alpha.1` |
|
|
206
208
|
| `0.1.4`, `0.2.x` | `0.1.1-rc.2` |
|
|
207
209
|
|
|
208
|
-
Existing 0.3.3-0.3.
|
|
210
|
+
Existing 0.3.3-0.3.11 apps do not need re-pairing. Earlier apps use a different status-bar strategy, so updating both is recommended. App 0.1.3 or earlier requires reinstalling and pairing again.
|
|
209
211
|
|
|
210
212
|
## Uninstall
|
|
211
213
|
|
package/README.md
CHANGED
|
@@ -26,14 +26,14 @@
|
|
|
26
26
|
|
|
27
27
|
> DSH Mobile 是 DeepSeek Harness 社区插件,原生 App 仅支持 Android。
|
|
28
28
|
>
|
|
29
|
-
> **0.3.
|
|
29
|
+
> **0.3.12 更新**:补充远程通知限制说明(#46,纯文档,无代码改动)。[详细记录](CHANGELOG.md)。
|
|
30
30
|
>
|
|
31
|
-
> **升级提醒**:Windows DSH Desktop 用户请更新至插件 0.3.
|
|
31
|
+
> **升级提醒**:Windows DSH Desktop 用户请更新至插件 0.3.12;现有 0.3.3-0.3.11 App 可继续使用,无需重新配对。[兼容说明](#兼容性)。
|
|
32
32
|
|
|
33
33
|
<p align="center">
|
|
34
|
-
<a href="https://github.com/saya-ch/dsh-mobile/releases/download/v0.3.
|
|
35
|
-
<a href="https://github.com/saya-ch/dsh-mobile/releases/download/v0.3.
|
|
36
|
-
<sub><a href="https://github.com/saya-ch/dsh-mobile/releases/tag/v0.3.
|
|
34
|
+
<a href="https://github.com/saya-ch/dsh-mobile/releases/download/v0.3.12/dsh-mobile-android-v0.3.12.apk"><img src="assets/brand/app-icon-rounded.svg" alt="DSH Mobile 安卓应用图标" width="72" height="72"></a><br>
|
|
35
|
+
<a href="https://github.com/saya-ch/dsh-mobile/releases/download/v0.3.12/dsh-mobile-android-v0.3.12.apk"><strong>下载 Android App 0.3.12</strong></a><br>
|
|
36
|
+
<sub><a href="https://github.com/saya-ch/dsh-mobile/releases/tag/v0.3.12">版本说明与校验文件</a></sub>
|
|
37
37
|
</p>
|
|
38
38
|
|
|
39
39
|
DSH Mobile 是一个 DeepSeek Harness 插件,让手机浏览器或 Android App 通过局域网,或可选的 Tailscale Funnel、cpolar、自建 FRP 远程通道连接电脑,继续使用同一份会话、工作区、消息和工具。局域网与远程访问分别启停、分别管理设备,且都不修改 DeepSeek Harness 源码。
|
|
@@ -125,6 +125,8 @@ dsh plugin --profile web add dshmarket
|
|
|
125
125
|
3. 在 Android App 中进入 **远程访问**,扫描二维码完成独立配对。
|
|
126
126
|
4. 此后 App 会保存设备信任并自动重连;不使用时可以关闭远程访问,局域网连接不会受影响。
|
|
127
127
|
|
|
128
|
+
> **远程通知说明**:浏览器通知权限按地址分别授权,远程地址需在浏览器中单独允许;系统级弹窗只出现在电脑上,手机收不到。任务完成要推送到手机时,请使用第三方通道(如 dsh-messager 的飞书/企业微信/Telegram 推送),它们走服务端下发,不受网关影响。
|
|
129
|
+
|
|
128
130
|
Tailscale Funnel 覆盖范围广,但在中国大陆网络下可能不稳定。其运行组件把公开监听生命周期绑定到父进程和受限控制通道;父进程退出、控制通道关闭或显式停止时会结束当前代次并清理资源。cpolar 更适合国内网络;自建 FRP 适合已有 VPS、希望避开公共服务带宽限制的用户。中国大陆 VPS 上的未备案域名可能被云厂商拦截,此时可使用公网 IPv4 模式。插件会校验按需下载的固定版本组件,配置与程序均保存在 `$DSH_HOME/mobile-access/`,可随时在面板中彻底清除。
|
|
129
131
|
|
|
130
132
|
自建 FRP 只生成一个指向 DSH 回环网关的 HTTP vhost,不提供任意 FRP 配置、TCP/UDP 代理或 FRP 插件。VPS 的明文 vhost 必须只监听 `127.0.0.1`,由 Caddy 提供公网 HTTPS;插件会拒绝可从公网访问的明文端口,并在公开发现接口确认连接到当前电脑后才显示“已就绪”。
|
|
@@ -207,14 +209,14 @@ flowchart LR
|
|
|
207
209
|
|
|
208
210
|
| DSH Mobile 插件 | 验证支持的 DeepSeek Harness 版本 |
|
|
209
211
|
| --- | --- |
|
|
210
|
-
| `0.3.10` | `0.1.3-alpha.1` |
|
|
212
|
+
| `0.3.10`-`0.3.12` | `0.1.3-alpha.1` |
|
|
211
213
|
| `0.3.9` | `0.1.3-alpha.1` |
|
|
212
214
|
| `0.3.6`-`0.3.8` | `0.1.2-rc.1` |
|
|
213
215
|
| `0.3.4`、`0.3.5` | `0.1.2-alpha.2` |
|
|
214
216
|
| `0.3.0`-`0.3.3` | `0.1.2-alpha.1` |
|
|
215
217
|
| `0.1.4`、`0.2.x` | `0.1.1-rc.2` |
|
|
216
218
|
|
|
217
|
-
现有 0.3.3-0.3.
|
|
219
|
+
现有 0.3.3-0.3.11 App 无需重新配对;更早的 App 使用不同的状态栏策略,建议同步升级;App 0.1.3 及更早版本需卸载重装并重新配对。
|
|
218
220
|
|
|
219
221
|
## 卸载
|
|
220
222
|
|
package/lib/client.js
CHANGED
|
@@ -151,7 +151,14 @@ window.__ModuleLoader__.load({
|
|
|
151
151
|
remoteQrReady: "Remote pairing QR code generated. Scan it from “Remote access” in the app.",
|
|
152
152
|
resetCpolarConfirm: "Disable the cpolar remote channel and remove all remote paired devices? Your cpolar account and other tunnels are unchanged.",
|
|
153
153
|
resetTailscaleConfirm: "Sign out of Tailscale on this computer and remove all remote paired devices? Local network configuration is unchanged.",
|
|
154
|
-
requestFailed: "Request failed: {error}"
|
|
154
|
+
requestFailed: "Request failed: {error}",
|
|
155
|
+
wsPathsTitle: "Third-party WebSocket paths",
|
|
156
|
+
wsPathsIntro: "Let installed plugins’ WebSocket endpoints (exact paths such as /sidebar/ws/terminal) work through the gateway. Built-in DSH paths always work; everything else stays blocked.",
|
|
157
|
+
wsPathsPlaceholder: "/sidebar/ws/terminal",
|
|
158
|
+
wsPathsAdd: "Allow path",
|
|
159
|
+
wsPathsRemove: "Remove",
|
|
160
|
+
wsPathsEmpty: "No extra paths allowed.",
|
|
161
|
+
wsPathsInvalid: "Enter an exact path starting with / (no query string)."
|
|
155
162
|
},
|
|
156
163
|
it: {
|
|
157
164
|
mobileAccess: "Accesso mobile",
|
|
@@ -297,7 +304,14 @@ window.__ModuleLoader__.load({
|
|
|
297
304
|
remoteQrReady: "QR di abbinamento remoto generato. Scansionalo da “Accesso remoto” nell’app.",
|
|
298
305
|
resetCpolarConfirm: "Disattivare il canale remoto cpolar e rimuovere tutti i dispositivi remoti? Account cpolar e altri tunnel restano invariati.",
|
|
299
306
|
resetTailscaleConfirm: "Uscire da Tailscale su questo computer e rimuovere tutti i dispositivi remoti? La configurazione della rete locale resta invariata.",
|
|
300
|
-
requestFailed: "Richiesta non riuscita: {error}"
|
|
307
|
+
requestFailed: "Richiesta non riuscita: {error}",
|
|
308
|
+
wsPathsTitle: "Percorsi WebSocket di terze parti",
|
|
309
|
+
wsPathsIntro: "Consenti agli endpoint WebSocket dei plugin installati (percorsi esatti come /sidebar/ws/terminal) di passare dal gateway. I percorsi DSH integrati funzionano sempre; tutto il resto resta bloccato.",
|
|
310
|
+
wsPathsPlaceholder: "/sidebar/ws/terminal",
|
|
311
|
+
wsPathsAdd: "Consenti percorso",
|
|
312
|
+
wsPathsRemove: "Rimuovi",
|
|
313
|
+
wsPathsEmpty: "Nessun percorso aggiuntivo consentito.",
|
|
314
|
+
wsPathsInvalid: "Inserisci un percorso esatto che inizi con / (senza query)."
|
|
301
315
|
},
|
|
302
316
|
zh: {}
|
|
303
317
|
};
|
|
@@ -445,7 +459,14 @@ window.__ModuleLoader__.load({
|
|
|
445
459
|
remoteQrReady: "远程配对二维码已生成。请在 App 的“远程访问”中扫描。",
|
|
446
460
|
resetCpolarConfirm: "关闭 cpolar 远程通道并移除所有远程配对设备?不会修改你的 cpolar 账号或其他隧道。",
|
|
447
461
|
resetTailscaleConfirm: "退出电脑上的 Tailscale 登录并移除所有远程配对设备?局域网配置不会改变。",
|
|
448
|
-
requestFailed: "请求失败:{error}"
|
|
462
|
+
requestFailed: "请求失败:{error}",
|
|
463
|
+
wsPathsTitle: "第三方 WebSocket 路径",
|
|
464
|
+
wsPathsIntro: "允许已装插件的 WebSocket 端点(确切路径,如 /sidebar/ws/terminal)经网关通行。DSH 内置路径始终可用,其余一律拦截。",
|
|
465
|
+
wsPathsPlaceholder: "/sidebar/ws/terminal",
|
|
466
|
+
wsPathsAdd: "允许该路径",
|
|
467
|
+
wsPathsRemove: "移除",
|
|
468
|
+
wsPathsEmpty: "暂无额外允许的路径。",
|
|
469
|
+
wsPathsInvalid: "请输入以 / 开头的确切路径(不带 query)。"
|
|
449
470
|
});
|
|
450
471
|
Object.assign(MOBILE_CONTROL_MESSAGES.en, {
|
|
451
472
|
selfHostedConnections: "Self-hosted connection",
|
|
@@ -2527,8 +2548,85 @@ window.__ModuleLoader__.load({
|
|
|
2527
2548
|
remoteManageRow.append(remoteDevices, remoteReset);
|
|
2528
2549
|
const remoteDevicePanel = element("div", "dsh-mobile-control__devices");
|
|
2529
2550
|
remoteDevicePanel.hidden = true;
|
|
2551
|
+
const wsPathsSection = element("section", "dsh-mobile-control__ws-paths");
|
|
2552
|
+
const wsPathsTitle = element("h3", "dsh-mobile-control__section-title");
|
|
2553
|
+
wsPathsTitle.textContent = t("wsPathsTitle");
|
|
2554
|
+
const wsPathsIntro = element("p", "dsh-mobile-control__intro");
|
|
2555
|
+
wsPathsIntro.textContent = t("wsPathsIntro");
|
|
2556
|
+
const wsPathsList = element("ul", "dsh-mobile-control__ws-paths-list");
|
|
2557
|
+
const wsPathsRow = element("div", "dsh-mobile-control__ws-paths-row");
|
|
2558
|
+
const wsPathsInput = element("input", "dsh-mobile-control__ws-paths-input");
|
|
2559
|
+
wsPathsInput.type = "text";
|
|
2560
|
+
wsPathsInput.placeholder = t("wsPathsPlaceholder");
|
|
2561
|
+
wsPathsInput.setAttribute("aria-label", t("wsPathsTitle"));
|
|
2562
|
+
const wsPathsAdd = element("button", "dsh-mobile-control__secondary");
|
|
2563
|
+
wsPathsAdd.type = "button";
|
|
2564
|
+
wsPathsAdd.textContent = t("wsPathsAdd");
|
|
2565
|
+
const wsPathsStatus = element("p", "dsh-mobile-control__status");
|
|
2566
|
+
wsPathsStatus.hidden = true;
|
|
2567
|
+
wsPathsStatus.setAttribute("aria-live", "polite");
|
|
2568
|
+
wsPathsRow.append(wsPathsInput, wsPathsAdd);
|
|
2569
|
+
wsPathsSection.append(wsPathsTitle, wsPathsIntro, wsPathsList, wsPathsRow, wsPathsStatus);
|
|
2570
|
+
let wsPathsCurrent = [];
|
|
2571
|
+
let wsPathsLoaded = false;
|
|
2572
|
+
const renderWsPaths = (paths) => {
|
|
2573
|
+
wsPathsCurrent = [...paths];
|
|
2574
|
+
wsPathsList.replaceChildren();
|
|
2575
|
+
if (paths.length === 0) {
|
|
2576
|
+
const empty = element("li", "dsh-mobile-control__ws-paths-empty");
|
|
2577
|
+
empty.textContent = t("wsPathsEmpty");
|
|
2578
|
+
wsPathsList.append(empty);
|
|
2579
|
+
}
|
|
2580
|
+
for (const path of paths) {
|
|
2581
|
+
const item = element("li", "dsh-mobile-control__ws-paths-item");
|
|
2582
|
+
const label = element("code");
|
|
2583
|
+
label.textContent = path;
|
|
2584
|
+
const remove = element("button", "dsh-mobile-control__ws-paths-remove");
|
|
2585
|
+
remove.type = "button";
|
|
2586
|
+
remove.textContent = t("wsPathsRemove");
|
|
2587
|
+
remove.setAttribute("aria-label", `${t("wsPathsRemove")}: ${path}`);
|
|
2588
|
+
remove.addEventListener("click", () => {
|
|
2589
|
+
saveWsPaths(wsPathsCurrent.filter((entry) => entry !== path));
|
|
2590
|
+
});
|
|
2591
|
+
item.append(label, remove);
|
|
2592
|
+
wsPathsList.append(item);
|
|
2593
|
+
}
|
|
2594
|
+
};
|
|
2595
|
+
const loadWsPaths = () => {
|
|
2596
|
+
controlRequestJson("/api/mobile-access/remote/websocket-paths").then((data) => {
|
|
2597
|
+
wsPathsLoaded = true;
|
|
2598
|
+
wsPathsStatus.hidden = true;
|
|
2599
|
+
renderWsPaths(Array.isArray(data.paths) ? data.paths.filter((entry) => typeof entry === "string") : []);
|
|
2600
|
+
}, (error) => {
|
|
2601
|
+
wsPathsStatus.hidden = false;
|
|
2602
|
+
wsPathsStatus.textContent = t("requestFailed", { error: String(error) });
|
|
2603
|
+
});
|
|
2604
|
+
};
|
|
2605
|
+
const saveWsPaths = (paths) => {
|
|
2606
|
+
wsPathsStatus.hidden = true;
|
|
2607
|
+
controlRequestJson("/api/mobile-access/remote/websocket-paths", {
|
|
2608
|
+
method: "POST",
|
|
2609
|
+
body: JSON.stringify({ paths })
|
|
2610
|
+
}).then((data) => {
|
|
2611
|
+
wsPathsLoaded = true;
|
|
2612
|
+
renderWsPaths(Array.isArray(data.paths) ? data.paths.filter((entry) => typeof entry === "string") : []);
|
|
2613
|
+
}, (error) => {
|
|
2614
|
+
wsPathsStatus.hidden = false;
|
|
2615
|
+
wsPathsStatus.textContent = t("requestFailed", { error: String(error) });
|
|
2616
|
+
});
|
|
2617
|
+
};
|
|
2618
|
+
wsPathsAdd.addEventListener("click", () => {
|
|
2619
|
+
const value = wsPathsInput.value.trim();
|
|
2620
|
+
if (value === "") {
|
|
2621
|
+
wsPathsStatus.hidden = false;
|
|
2622
|
+
wsPathsStatus.textContent = t("wsPathsInvalid");
|
|
2623
|
+
return;
|
|
2624
|
+
}
|
|
2625
|
+
wsPathsInput.value = "";
|
|
2626
|
+
saveWsPaths([...wsPathsCurrent, value]);
|
|
2627
|
+
});
|
|
2530
2628
|
const remoteWorkspace = element("section", "dsh-mobile-control__remote-workspace");
|
|
2531
|
-
remoteWorkspace.append(providerSetupHeader, remoteStatus, remoteAccess, remoteGuide, providerSetupBody, remoteActions, remoteQr, remoteManageRow, remoteDevicePanel);
|
|
2629
|
+
remoteWorkspace.append(providerSetupHeader, remoteStatus, remoteAccess, remoteGuide, providerSetupBody, remoteActions, remoteQr, remoteManageRow, remoteDevicePanel, wsPathsSection);
|
|
2532
2630
|
const diagnosticsView = element("div", "dsh-mobile-control__view is-diagnostics");
|
|
2533
2631
|
diagnosticsView.hidden = true;
|
|
2534
2632
|
const diagnosticsIntro = element("p", "dsh-mobile-control__intro");
|
|
@@ -2669,6 +2767,7 @@ window.__ModuleLoader__.load({
|
|
|
2669
2767
|
remoteTab.addEventListener("click", () => {
|
|
2670
2768
|
selectView("remote");
|
|
2671
2769
|
loadRemote();
|
|
2770
|
+
if (!wsPathsLoaded) loadWsPaths();
|
|
2672
2771
|
});
|
|
2673
2772
|
const setOpen = (open) => {
|
|
2674
2773
|
panel.hidden = !open;
|
|
@@ -5003,7 +5102,7 @@ window.__ModuleLoader__.load({
|
|
|
5003
5102
|
.dsh-mobile-control__actions{display:flex;flex-wrap:nowrap;gap:6px}.dsh-mobile-control__actions button{flex:1 1 0;min-width:0;min-height:40px;padding:8px 4px;border-radius:10px;font:12px/1.2 system-ui;cursor:pointer;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.dsh-mobile-control__secondary{border:1px solid var(--dsw-alias-border-normal,#cfd5dd);background:transparent;color:inherit}.dsh-mobile-control__primary{border:1px solid #2563eb;background:#2563eb;color:#fff}.dsh-mobile-control__actions button:disabled{cursor:not-allowed;opacity:.45}
|
|
5004
5103
|
.dsh-mobile-control button:focus-visible,.dsh-mobile-control a:focus-visible,.dsh-mobile-control input:focus-visible,.dsh-mobile-control summary:focus-visible{outline:3px solid rgb(37 99 235 / 28%);outline-offset:2px}
|
|
5005
5104
|
.dsh-mobile-control__trigger{box-sizing:border-box;flex:none;display:flex;align-items:center;gap:8px;width:calc(100% + 4px);height:42px;margin:4px -2px;padding:0 10px 0 8px;border:0;border-radius:12px;background:transparent;color:var(--dsw-alias-label-primary,#16181d);font-family:inherit;font-size:14px;line-height:22px;cursor:pointer;overflow:hidden}.dsh-mobile-control__trigger:hover{background:var(--dsw-alias-interactive-bg-hover,#f1f3f6)}.dsh-mobile-control__trigger:active,.dsh-mobile-control__trigger[aria-expanded="true"]{background:var(--dsw-alias-interactive-bg-active,#e8ebf0)}.dsh-mobile-control__trigger:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary,currentColor);outline-offset:2px}.dsh-mobile-control__trigger.is-rail{width:36px;height:36px;margin:8px 0 10px;padding:0;justify-content:center;gap:0;border-radius:50%}.dsh-mobile-control__trigger-icon{display:block;flex:none}.dsh-mobile-control__trigger-label{min-width:0;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}
|
|
5006
|
-
.dsh-mobile-control__manage-row{display:flex;justify-content:space-between;gap:8px;margin-top:10px}.dsh-mobile-control__manage{flex:1 1 0;min-width:0;min-height:34px;padding:6px 8px;border:1px solid var(--dsw-alias-border-normal,#cfd5dd);border-radius:10px;background:transparent;color:inherit;font:12px/1.3 system-ui;cursor:pointer}.dsh-mobile-control__devices{margin-top:10px;border:1px solid var(--dsw-alias-border-subtle,#e1e5eb);border-radius:10px;padding:8px;max-height:220px;overflow-y:auto}.dsh-mobile-control__device-empty{color:var(--dsw-alias-label-secondary,#606873);font-size:12px;margin:0}.dsh-mobile-control__device{display:flex;align-items:center;gap:8px;padding:6px 2px}.dsh-mobile-control__device + .dsh-mobile-control__device{border-top:1px solid var(--dsw-alias-border-subtle,#e1e5eb)}.dsh-mobile-control__device-label{flex:1 1 0;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:12px}.dsh-mobile-control__device-meta{flex:none;color:var(--dsw-alias-label-secondary,#606873);font-size:11px;white-space:nowrap}.dsh-mobile-control__device-revoke{flex:none;min-height:28px;padding:4px 8px;border:1px solid #dc2626;border-radius:8px;background:transparent;color:#dc2626;font:12px/1.2 system-ui;cursor:pointer}
|
|
5105
|
+
.dsh-mobile-control__manage-row{display:flex;justify-content:space-between;gap:8px;margin-top:10px}.dsh-mobile-control__manage{flex:1 1 0;min-width:0;min-height:34px;padding:6px 8px;border:1px solid var(--dsw-alias-border-normal,#cfd5dd);border-radius:10px;background:transparent;color:inherit;font:12px/1.3 system-ui;cursor:pointer}.dsh-mobile-control__devices{margin-top:10px;border:1px solid var(--dsw-alias-border-subtle,#e1e5eb);border-radius:10px;padding:8px;max-height:220px;overflow-y:auto}.dsh-mobile-control__device-empty{color:var(--dsw-alias-label-secondary,#606873);font-size:12px;margin:0}.dsh-mobile-control__device{display:flex;align-items:center;gap:8px;padding:6px 2px}.dsh-mobile-control__device + .dsh-mobile-control__device{border-top:1px solid var(--dsw-alias-border-subtle,#e1e5eb)}.dsh-mobile-control__device-label{flex:1 1 0;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:12px}.dsh-mobile-control__device-meta{flex:none;color:var(--dsw-alias-label-secondary,#606873);font-size:11px;white-space:nowrap}.dsh-mobile-control__device-revoke{flex:none;min-height:28px;padding:4px 8px;border:1px solid #dc2626;border-radius:8px;background:transparent;color:#dc2626;font:12px/1.2 system-ui;cursor:pointer}.dsh-mobile-control__ws-paths{margin:10px 0 0;padding:12px;border:1px solid var(--dsw-alias-border-subtle,#dbe1e8);border-radius:13px;background:var(--dsw-alias-bg-layer-2,#fff)}.dsh-mobile-control__ws-paths-list{margin:0 0 8px;padding:0;list-style:none}.dsh-mobile-control__ws-paths-empty{color:var(--dsw-alias-label-secondary,#606873);font-size:12px}.dsh-mobile-control__ws-paths-item{display:flex;align-items:center;gap:8px;padding:6px 0}.dsh-mobile-control__ws-paths-item + .dsh-mobile-control__ws-paths-item{border-top:1px solid var(--dsw-alias-border-subtle,#e1e5eb)}.dsh-mobile-control__ws-paths-item code{flex:1 1 0;min-width:0;overflow:hidden;font:11px/1.4 ui-monospace,SFMono-Regular,Consolas,monospace;text-overflow:ellipsis;white-space:nowrap}.dsh-mobile-control__ws-paths-remove{flex:none;min-height:28px;padding:4px 8px;border:1px solid var(--dsw-alias-border-normal,#cfd5dd);border-radius:8px;background:transparent;color:inherit;font:12px/1.2 system-ui;cursor:pointer}.dsh-mobile-control__ws-paths-row{display:flex;gap:8px}.dsh-mobile-control__ws-paths-row input{flex:1 1 0;min-width:0;box-sizing:border-box;min-height:40px;padding:8px 10px;border:1px solid var(--dsw-alias-border-normal,#cfd5dd);border-radius:10px;background:var(--dsw-alias-bg-layer-2,#fff);color:var(--dsw-alias-label-primary,#16181d);font:14px/1.4 system-ui}.dsh-mobile-control__ws-paths-row button{flex:none}
|
|
5007
5106
|
@media (max-width:359px){.dsh-mobile-control__provider-choices{grid-template-columns:1fr}.dsh-mobile-control__provider{min-height:68px}}@media (prefers-reduced-motion:reduce){.dsh-mobile-control__provider,.dsh-mobile-control__cpolar-connect{transition:none}.dsh-mobile-control__diagnostic-summary.is-running .dsh-mobile-control__diagnostic-summary-icon::before,.dsh-mobile-control__diagnostic-checks{animation:none}}
|
|
5008
5107
|
`;
|
|
5009
5108
|
/** Mount the desktop control or mobile feature enhancements. */
|