dsh-mobile 0.6.17 → 0.6.18
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 +25 -10
- package/CONTRIBUTORS.md +11 -5
- package/README.en.md +16 -10
- package/README.md +15 -10
- package/SECURITY.md +1 -1
- package/cordis.patch.yml +5 -9
- package/docs/ATTACH_EXISTING_FRPS.en.md +32 -2
- package/docs/ATTACH_EXISTING_FRPS.md +2 -2
- package/docs/MOBILE_PLUGIN_ADAPTATION.en.md +188 -0
- package/docs/MOBILE_PLUGIN_ADAPTATION.md +188 -0
- package/docs/README.md +8 -0
- package/docs/SELF_HOSTED_ORIGIN.en.md +1 -1
- package/docs/SELF_HOSTED_ORIGIN.md +2 -2
- package/docs/SLOW_CONNECTIONS.en.md +2 -2
- package/docs/SLOW_CONNECTIONS.md +2 -2
- package/docs/TRUSTED_NETWORKS.en.md +17 -0
- package/docs/TRUSTED_NETWORKS.md +17 -0
- package/lib/cli.js.map +1 -1
- package/lib/client.js +420 -42
- package/lib/client.js.map +1 -1
- package/lib/index.d.mts +3 -0
- package/lib/index.mjs +115 -27
- package/lib/index.mjs.map +1 -1
- package/package.json +5 -1
- package/packages/question-fixes/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,21 @@
|
|
|
2
2
|
|
|
3
3
|
Notable changes are recorded here. GitHub Releases provide the downloadable packages and generated commit notes.
|
|
4
4
|
|
|
5
|
+
## 0.6.18 - 2026-10-26
|
|
6
|
+
|
|
7
|
+
- Preserve DSH's adaptive directory-picker composition. The dedicated Mobile page reuses an available upstream browse picker, including its **New folder** action; a host using the system chooser keeps that chooser on Desktop and gets a separate web directory flow on the remote page. Thanks @OranImp for [#271](https://github.com/saya-ch/dsh-mobile/issues/271).
|
|
8
|
+
- Add **New folder** to the Mobile-owned directory flow. Create one child under a confirmed existing directory, report duplicate names and permission errors, and enter the new directory on success. Reject drive-relative and invalid names, fence cancelled results, prevent duplicate submissions and retain cancellation while admitted work settles. Escape and Back first close the creation step; writes are never automatically replayed.
|
|
9
|
+
- Give the folder list more room: use one compact path/navigation row, icon controls, a taller picker and smaller header/footer spacing, while retaining touch-sized targets and localized accessible labels.
|
|
10
|
+
- Offer the device-scoped module recovery page for stale profile defaults as well as saved computer/device selections. Recovery changes only the current device's selection, not computer defaults, other devices or installed plugins. Thanks @LUgABeEEE for [#276](https://github.com/saya-ch/dsh-mobile/issues/276).
|
|
11
|
+
- Add optional `adminAllowedCidrs` for controlled NAS administration. The default remains loopback-only; extra direct peers also require active DSH authentication, with existing Host/Origin and cross-site restrictions. Forwarded IP headers do not grant access. See [trusted networks](docs/TRUSTED_NETWORKS.en.md#accessing-the-nas-administration-page). Thanks @LzBsA for [#272](https://github.com/saya-ch/dsh-mobile/issues/272).
|
|
12
|
+
- Refresh only the legacy `upstreamOrigin` snapshot in managed setup when DSH's active WebServer port changes. Runtime forwarding already follows that port; this prevents misleading stale configuration, rather than establishing the cause of every connection timeout. Thanks @LUgABeEEE for [#274](https://github.com/saya-ch/dsh-mobile/pull/274).
|
|
13
|
+
- Add a bilingual [mobile adaptation guide for plugin authors](docs/MOBILE_PLUGIN_ADAPTATION.en.md), covering container layout, touch targets, keyboard/focus, safe areas and measured browser acceptance. Thanks @LUgABeEEE for [#280](https://github.com/saya-ch/dsh-mobile/pull/280).
|
|
14
|
+
|
|
15
|
+
## Android 0.6.8 - 2026-10-26
|
|
16
|
+
|
|
17
|
+
- Let the existing overall connection deadline govern the first page download, instead of interrupting it with the shorter page timer and automatically restarting the download after renewal. A real first-load failure retains explicit manual retry; already running pages retain their recovery behavior. Existing TLS verification, cancellation and renderer-crash handling remain. Thanks @LUgABeEEE for [#275](https://github.com/saya-ch/dsh-mobile/issues/275).
|
|
18
|
+
- App 0.6.8/build 84 is released independently of plugin 0.6.18, retaining the established package identity and signer. Existing pairings remain in place when upgrading the officially signed App.
|
|
19
|
+
|
|
5
20
|
## 0.6.17 - 2026-10-25
|
|
6
21
|
|
|
7
22
|
- Keep DSH's own directory-picker composition instead of registering a second Host service and Client surface. Official Desktop retains its native chooser, **Add workspace** action and `Ctrl+O` shortcut independently of Mobile's in-page picker. Thanks @ChaoPhone for [#257](https://github.com/saya-ch/dsh-mobile/issues/257) and @bvbhu for [#258](https://github.com/saya-ch/dsh-mobile/issues/258).
|
|
@@ -111,6 +126,13 @@ Notable changes are recorded here. GitHub Releases provide the downloadable pack
|
|
|
111
126
|
- Add bilingual remote-channel selection notes distinguishing the maintainer's long-term network experience from provider limits and conditional self-hosted deployment characteristics.
|
|
112
127
|
- At this plugin release, Android App 0.6.3 was still the published native version; Android 0.6.4 was published independently later on the same day. Its file-picker changes are not part of this plugin fix. Thanks @Yurzi for reporting [#213](https://github.com/saya-ch/dsh-mobile/issues/213).
|
|
113
128
|
|
|
129
|
+
## Android 0.6.4 - 2026-10-15
|
|
130
|
+
|
|
131
|
+
- Prefer the system Photo Picker on Android 13+ for supported image requests, with document selection for other requests or an unavailable picker. Preserve multi-selection, MIME filtering and selected URI results without adding storage permission or forcing a vendor gallery.
|
|
132
|
+
- Bind standard file callbacks to the active WebView, Origin and document. Cancel them on navigation or teardown and prevent old results from consuming a newer request. This native update is released independently from plugin 0.6.8 and preserves existing paired records.
|
|
133
|
+
- On WebViews with navigation-listener support, settle file requests before replacing their document and pause new selection until all in-flight document navigations finish, including cancelled and non-committing navigations. This prevents a late cancellation from disabling the new page's file input. Older providers retain their available callbacks; update WebView or reopen the paired computer if selection still fails after changing pages.
|
|
134
|
+
- Retain the package identity, established release signer, permission list and native pairing protocol. Thanks @Void-LifeStream for the attachment report in [#205](https://github.com/saya-ch/dsh-mobile/issues/205), and @xhwxt for the document-picker proposal in [#203](https://github.com/saya-ch/dsh-mobile/pull/203).
|
|
135
|
+
|
|
114
136
|
## 0.6.7 - 2026-10-14
|
|
115
137
|
|
|
116
138
|
- Add optional `cpolarSubdomain` and `cpolarRegion` profile settings for a reserved cpolar address. Omitted or blank values keep provider defaults; only the validated HTTPS origin reported by cpolar is used. Existing pairing and authorization checks are unchanged. [Configuration guide](docs/CPOLAR_SUBDOMAIN.en.md).
|
|
@@ -121,13 +143,6 @@ Notable changes are recorded here. GitHub Releases provide the downloadable pack
|
|
|
121
143
|
- Clarify `/mobile` and both READMEs: detected files are not proof of page activation; ordinary DSH login or phone-sized preview does not establish mobile pairing. Thanks @Dantezcx for the detailed reports in [#209](https://github.com/saya-ch/dsh-mobile/issues/209) and [#210](https://github.com/saya-ch/dsh-mobile/issues/210).
|
|
122
144
|
- Thanks @GavinQiEr for the request in [#207](https://github.com/saya-ch/dsh-mobile/issues/207) and implementation in [#208](https://github.com/saya-ch/dsh-mobile/pull/208); the original author commit is retained alongside maintainer corrections.
|
|
123
145
|
|
|
124
|
-
## Android 0.6.4 - 2026-10-15
|
|
125
|
-
|
|
126
|
-
- Prefer the system Photo Picker on Android 13+ for supported image requests, with document selection for other requests or an unavailable picker. Preserve multi-selection, MIME filtering and selected URI results without adding storage permission or forcing a vendor gallery.
|
|
127
|
-
- Bind standard file callbacks to the active WebView, Origin and document. Cancel them on navigation or teardown and prevent old results from consuming a newer request. This native update is released independently from plugin 0.6.8 and preserves existing paired records.
|
|
128
|
-
- On WebViews with navigation-listener support, settle file requests before replacing their document and pause new selection until all in-flight document navigations finish, including cancelled and non-committing navigations. This prevents a late cancellation from disabling the new page's file input. Older providers retain their available callbacks; update WebView or reopen the paired computer if selection still fails after changing pages.
|
|
129
|
-
- Retain the package identity, established release signer, permission list and native pairing protocol. Thanks @Void-LifeStream for the attachment report in [#205](https://github.com/saya-ch/dsh-mobile/issues/205), and @xhwxt for the document-picker proposal in [#203](https://github.com/saya-ch/dsh-mobile/pull/203).
|
|
130
|
-
|
|
131
146
|
## 0.6.6 - 2026-10-14
|
|
132
147
|
|
|
133
148
|
- Fix captured images not reaching DSH's attachment draft. Supply both files and iterable file items, with compatible drag-and-drop objects for browsers whose constructed objects are incomplete.
|
|
@@ -179,7 +194,7 @@ Notable changes are recorded here. GitHub Releases provide the downloadable pack
|
|
|
179
194
|
- Add Android App 0.6.2 (build 78), separately from plugin 0.6.3. Keep web content inside the native system-bar, cutout and keyboard area; add native-only page zoom in General settings, with 80–125% scaling and a 100% reset, without reloading the conversation. Older App versions and browsers do not show this control.
|
|
180
195
|
- Add a nonblocking update reminder for WebViews reporting Chromium below 100. Users may continue; unknown engine versions are not treated as obsolete, and each detected build is warned about once. This does not promise full compatibility with unsupported old engines.
|
|
181
196
|
- Improve bounded Windows retries and rollback for managed Caddy preparation while keeping official managed installation disabled. Thanks @abworks-dev for [PR #190](https://github.com/saya-ch/dsh-mobile/pull/190).
|
|
182
|
-
- Hide the duplicate passive pin marker on narrow mobile session lists while retaining pin actions and desktop presentation. Thanks @
|
|
197
|
+
- Hide the duplicate passive pin marker on narrow mobile session lists while retaining pin actions and desktop presentation. Thanks @abworks-dev for [PR #191](https://github.com/saya-ch/dsh-mobile/pull/191).
|
|
183
198
|
- Add a repository-local Agent maintenance skill and discovery entrypoint covering compatibility, packaging, runtime/ADB, collaboration and independent releases, with guidance for updating demonstrated reusable lessons.
|
|
184
199
|
|
|
185
200
|
## 0.6.2 - 2026-10-08
|
|
@@ -317,7 +332,7 @@ Add mobile page module management, Android launcher choices, fixed device orderi
|
|
|
317
332
|
|
|
318
333
|
## 0.4.5 - 2026-09-23
|
|
319
334
|
|
|
320
|
-
- Support the document-relative plugin URLs introduced in DSH 0.1.7 without weakening the same-origin `/plugins/` check. This fixes mobile boot batches returning `502 upstream_unavailable`; local and remote gateways were verified against DSH 0.1.7-alpha.2 (thanks @
|
|
335
|
+
- Support the document-relative plugin URLs introduced in DSH 0.1.7 without weakening the same-origin `/plugins/` check. This fixes mobile boot batches returning `502 upstream_unavailable`; local and remote gateways were verified against DSH 0.1.7-alpha.2 (thanks @miqian-nomad for [#97](https://github.com/saya-ch/dsh-mobile/issues/97)).
|
|
321
336
|
- Keep failed revisioned plugin scripts and hashed assets on `no-store` instead of caching their 404 responses as immutable for a year (thanks @abworks-dev for [PR #98](https://github.com/saya-ch/dsh-mobile/pull/98)).
|
|
322
337
|
- Guard WebSocket upgrade sockets before asynchronous authentication so disconnects during reconnect cannot emit an unhandled socket error (follow-up to [#95](https://github.com/saya-ch/dsh-mobile/issues/95)).
|
|
323
338
|
- Give Android connection restoration an exit after a short wait: direct-start Retry stays bound to that paired computer, while manual and legacy flows offer the Device list without retrying a different computer. Existing credentials remain intact (thanks @sznyhgm for [#96](https://github.com/saya-ch/dsh-mobile/issues/96)).
|
|
@@ -384,7 +399,7 @@ Add mobile page module management, Android launcher choices, fixed device orderi
|
|
|
384
399
|
- Let cpolar choose its default route instead of forcing `cn`: the plugin no longer passes `-region`, so cpolar selects its own tunnel server. No profile or environment setting exposes an explicit region.
|
|
385
400
|
- Add Android task-completion and pending-input reminders through authenticated Host events and the exact-origin native bridge; notification permission is enabled explicitly from the foreground app menu, lock-screen text stays generic, and each completed turn keeps a separate reminder (thanks @qzyqmzn for PR #75).
|
|
386
401
|
- Show and re-copy remote pairing links without invalidating the QR code's active one-time pairing window (thanks @qzyqmzn for PR #75).
|
|
387
|
-
- Detect plugin-market installations that have not completed LAN setup, prevent the loopback-only `127.0.0.1` fallback from being presented as phone access, and provide a localized in-panel network picker that creates private TLS material and LAN-only Windows firewall rules after explicit confirmation. The configured gateway starts after one DSH restart (thanks @cangming99 for
|
|
402
|
+
- Detect plugin-market installations that have not completed LAN setup, prevent the loopback-only `127.0.0.1` fallback from being presented as phone access, and provide a localized in-panel network picker that creates private TLS material and LAN-only Windows firewall rules after explicit confirmation. The configured gateway starts after one DSH restart (thanks @cangming99 for the report).
|
|
388
403
|
- Keep native DSH file selection in the composer Add group, add only camera capture there, and reuse the native menu-row styling for the mobile action.
|
|
389
404
|
- Add a native-app-only Switch computer action to the WebView's DSH General settings page, keeping the Android device-list settings and DSH content toolbar focused on their own controls.
|
|
390
405
|
- Hide the Android shell toolbar above the WebView so DSH occupies the full safe viewport; the system status-bar color continues to follow the page background.
|
package/CONTRIBUTORS.md
CHANGED
|
@@ -1,8 +1,14 @@
|
|
|
1
1
|
# 贡献者 / Contributors
|
|
2
2
|
|
|
3
|
-
GitHub 的 [Contributors 图表](https://github.com/saya-ch/dsh-mobile/graphs/contributors) 按进入默认分支的提交自动统计,无法手动加入仅提交 issue 或 PR 提案的成员。本页按截至 2026-10-
|
|
3
|
+
GitHub 的 [Contributors 图表](https://github.com/saya-ch/dsh-mobile/graphs/contributors) 按进入默认分支的提交自动统计,无法手动加入仅提交 issue 或 PR 提案的成员。本页按截至 2026-10-26 的实际参与方式感谢社区成员;仓库维护者与自动依赖更新仍可在 GitHub 历史记录中查看。
|
|
4
4
|
|
|
5
|
-
GitHub's Contributors graph counts commits on the default branch; issue reports and PR proposals cannot be manually added to it. This page credits community members by how they contributed, through 2026-10-
|
|
5
|
+
GitHub's Contributors graph counts commits on the default branch; issue reports and PR proposals cannot be manually added to it. This page credits community members by how they contributed, through 2026-10-26. The repository maintainer and automated dependency updates remain visible in GitHub's history.
|
|
6
|
+
|
|
7
|
+
## 0.6.18 代码贡献与反馈 / Code contributions and reports for 0.6.18
|
|
8
|
+
|
|
9
|
+
感谢 [@OranImp](https://github.com/OranImp) 在 [#271](https://github.com/saya-ch/dsh-mobile/issues/271) 反馈目录选择流程缺少新建文件夹,[@LzBsA](https://github.com/LzBsA) 在 [#272](https://github.com/saya-ch/dsh-mobile/issues/272) 提出受控 NAS 管理入口需求,以及 [@LUgABeEEE](https://github.com/LUgABeEEE) 在 [#275](https://github.com/saya-ch/dsh-mobile/issues/275)、[#276](https://github.com/saya-ch/dsh-mobile/issues/276) 提供慢链路启动与模块恢复的详细报告。[@LUgABeEEE](https://github.com/LUgABeEEE) 的 [#274](https://github.com/saya-ch/dsh-mobile/pull/274) 配置快照修正和 [#280](https://github.com/saya-ch/dsh-mobile/pull/280) 插件适配指南保留原作者提交,并另附维护者修正。#275 的原生加载修复随独立编号的 App 发布,不由插件升级替代。
|
|
10
|
+
|
|
11
|
+
Thanks [@OranImp](https://github.com/OranImp) for reporting missing folder creation in [#271](https://github.com/saya-ch/dsh-mobile/issues/271), [@LzBsA](https://github.com/LzBsA) for the controlled NAS administration request in [#272](https://github.com/saya-ch/dsh-mobile/issues/272), and [@LUgABeEEE](https://github.com/LUgABeEEE) for the detailed slow-link boot and module-recovery reports in [#275](https://github.com/saya-ch/dsh-mobile/issues/275) and [#276](https://github.com/saya-ch/dsh-mobile/issues/276). Original commits for [@LUgABeEEE](https://github.com/LUgABeEEE)'s setup snapshot correction in [#274](https://github.com/saya-ch/dsh-mobile/pull/274) and adaptation guide in [#280](https://github.com/saya-ch/dsh-mobile/pull/280) are retained alongside maintainer corrections. The native loading fix for #275 belongs to the independently versioned App, not a plugin-only update.
|
|
6
12
|
|
|
7
13
|
## 0.6.17 代码贡献与反馈 / Code contributions and reports for 0.6.17
|
|
8
14
|
|
|
@@ -70,9 +76,9 @@ Thanks [@jamorzzz](https://github.com/jamorzzz) for the community-auth navigatio
|
|
|
70
76
|
|
|
71
77
|
## 0.6.3 代码贡献 / Code contributions in 0.6.3
|
|
72
78
|
|
|
73
|
-
[@abworks-dev](https://github.com/abworks-dev) 的 [#190](https://github.com/saya-ch/dsh-mobile/pull/190)、[#
|
|
79
|
+
[@abworks-dev](https://github.com/abworks-dev) 的 [#190](https://github.com/saya-ch/dsh-mobile/pull/190)、[#191](https://github.com/saya-ch/dsh-mobile/pull/191)、[#192](https://github.com/saya-ch/dsh-mobile/pull/192),以及 [@chintoleung](https://github.com/chintoleung) 在 [#189](https://github.com/saya-ch/dsh-mobile/issues/189) 提供的三个 Worker 原型提交参与本版,保留原始提交并追加适配与修正。具体范围见 [更新记录](CHANGELOG.md#063---2026-10-10)。
|
|
74
80
|
|
|
75
|
-
[@abworks-dev](https://github.com/abworks-dev)'s [#190](https://github.com/saya-ch/dsh-mobile/pull/190)
|
|
81
|
+
[@abworks-dev](https://github.com/abworks-dev)'s [#190](https://github.com/saya-ch/dsh-mobile/pull/190), [#191](https://github.com/saya-ch/dsh-mobile/pull/191) and [#192](https://github.com/saya-ch/dsh-mobile/pull/192), plus three Worker prototype commits supplied by [@chintoleung](https://github.com/chintoleung) through [#189](https://github.com/saya-ch/dsh-mobile/issues/189), contribute to this release with original history and maintainer corrections. See the [release scope](CHANGELOG.md#063---2026-10-10).
|
|
76
82
|
|
|
77
83
|
## 已合并 PR / Merged PRs
|
|
78
84
|
|
|
@@ -137,7 +143,6 @@ Thanks [@xhwxt](https://github.com/xhwxt) for the document-picker proposal in [#
|
|
|
137
143
|
| [@abworks-dev](https://github.com/abworks-dev) | [#174](https://github.com/saya-ch/dsh-mobile/issues/174) |
|
|
138
144
|
| [@Ann-luo](https://github.com/Ann-luo) | [#150](https://github.com/saya-ch/dsh-mobile/issues/150) |
|
|
139
145
|
| [@Anyways366](https://github.com/Anyways366) | [#223](https://github.com/saya-ch/dsh-mobile/issues/223) |
|
|
140
|
-
| [@azri57806-design](https://github.com/azri57806-design) | [#97](https://github.com/saya-ch/dsh-mobile/issues/97) |
|
|
141
146
|
| [@BrainZombie](https://github.com/BrainZombie) | [#128](https://github.com/saya-ch/dsh-mobile/issues/128) |
|
|
142
147
|
| [@bvbhu](https://github.com/bvbhu) | [#258](https://github.com/saya-ch/dsh-mobile/issues/258) |
|
|
143
148
|
| [@CESAEREE](https://github.com/CESAEREE) | [#1](https://github.com/saya-ch/dsh-mobile/issues/1) |
|
|
@@ -160,6 +165,7 @@ Thanks [@xhwxt](https://github.com/xhwxt) for the document-picker proposal in [#
|
|
|
160
165
|
| [@KMGTPEZY](https://github.com/KMGTPEZY) | [#95](https://github.com/saya-ch/dsh-mobile/issues/95) |
|
|
161
166
|
| [@luoyangchan](https://github.com/luoyangchan) | [#187](https://github.com/saya-ch/dsh-mobile/issues/187) |
|
|
162
167
|
| [@LWping](https://github.com/LWping) | [#94](https://github.com/saya-ch/dsh-mobile/issues/94) |
|
|
168
|
+
| [@miqian-nomad](https://github.com/miqian-nomad) | [#97](https://github.com/saya-ch/dsh-mobile/issues/97) |
|
|
163
169
|
| [@MLYR](https://github.com/MLYR) | [#193](https://github.com/saya-ch/dsh-mobile/issues/193) |
|
|
164
170
|
| [@oliverwan97](https://github.com/oliverwan97) | [#26](https://github.com/saya-ch/dsh-mobile/issues/26) |
|
|
165
171
|
| [@optttt](https://github.com/optttt) | [#111](https://github.com/saya-ch/dsh-mobile/issues/111) |
|
package/README.en.md
CHANGED
|
@@ -26,13 +26,13 @@
|
|
|
26
26
|
<a href="#compatibility">Compatibility</a> ·
|
|
27
27
|
<a href="docs/README.md">Documentation</a> ·
|
|
28
28
|
<a href="#contributors">Contributors</a> ·
|
|
29
|
-
<a href="https://github.com/saya-ch/dsh-mobile/releases/tag/v0.6.
|
|
29
|
+
<a href="https://github.com/saya-ch/dsh-mobile/releases/tag/v0.6.18">Release notes</a> ·
|
|
30
30
|
<a href="README.md">简体中文</a>
|
|
31
31
|
</p>
|
|
32
32
|
|
|
33
33
|
> DSH Mobile is a DeepSeek Harness community plugin; the native app supports Android only.
|
|
34
34
|
>
|
|
35
|
-
> **Current stable release: 0.6.
|
|
35
|
+
> **Current stable release: 0.6.18**. Create folders from the remote directory picker, with compact navigation and controls that leave more room for folders. Recover from stale module choices that prevented the page from opening, and optionally administer a NAS from an authenticated, controlled network. The Android App is released independently; App **0.6.7** supports these plugin features. [Plugin release notes and downloads](https://github.com/saya-ch/dsh-mobile/releases/tag/v0.6.18) · [Full changelog](CHANGELOG.md).
|
|
36
36
|
>
|
|
37
37
|
> **Version policy**: since plugin **0.6.2**, the Android app and plugin use independent version numbers and releases. Their numbers do not need to match, and a plugin update does not imply an app update. [Compatibility notes](#compatibility).
|
|
38
38
|
|
|
@@ -130,7 +130,7 @@ Use this when the phone and computer share Wi-Fi, Ethernet, or a phone hotspot.
|
|
|
130
130
|
|
|
131
131
|
When other plugin entries share the sidebar footer, **Mobile access** becomes a phone-icon button. Hover to read its name; clicking opens the same panel. Its text label returns when the entry is alone.
|
|
132
132
|
|
|
133
|
-
Port note: `dsh web --port` changes the DSH Web upstream port (3080 by default), which the plugin follows automatically. `dsh-mobile setup --port` changes the Mobile HTTPS listener (3443 by default), and the pairing QR code includes the selected port.
|
|
133
|
+
Port note: `dsh web --port` changes the DSH Web upstream port (3080 by default), which the plugin follows automatically. `dsh-mobile setup --port` changes the Mobile HTTPS listener (3443 by default), and the pairing QR code includes the selected port. When DSH Desktop starts with `--port 0`, the gateway follows the **actual port in use**; `upstreamOrigin` in `mobile-access/setup.json` is only the snapshot from the first setup, and the plugin refreshes it at startup — do not read it as the upstream the gateway uses.
|
|
134
134
|
|
|
135
135
|
<details>
|
|
136
136
|
<summary>Headless hosts, private proxies and additional source networks</summary>
|
|
@@ -363,6 +363,7 @@ flowchart LR
|
|
|
363
363
|
Lan --> Gateway["DSH Mobile Gateway Core"]
|
|
364
364
|
Remote --> Gateway
|
|
365
365
|
Gateway -->|"loopback proxy"| DSH["Stock DSH Web and Host"]
|
|
366
|
+
DSH -->|"same workspace, sessions and event stream"| Phone
|
|
366
367
|
```
|
|
367
368
|
|
|
368
369
|
Three layers: the Host face for discovery, pairing, HTTPS, loopback proxying, and extension registration; the Client face for the dedicated mobile layout and extension SDK; and the Android app for a narrow native bridge. The bridge uses `androidx.webkit` WebMessage, verifies the exact top-level origin and main frame on every bounded message, and never uses `addJavascriptInterface`. The plugin does not rewrite source or webpage files in the DeepSeek Harness installation. Its mobile gateway serves the startup compatibility layer and dedicated layout per request; installation and removal use the plugin mechanism. The upstream DSH Web port defaults to 3080 and is configurable through `dsh web --port`.
|
|
@@ -417,20 +418,25 @@ On macOS, local network, cloudflared, self-hosted FRP and the own reverse proxy
|
|
|
417
418
|
| `0.6.11` | Isolated packed-browser CI on `0.1.7-alpha.2`, `0.1.7-rc.1`, `0.1.7-rc.2`, `0.2.0-rc.1`, `0.2.0-rc.2`, `0.2.1-alpha.2` and `0.2.1-alpha.3`; additional real history-pagination, viewport-preservation and manual-loading checks on `0.2.0-rc.2` and `0.2.1-alpha.3`. Browser checks do not establish acceptance of every phone engine, third-party plugin or public route |
|
|
418
419
|
| `0.6.12` | Packed installation, mobile boot, missing-API simulation, Workspace streaming, retained-page transport recovery and mobile settings on `0.2.1-rc.2`; authentication/resource regression with the actual community `dsh-web-startup-auth@0.1.12` on `0.2.0-rc.2`. This does not establish physical Chromium 92, arbitrary auth-plugin or public-route acceptance |
|
|
419
420
|
| `0.6.13` | Packed text/image HTTP 400 recovery, Host refusal guard and error-feedback checks on `0.2.0-rc.2` and `0.2.1-rc.2`; Gateway 408/431 classification, bounded diagnostics and four Gateway factory wiring passed local tests. DSH source, iroh P2P and Android native code are outside this release |
|
|
421
|
+
| `0.6.14` | Release CI packed-browser jobs green on all eight DSH versions from `0.1.7-alpha.2` to `0.2.1-rc.2`; no additional per-version manual acceptance was recorded for this release |
|
|
422
|
+
| `0.6.15` | `0.2.1-rc.2`: real admin-panel pairing in Firefox 158 privacy mode, the HTTPS mobile page and Workspace-read baseline, and silent Blob playback; release CI green on all eight versions |
|
|
423
|
+
| `0.6.16` | `0.2.1-rc.2`: Gallery selection, plain-text draft transfer through public DSH input APIs, real mux recovery and cross-client pending questions; CI additionally covered `0.1.7-alpha.2`, `0.1.7-rc.1`, `0.1.7-rc.2`, `0.2.0-rc.1`, `0.2.0-rc.2`, `0.2.1-alpha.2` and `0.2.1-alpha.3` |
|
|
424
|
+
| `0.6.18` | `0.2.1-rc.2`: 18 real packed Chromium directory-picker checks, including compact layout, folder creation and cancellation; the candidate was installed in local official Desktop `0.2.1-rc.3` with LAN and Cloudflare gateways running |
|
|
425
|
+
| `0.6.17` | `0.2.0-rc.2` and `0.2.1-rc.2`: 15 real packed Chromium directory-picker checks, the old-WebView missing-API simulation and Workspace mux reads; the published package was then installed into official Desktop `0.2.1-rc.2` and its files matched byte for byte |
|
|
420
426
|
|
|
421
427
|
<details>
|
|
422
428
|
<summary>Historical version checks</summary>
|
|
423
429
|
|
|
424
430
|
| DSH Mobile plugin | Verified DeepSeek Harness version |
|
|
425
431
|
| --- | --- |
|
|
426
|
-
| `0.5.5` | `0.1.7-alpha.2`, `0.1.7-rc.1`, `0.1.7-rc.2`, `0.2.0-rc.1`, and `0.2.0-rc.2` (npm installation, isolated pairing, mobile-page boot, and WebSocket Workspace baseline) |
|
|
427
|
-
| `0.6.0` | `0.1.7-alpha.2`, `0.1.7-rc.1`, `0.1.7-rc.2`, `0.2.0-rc.1` and `0.2.0-rc.2` (packed installation, pairing, mobile-page boot and WebSocket Workspace reads); additional checks cover the mobile composer, module settings and component loading after a normal official Desktop restart |
|
|
428
|
-
| `0.6.2` | Packed legacy-WebView boot, touch scrolling and missing-API/viewport negative controls passed on `0.2.0-rc.2`, with release CI passing. The reporter's physical old devices in #187 were not claimed as accepted |
|
|
429
|
-
| `0.6.3` | `0.2.0-rc.2` and `0.2.1-alpha.2` (packed installation, isolated pairing, mobile boot and WebSocket Workspace reads); additional checks cover the composer, settings and extension Worker timeout, streaming and explicit recovery |
|
|
430
|
-
| `0.6.4` | `0.2.0-rc.2` (packed installation, isolated pairing, mobile boot and WebSocket Workspace reads); additionally 72 real public-slot composer layouts, Windows Desktop directory-picker composition and cross-platform regressions. The reported remote timeout in community Desktop 2.0.17 remains unclaimed as accepted |
|
|
431
|
-
| `0.6.5` | Packed module-management and mobile-settings regressions on `0.2.0-rc.2` and `0.2.1-alpha.2`; additionally Windows cpolar extraction and populated Trajectory layout with published `maid-atelier` 0.1.7. This does not establish acceptance of every third-party skin or reporter device |
|
|
432
|
-
| `0.6.6` | Packed attachment intake and decoded-preview regressions on `0.2.0-rc.2` and `0.2.1-alpha.2`, covering multiple images, cancellation, late results and superseded requests. Android system-picker changes are released independently, not through the npm update |
|
|
433
432
|
| `0.6.8` | Packed mobile boot, legacy-WebView API simulation, WebSocket Workspace reads, mobile settings, module management, sidebar and composer regressions on `0.2.1-alpha.3`; separate real HTTP/TLS and legacy-credential upgrade tests cover the identity fix. The local official Desktop `0.2.0-rc.2` loads this plugin version with existing pairings preserved. This does not establish phone cellular or every third-party plugin combination |
|
|
433
|
+
| `0.6.6` | Packed attachment intake and decoded-preview regressions on `0.2.0-rc.2` and `0.2.1-alpha.2`, covering multiple images, cancellation, late results and superseded requests. Android system-picker changes are released independently, not through the npm update |
|
|
434
|
+
| `0.6.5` | Packed module-management and mobile-settings regressions on `0.2.0-rc.2` and `0.2.1-alpha.2`; additionally Windows cpolar extraction and populated Trajectory layout with published `maid-atelier` 0.1.7. This does not establish acceptance of every third-party skin or reporter device |
|
|
435
|
+
| `0.6.4` | `0.2.0-rc.2` (packed installation, isolated pairing, mobile boot and WebSocket Workspace reads); additionally 72 real public-slot composer layouts, Windows Desktop directory-picker composition and cross-platform regressions. The reported remote timeout in community Desktop 2.0.17 remains unclaimed as accepted |
|
|
436
|
+
| `0.6.3` | `0.2.0-rc.2` and `0.2.1-alpha.2` (packed installation, isolated pairing, mobile boot and WebSocket Workspace reads); additional checks cover the composer, settings and extension Worker timeout, streaming and explicit recovery |
|
|
437
|
+
| `0.6.2` | Packed legacy-WebView boot, touch scrolling and missing-API/viewport negative controls passed on `0.2.0-rc.2`, with release CI passing. The reporter's physical old devices in #187 were not claimed as accepted |
|
|
438
|
+
| `0.6.0` | `0.1.7-alpha.2`, `0.1.7-rc.1`, `0.1.7-rc.2`, `0.2.0-rc.1` and `0.2.0-rc.2` (packed installation, pairing, mobile-page boot and WebSocket Workspace reads); additional checks cover the mobile composer, module settings and component loading after a normal official Desktop restart |
|
|
439
|
+
| `0.5.5` | `0.1.7-alpha.2`, `0.1.7-rc.1`, `0.1.7-rc.2`, `0.2.0-rc.1`, and `0.2.0-rc.2` (npm installation, isolated pairing, mobile-page boot, and WebSocket Workspace baseline) |
|
|
434
440
|
| `0.5.4` | `0.1.7-alpha.2`, `0.1.7-rc.1`, `0.1.7-rc.2`, `0.2.0-rc.1`, and `0.2.0-rc.2` (npm installation, isolated pairing, mobile-page boot, and WebSocket Workspace baseline) |
|
|
435
441
|
| `0.5.3` | `0.1.7-alpha.2`, `0.1.7-rc.1`, `0.1.7-rc.2`, `0.2.0-rc.1`, and `0.2.0-rc.2` (source contract, npm installation, isolated pairing, mobile-page boot, and WebSocket Workspace baseline) |
|
|
436
442
|
| `0.5.2` | `0.1.7-alpha.2`, `0.1.7-rc.1`, `0.1.7-rc.2`, and `0.2.0-rc.1` (carried forward from earlier verification); `0.2.0-rc.2` (source contract, isolated pairing, mobile-page boot, and WebSocket Workspace baseline) |
|
package/README.md
CHANGED
|
@@ -26,13 +26,13 @@
|
|
|
26
26
|
<a href="#兼容性">兼容性</a> ·
|
|
27
27
|
<a href="docs/README.md">文档</a> ·
|
|
28
28
|
<a href="#贡献者">贡献者</a> ·
|
|
29
|
-
<a href="https://github.com/saya-ch/dsh-mobile/releases/tag/v0.6.
|
|
29
|
+
<a href="https://github.com/saya-ch/dsh-mobile/releases/tag/v0.6.18">更新记录</a> ·
|
|
30
30
|
<a href="README.en.md">English</a>
|
|
31
31
|
</p>
|
|
32
32
|
|
|
33
33
|
> DSH Mobile 是 DeepSeek Harness 社区插件,原生 App 仅支持 Android。
|
|
34
34
|
>
|
|
35
|
-
> **当前正式版本:0.6.
|
|
35
|
+
> **当前正式版本:0.6.18**。远程目录选择支持新建文件夹,导航和按钮更紧凑,为文件夹列表留出更多空间;修复过期模块配置导致无法进入页面的问题,并增加受控 NAS 管理入口。Android App 独立发布,现有 **0.6.7** 可使用本次插件功能。[插件更新与下载](https://github.com/saya-ch/dsh-mobile/releases/tag/v0.6.18) · [完整更新记录](CHANGELOG.md)。
|
|
36
36
|
>
|
|
37
37
|
> **版本说明**:自插件 **0.6.2** 起,Android App 与插件独立编号、独立发布,版本号无需一致;插件升级不代表 App 需要同步升级。[兼容说明](#兼容性)。
|
|
38
38
|
|
|
@@ -130,7 +130,7 @@ dsh plugin --profile web add dshmarket
|
|
|
130
130
|
|
|
131
131
|
侧栏底部有其他插件入口时,**移动访问**会收起为手机图标;悬停可查看名称,点击仍打开原面板。独占该区域时恢复文字显示。
|
|
132
132
|
|
|
133
|
-
端口说明:`dsh web --port` 修改 DSH Web 上游端口(默认 3080),插件会自动跟随;`dsh-mobile setup --port` 修改 Mobile HTTPS 监听端口(默认 3443
|
|
133
|
+
端口说明:`dsh web --port` 修改 DSH Web 上游端口(默认 3080),插件会自动跟随;`dsh-mobile setup --port` 修改 Mobile HTTPS 监听端口(默认 3443),配对二维码会包含实际端口。若 DSH Desktop 以 `--port 0` 随机端口启动,网关跟随的是**当前实际端口**,`mobile-access/setup.json` 里的 `upstreamOrigin` 只是首次配置的快照,插件启动时会把它更新为当前端口——排查时不要把它当成网关实际使用的上游。
|
|
134
134
|
|
|
135
135
|
<details>
|
|
136
136
|
<summary>无界面主机、内网代理与额外来源网段</summary>
|
|
@@ -418,20 +418,25 @@ macOS 上局域网、cloudflared、自建 FRP 与自有反向代理可用;Funn
|
|
|
418
418
|
| `0.6.11` | `0.1.7-alpha.2`、`0.1.7-rc.1`、`0.1.7-rc.2`、`0.2.0-rc.1`、`0.2.0-rc.2`、`0.2.1-alpha.2`、`0.2.1-alpha.3` 的隔离打包浏览器 CI;`0.2.0-rc.2` 与 `0.2.1-alpha.3` 另通过真实历史分页、滚动位置保持和手动加载检查。浏览器检查不代表所有手机内核、第三方插件或公网线路已验收 |
|
|
419
419
|
| `0.6.12` | `0.2.1-rc.2` 的打包安装、移动启动、缺失 API 模拟、工作区实时读取、保留页面的断线恢复及移动设置;`0.2.0-rc.2` 搭配实际社区认证插件 `dsh-web-startup-auth@0.1.12` 的认证与资源回归。未将 Chromium 92 真机、任意认证插件或公网线路写成已验收 |
|
|
420
420
|
| `0.6.13` | `0.2.0-rc.2`、`0.2.1-rc.2` 的打包图文 HTTP 400 恢复、Host 拒绝护栏与错误提示回归;网关 408/431 分类、三类受限诊断及四种 Gateway 工厂接线通过本地测试。DSH 源码、iroh P2P 和 Android 原生代码不在本版范围 |
|
|
421
|
+
| `0.6.14` | 8 个 DSH 版本(`0.1.7-alpha.2`–`0.2.1-rc.2`)的发布 CI 打包浏览器作业全绿;本版未记录额外的逐版本人工验收范围 |
|
|
422
|
+
| `0.6.15` | `0.2.1-rc.2` 的 Firefox 158 隐私模式真实管理面板配对、HTTPS 移动页面与工作区读取基线,以及静音 Blob 播放;发布 CI 8 版本全绿 |
|
|
423
|
+
| `0.6.16` | `0.2.1-rc.2` 的相册选择、纯文本草稿经公开 DSH 输入接口传输、真实 mux 恢复与跨客户端待答问题;CI 另覆盖 `0.1.7-alpha.2`、`0.1.7-rc.1`、`0.1.7-rc.2`、`0.2.0-rc.1`、`0.2.0-rc.2`、`0.2.1-alpha.2`、`0.2.1-alpha.3` |
|
|
424
|
+
| `0.6.18` | `0.2.1-rc.2` 上的 18 项真实打包 Chromium 目录选择检查,含紧凑布局、目录创建和取消;本机官方 Desktop `0.2.1-rc.3` 已装入候选并启用局域网与 Cloudflare 网关 |
|
|
425
|
+
| `0.6.17` | `0.2.0-rc.2`、`0.2.1-rc.2` 的 15 项真实打包 Chromium 目录选择检查、旧 WebView 缺失 API 模拟与工作区 mux 读取;发布后装入官方 Desktop `0.2.1-rc.2` 并核对包内文件一致 |
|
|
421
426
|
|
|
422
427
|
<details>
|
|
423
428
|
<summary>历史版本验证记录</summary>
|
|
424
429
|
|
|
425
430
|
| DSH Mobile 插件 | 验证支持的 DeepSeek Harness 版本 |
|
|
426
431
|
| ----------------------------------------- | -------------------------------------------------------------- |
|
|
427
|
-
| `0.5.5` | `0.1.7-alpha.2`、`0.1.7-rc.1`、`0.1.7-rc.2`、`0.2.0-rc.1`、`0.2.0-rc.2`(npm 打包安装、隔离配对、移动页面启动及 WebSocket 工作区读取) |
|
|
428
|
-
| `0.6.0` | `0.1.7-alpha.2`、`0.1.7-rc.1`、`0.1.7-rc.2`、`0.2.0-rc.1`、`0.2.0-rc.2`(打包安装、配对、移动页面启动与 WebSocket 工作区读取);另验证移动输入栏、模块设置及官方 Desktop 正常重启后的组件加载 |
|
|
429
|
-
| `0.6.2` | `0.2.0-rc.2` 的打包旧 WebView 启动、触屏滚动与缺失 API/视口负对照通过;发布 CI 通过。未将 #187 报告者的实际旧设备写成已验收 |
|
|
430
|
-
| `0.6.3` | `0.2.0-rc.2`、`0.2.1-alpha.2`(打包安装、隔离配对、移动页面与 WebSocket 工作区读取);另验证输入栏、设置与扩展 Worker 的超时、流式传输和显式恢复 |
|
|
431
|
-
| `0.6.4` | `0.2.0-rc.2`(打包安装、隔离配对、移动页面与 WebSocket 工作区读取);另验证 72 组真实公共插槽输入栏布局、Windows Desktop 目录选择器组合及跨平台回归。社区 Desktop 2.0.17 的原报告远程超时仍未宣称验收 |
|
|
432
|
-
| `0.6.5` | `0.2.0-rc.2`、`0.2.1-alpha.2` 的打包模块管理与移动设置回归;另验证 Windows cpolar 解包及正式 `maid-atelier` 0.1.7 下有内容轨迹的布局修复。不代表全部第三方皮肤或报告者设备已验收 |
|
|
433
|
-
| `0.6.6` | `0.2.0-rc.2`、`0.2.1-alpha.2` 的打包附件接收与图片预览回归,覆盖多图、取消、迟到结果和旧请求;Android 系统选择器改进独立发布,不包含在 npm 更新中 |
|
|
434
432
|
| `0.6.8` | `0.2.1-alpha.3` 的打包移动页面、旧 WebView API 模拟、WebSocket 工作区读取、移动设置、模块管理、侧栏及输入栏回归;身份修复另有真实 HTTP/TLS 与旧凭据升级测试。本机官方 Desktop `0.2.0-rc.2` 已加载该版本插件,原配对保留;不代表手机 5G 或全部第三方插件组合已验收 |
|
|
433
|
+
| `0.6.6` | `0.2.0-rc.2`、`0.2.1-alpha.2` 的打包附件接收与图片预览回归,覆盖多图、取消、迟到结果和旧请求;Android 系统选择器改进独立发布,不包含在 npm 更新中 |
|
|
434
|
+
| `0.6.5` | `0.2.0-rc.2`、`0.2.1-alpha.2` 的打包模块管理与移动设置回归;另验证 Windows cpolar 解包及正式 `maid-atelier` 0.1.7 下有内容轨迹的布局修复。不代表全部第三方皮肤或报告者设备已验收 |
|
|
435
|
+
| `0.6.4` | `0.2.0-rc.2`(打包安装、隔离配对、移动页面与 WebSocket 工作区读取);另验证 72 组真实公共插槽输入栏布局、Windows Desktop 目录选择器组合及跨平台回归。社区 Desktop 2.0.17 的原报告远程超时仍未宣称验收 |
|
|
436
|
+
| `0.6.3` | `0.2.0-rc.2`、`0.2.1-alpha.2`(打包安装、隔离配对、移动页面与 WebSocket 工作区读取);另验证输入栏、设置与扩展 Worker 的超时、流式传输和显式恢复 |
|
|
437
|
+
| `0.6.2` | `0.2.0-rc.2` 的打包旧 WebView 启动、触屏滚动与缺失 API/视口负对照通过;发布 CI 通过。未将 #187 报告者的实际旧设备写成已验收 |
|
|
438
|
+
| `0.6.0` | `0.1.7-alpha.2`、`0.1.7-rc.1`、`0.1.7-rc.2`、`0.2.0-rc.1`、`0.2.0-rc.2`(打包安装、配对、移动页面启动与 WebSocket 工作区读取);另验证移动输入栏、模块设置及官方 Desktop 正常重启后的组件加载 |
|
|
439
|
+
| `0.5.5` | `0.1.7-alpha.2`、`0.1.7-rc.1`、`0.1.7-rc.2`、`0.2.0-rc.1`、`0.2.0-rc.2`(npm 打包安装、隔离配对、移动页面启动及 WebSocket 工作区读取) |
|
|
435
440
|
| `0.5.4` | `0.1.7-alpha.2`、`0.1.7-rc.1`、`0.1.7-rc.2`、`0.2.0-rc.1`、`0.2.0-rc.2`(npm 打包安装、隔离配对、移动页面启动及 WebSocket 工作区读取) |
|
|
436
441
|
| `0.5.3` | `0.1.7-alpha.2`、`0.1.7-rc.1`、`0.1.7-rc.2`、`0.2.0-rc.1`、`0.2.0-rc.2`(源码契约、npm 打包安装、隔离配对、移动页面启动及 WebSocket 工作区读取) |
|
|
437
442
|
| `0.5.2` | `0.1.7-alpha.2`、`0.1.7-rc.1`、`0.1.7-rc.2`、`0.2.0-rc.1`(延续既有验证);`0.2.0-rc.2`(源码契约、隔离配对、移动页面启动和 WebSocket 工作区读取) |
|
package/SECURITY.md
CHANGED
|
@@ -18,7 +18,7 @@ The maintainer will acknowledge a complete report within seven days. Publication
|
|
|
18
18
|
|
|
19
19
|
- Keep the ordinary DSH Web listener on loopback.
|
|
20
20
|
- Expose only the plugin-owned HTTPS listener to the LAN.
|
|
21
|
-
-
|
|
21
|
+
- By default, the desktop admin API accepts only direct loopback peers and a loopback, RFC1918 or IPv4 link-local Host. Explicit `adminAllowedCidrs` can admit additional direct peers, but each non-loopback request must also pass DSH's current request authentication; a network or source marker is not an identity. Missing authentication support fails closed. Do not publicly forward `/api/mobile-access`; proxy access control, authentication and the existing Host/Origin restrictions remain required. See [NAS administration](docs/TRUSTED_NETWORKS.en.md#accessing-the-nas-administration-page).
|
|
22
22
|
- Mutating Web admin requests normally require a same-origin `Origin`. When a browser omits it, the plugin accepts only a JSON POST with its exact non-simple Web marker and absent or `same-origin` Fetch Metadata. Explicit foreign Origins/sites remain rejected. This marker is not a credential: its CSRF protection relies on browser CORS enforcement and the management prefix refusing OPTIONS without CORS permission. A trusted reverse proxy must not answer allowed CORS preflights or inject CORS authorization for `/api/mobile-access`.
|
|
23
23
|
- Official DSH Desktop uses a separate path: its forwarder strips `Origin` and `Sec-Fetch-Site` and supplies a signed Host browser-session Cookie. The plugin requires both its separate Desktop marker and Connection's successful browser-session verification before accepting an Origin-less Desktop write. The Web marker cannot replace that authentication.
|
|
24
24
|
### Discovery, pairing and TLS
|
package/cordis.patch.yml
CHANGED
|
@@ -1,15 +1,11 @@
|
|
|
1
1
|
# Community bundle for the stock DSH Web profile. Installation contributes a
|
|
2
2
|
# Host gateway and a browser Client face; it does not patch DSH source files.
|
|
3
3
|
#
|
|
4
|
-
#
|
|
5
|
-
#
|
|
6
|
-
#
|
|
7
|
-
#
|
|
8
|
-
#
|
|
9
|
-
# `directoryPicker` service, which makes the "Add workspace" action and its
|
|
10
|
-
# Ctrl+O shortcut disappear. The dedicated Mobile page registers its own in-page
|
|
11
|
-
# flow from the client face instead (see src/client.ts), so the desktop keeps its
|
|
12
|
-
# native OS chooser without a second Host entry.
|
|
4
|
+
# Leave DSH's adaptive Host/Client directory-picker pair intact. A second Host
|
|
5
|
+
# provider conflicts with its single service; disabling the default can leave
|
|
6
|
+
# workspace actions without a picker. The dedicated Mobile page reuses an
|
|
7
|
+
# upstream browse surface when present and otherwise registers its own web flow
|
|
8
|
+
# through public workspace slots, without replacing the Desktop's system chooser.
|
|
13
9
|
- insert:
|
|
14
10
|
- id: mobile-access
|
|
15
11
|
name: dsh-mobile
|
|
@@ -28,18 +28,42 @@ Plugin 0.6.16 adds Chinese, English and Italian field-level feedback: submission
|
|
|
28
28
|
## Public-CA mode
|
|
29
29
|
|
|
30
30
|
1. In **Self-hosted FRP**, choose **Attach to my existing frps** and **Public CA certificate**. Enter the VPS address, frps control port, high-entropy shared token, public domain or IPv4 HTTPS origin, and the frps instance's actual `vhostHTTPPort`. Do not assume the managed deployment's default of 7080.
|
|
31
|
-
2. Copy the attachment plan. Confirm the plaintext vhost is loopback-only, then add the generated Caddy snippet and `import` manually. Caddy manages domain certificates. For public IPv4, the current plan pins Certbot 5.8.0 and uses `--standalone --preferred-profile shortlived --ip-address` for a [roughly six-day Let's Encrypt IP certificate](https://letsencrypt.org/2026/03/11/shorter-certs-certbot). Standalone issuance briefly stops Caddy to free port 80 and may interrupt other sites on the VPS; schedule a maintenance window, choose a domain, or use the self-signed TCP mode in app 0.4.6 or later if that interruption is unacceptable. The attach path only checks an existing `certbot.timer`; it does not install renewal or a certificate-copy/reload hook. Arrange renewal, installation into Caddy, and reload before expiry yourself. Copying the plan does not change the VPS.
|
|
31
|
+
2. Copy the attachment plan. Confirm the plaintext vhost is loopback-only, then add the generated Caddy snippet at `/etc/caddy/dsh-mobile-dsh.caddy` and its `import` line at the top of the Caddyfile manually. Caddy manages domain certificates. For public IPv4, the current plan pins Certbot 5.8.0 and uses `--standalone --preferred-profile shortlived --ip-address` for a [roughly six-day Let's Encrypt IP certificate](https://letsencrypt.org/2026/03/11/shorter-certs-certbot). Standalone issuance briefly stops Caddy to free port 80 and may interrupt other sites on the VPS; schedule a maintenance window, choose a domain, or use the self-signed TCP mode in app 0.4.6 or later if that interruption is unacceptable. The attach path only checks an existing `certbot.timer`; it does not install renewal or a certificate-copy/reload hook. Arrange renewal, installation into Caddy, and reload before expiry yourself. Copying the plan does not change the VPS.
|
|
32
32
|
3. Install the pinned official `frpc` on the computer, save and verify the connection, and test `/mobile-access/discovery` from an independent external network with normal certificate validation. Confirm HTTP 200 and this computer's installation identifier before pairing through the app's **Remote access** flow or a phone browser. A local self-check alone does not verify public reachability.
|
|
33
33
|
|
|
34
34
|
## Self-signed passthrough mode
|
|
35
35
|
|
|
36
36
|
The computer-side gateway terminates TLS with a five-year CA and 397-day public-IPv4 leaf. The leaf can renew under the same CA; an expired or replaced CA requires a new fingerprint check and pairing. QR links and App keys carry the CA-required `dsh2` marker, rejected by older apps. Supported apps keep this CA in their private connection records, never Android's system trust store.
|
|
37
37
|
|
|
38
|
+
> Topology: `phone ──HTTPS(:33080)──▶ frps TCP proxy (passthrough) ──encrypted tunnel──▶ local frpc ──▶ 127.0.0.1:<gateway HTTPS port> ──▶ dsh web 127.0.0.1:3080`
|
|
39
|
+
|
|
38
40
|
1. In **Self-hosted FRP**, enter the VPS address, frps control port, token, and `https://YOUR_PUBLIC_IPV4`. Choose **Attach to my existing frps**, **Self-signed passthrough**, and the public TCP port (default 33080; not 3080, 3443, or 3444).
|
|
39
41
|
2. Copy and review the masked `frpc.toml` and VPS checklist. This is read-only: finish the server checks before selecting **Save and verify connection**.
|
|
40
42
|
3. On the VPS, allow the chosen TCP entry port in its host firewall and cloud security group; the existing frps control port must already be reachable from the computer. Confirm frps is running and the TCP proxy listens on an address reachable from the public network. The plugin does not change the server's frps configuration or firewall.
|
|
43
|
+
|
|
44
|
+
```sh
|
|
45
|
+
ufw allow 33080/tcp
|
|
46
|
+
ufw status | grep 33080
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
With firewalld or a cloud security group, allow the same **TCP 33080**. Then check the frps service and its listeners (use your own service manager if frps does not run under systemd):
|
|
50
|
+
|
|
51
|
+
```sh
|
|
52
|
+
systemctl is-active frps || true
|
|
53
|
+
ss -lnt | grep -E ':(<your bindPort>|33080)\b' || true
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
The control port should already be listening. A proxy entry such as 33080 usually appears only after frpc registers successfully, so check its actual address once the connection is up.
|
|
41
57
|
4. Install official frpc and select **Save and verify connection**. The plugin now writes the config in private `remote/frp/config/` (Unix `0600`, restricted Windows ACL), then runs `frpc verify` before startup. Clear the clipboard if you explicitly copied a token-bearing config. A public TCP proxy port normally appears only after frpc registers; check its actual listener then.
|
|
42
|
-
5. From another network, check
|
|
58
|
+
5. From another network, check the public entry end to end, replacing the host and port with your own:
|
|
59
|
+
|
|
60
|
+
```sh
|
|
61
|
+
# Replace YOUR_PUBLIC_IPV4 and 33080, then run this from an external network.
|
|
62
|
+
curl -k -sS -o /dev/null -w '%{http_code}\n' https://YOUR_PUBLIC_IPV4:33080/mobile-access/discovery
|
|
63
|
+
# Expected output: 200. `-k` skips curl's certificate check and proves reachability only, not identity.
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
HTTP 200 proves reachability only: `-k` does not verify identity. Pair through **Remote access** in app 0.4.6 or later; it fetches the CA without device credentials, checks the `dsh2` fingerprint and pins the exact Origin. CA HTTP 404 cannot fall back to platform trust. An Origin or CA change requires new pairing.
|
|
43
67
|
|
|
44
68
|
## Troubleshooting and cleanup
|
|
45
69
|
|
|
@@ -53,5 +77,11 @@ The computer-side gateway terminates TLS with a five-year CA and 397-day public-
|
|
|
53
77
|
| `frp_proxy_name_in_use` | frps keeps proxy names unique across **all** its clients, and this installation's own name (`dsh-mobile-<first 12 characters of the installation identity>`) is already registered — usually another DSH computer, or this computer's previous session before the frps heartbeat expires it. Disable self-hosted FRP there, or remove that proxy on the frps. frpc keeps running without publishing the entry port, so check proxy registration rather than relying on process liveness. |
|
|
54
78
|
| `frp_remote_port_in_use` | Another proxy on the same frps already owns the chosen entry port. Ports are first-come, first-served per server, so give this computer a different `publicPort` and allow it in the firewall. |
|
|
55
79
|
| Public entry unreachable | Check the chosen port, cloud and host firewalls, frps listener address, running `frpc`, and the external-network probe. A computer-side probe is not proof that a phone can connect. |
|
|
80
|
+
| App reports "connected to another DSH" | The public entry points at a different DSH: check `remotePort`, and confirm frpc is running on this computer. |
|
|
81
|
+
|
|
82
|
+
## Relation to the other channels
|
|
83
|
+
|
|
84
|
+
- The **`origin` own-reverse-proxy channel** (default 3444) is a separate path: TLS is terminated by **your own external proxy** and it is independent of this mode.
|
|
85
|
+
- **Deploy mode** (the plugin installs frps + Caddy) is unchanged and still needs SSH; attach mode needs **zero SSH**.
|
|
56
86
|
|
|
57
87
|
**Remove FRP completely** deletes only plugin-managed FRP files on the computer, including the local `frpc` configuration and self-signed ingress material. The non-secret plugin `installation-id` remains so a later FRP connection keeps the same proxy name; removing all DSH Mobile private state removes that identifier too. The attach path never deletes or restarts your existing frps, Caddy site, certificates, or firewall rules on the VPS. Managed deployment and its separate server cleanup are described in the [self-hosted FRP guide](SELF_HOSTED_FRP.en.md).
|
|
@@ -77,7 +77,7 @@
|
|
|
77
77
|
|
|
78
78
|
### 3. 本机连接,再让手机配对
|
|
79
79
|
|
|
80
|
-
5. 按需安装官方 frpc
|
|
80
|
+
5. 按需安装官方 frpc,点击「保存配置并验证连接」。配置此时才写入私有 `remote/frp/config/frpc.toml`(Unix `0600`,Windows 受限 ACL),启动前运行 `frpc verify`。若明确复制过含 Token 的配置,请及时清理剪贴板。
|
|
81
81
|
|
|
82
82
|
6. 在电脑面板「远程访问」生成**远程配对二维码 / 配对链接**(含 CA 指纹、一次性 Token 和必须固定 CA 的 `dsh2` 标记)。
|
|
83
83
|
7. 用 Android App 扫码(或粘贴链接)完成配对,即可远程进入 DSH。
|
|
@@ -102,7 +102,7 @@ curl -k -sS -o /dev/null -w '%{http_code}\n' https://YOUR_PUBLIC_IPV4:33080/mobi
|
|
|
102
102
|
| `frp_attach_cert_unknown` | 自签入口证书缺失或不可读;检查面板证书状态与私有目录的 `remote/ingress/`,不要绕过指纹验证。 |
|
|
103
103
|
| `frp_ingress_ca_expired` | 自签 CA 已过期,插件不会静默替换受信任 CA;重新生成 CA 后,手机须核对新指纹并重新配对。Android App 0.6.3 及更新版本仍可读取、删除该设备记录,但 TLS 继续拒绝过期证书。若使用 0.6.2 或更早版本且设备库因此不可读,请保留 App 数据,并按 [App 手册](../apps/mobile/README.zh-CN.md)安装 0.6.3 或更新的同签名正式版,不要为一台电脑清除全部配对。 |
|
|
104
104
|
| 手机浏览器提示证书不受信任 | 自签档的正常现象;请在 App 内配对使用 |
|
|
105
|
-
|
|
|
105
|
+
| 自检显示「公网入口 TCP 端口不可达」 | 端口未放行、frpc 未启动,或 frps 未把该 `remotePort` 转发出来 |
|
|
106
106
|
| `frp_proxy_name_in_use` | frps 的代理名在**整台服务器**上唯一。本机安装名(`dsh-mobile-<安装标识前 12 位>`)已被占用:多半是另一台 DSH 电脑,或本机上一次连接尚未等到 frps 心跳超时。到那台机器上关闭自建 FRP,或在 frps 上移除该代理。frpc 此时仍在运行、只是入口端口没被发布,应检查代理是否注册成功,不能仅凭进程存在判断就绪。 |
|
|
107
107
|
| `frp_remote_port_in_use` | 同一台 frps 上该入口端口已被别的代理占用(端口先到先得)。给这台电脑换一个 `publicPort`,并在防火墙/安全组放行。 |
|
|
108
108
|
| App 报「连接到另一台 DSH」 | 公网入口指向了别的 DSH:检查 `remotePort` 与 frpc 是否在本机运行 |
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
# Mobile plugin adaptation guide
|
|
2
|
+
|
|
3
|
+
[中文](MOBILE_PLUGIN_ADAPTATION.md) · [Documentation index](README.md)
|
|
4
|
+
|
|
5
|
+
This guide is for DSH plugin authors, aiming for **usable small screens without desktop regressions**. DSH Mobile provides connectivity, page layout and shared entry points; it does not rearrange every third-party plugin's internal controls. Start in a browser, then add device acceptance; an Android device is not required to begin.
|
|
6
|
+
|
|
7
|
+
## Identify where the panel is mounted
|
|
8
|
+
|
|
9
|
+
| Current mobile-page behavior | What the plugin should do |
|
|
10
|
+
| --- | --- |
|
|
11
|
+
| Opening a panel in the `main` slot adds a “Back to conversation” bar above it | Use the container's actual available height. The bar is at least 56px high; safe areas and content can increase it. Do not subtract a fixed 56px from screen height |
|
|
12
|
+
| The narrow sidebar is a drawer no wider than `min(88vw, 340px)`; a wide layout can keep it persistent | Do not assume a fixed 340px sidebar. Let entry labels and buttons shrink |
|
|
13
|
+
| The mobile layout has `.dshm-shell`, `[data-pane="conversation"]` and `[data-pane="sidebar"]` markers | Use these to locate regions while diagnosing. Scope internal styles to the plugin's own root rather than private host CSS class names |
|
|
14
|
+
| The mobile shell gives inputs and editable areas a 16px font floor while retaining larger inherited sizes | Leave room for editing, rather than counteracting user preferences with a smaller fixed font |
|
|
15
|
+
| Adapted shared entry points do not guarantee arbitrary third-party hit areas | Plugin authors must still check buttons, close actions, checkboxes and menus for actual hit testing |
|
|
16
|
+
|
|
17
|
+
These describe the current layout, not fixed dimensions a plugin should copy. Overlays, sidebars and main panels have different available space; verify the actual mounting location.
|
|
18
|
+
|
|
19
|
+
## Adapt to available space
|
|
20
|
+
|
|
21
|
+
Make the base layout shrink first: give flex/grid children `min-width: 0`, let toolbars wrap, and use content-driven height. Panel width is not always viewport width: a 400px panel in a desktop sidebar needs compact layout too.
|
|
22
|
+
|
|
23
|
+
For arrangement-only changes, CSS container queries are an option; full-page viewport adaptation can still use media queries. The `600px` below is an example breakpoint, to be chosen for the plugin's content:
|
|
24
|
+
|
|
25
|
+
```css
|
|
26
|
+
.plugin-panel-host { container-type: inline-size; min-width: 0; }
|
|
27
|
+
.plugin-panel { min-width: 0; }
|
|
28
|
+
.plugin-panel .toolbar { display: flex; flex-wrap: wrap; gap: 8px; }
|
|
29
|
+
|
|
30
|
+
@container (max-width: 600px) {
|
|
31
|
+
.plugin-panel .toolbar { display: grid; grid-template-columns: minmax(0, 1fr); }
|
|
32
|
+
}
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
Wrap `.plugin-panel` in `.plugin-panel-host`. On engines without container queries, the base wrapping and fluid widths should remain usable; do not put an essential action solely in the query branch.
|
|
36
|
+
|
|
37
|
+
When a script branch is necessary, observe the component's root width instead of classifying a phone by user agent:
|
|
38
|
+
|
|
39
|
+
```js
|
|
40
|
+
const rootRef = useRef(null)
|
|
41
|
+
const [panelWidth, setPanelWidth] = useState(null)
|
|
42
|
+
const isNarrow = panelWidth !== null && panelWidth <= 600
|
|
43
|
+
|
|
44
|
+
useEffect(() => {
|
|
45
|
+
const element = rootRef.current
|
|
46
|
+
if (element === null) return undefined
|
|
47
|
+
const measure = () => setPanelWidth(element.getBoundingClientRect().width)
|
|
48
|
+
measure()
|
|
49
|
+
window.addEventListener('resize', measure)
|
|
50
|
+
const observer = typeof window.ResizeObserver === 'function' ? new window.ResizeObserver(measure) : null
|
|
51
|
+
observer?.observe(element)
|
|
52
|
+
return () => {
|
|
53
|
+
window.removeEventListener('resize', measure)
|
|
54
|
+
observer?.disconnect()
|
|
55
|
+
}
|
|
56
|
+
}, [])
|
|
57
|
+
|
|
58
|
+
// The component's returned root; keep a usable base layout before the first measurement.
|
|
59
|
+
h('section', { ref: rootRef, className: 'plugin-panel', 'data-narrow': isNarrow ? 'true' : 'false' }, contents)
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
Without ResizeObserver, this fallback only measures again on window resize. If a panel resizes independently, also use the plugin's existing layout notifications. Dispose observers and listeners when the component unmounts.
|
|
63
|
+
|
|
64
|
+
## Adaptation checklist
|
|
65
|
+
|
|
66
|
+
### Touch targets and spacing
|
|
67
|
+
|
|
68
|
+
This project recommends at least a **44×44 CSS px** hit area for primary Web controls, with 48px for primary actions where space permits; these are not conversions from Android dp or iOS pt. Leave space between adjacent actions rather than extending targets over their neighbors.
|
|
69
|
+
|
|
70
|
+
```css
|
|
71
|
+
.plugin-panel :is(button, select, input:not([type="checkbox"]):not([type="radio"])) { min-height: 44px; }
|
|
72
|
+
.plugin-panel .icon-button { min-width: 44px; }
|
|
73
|
+
.plugin-panel .actions { display: flex; flex-wrap: wrap; gap: 8px; }
|
|
74
|
+
.plugin-panel .check-label { box-sizing: border-box; display: inline-flex; align-items: center; gap: 8px; min-width: 44px; min-height: 44px; padding-inline: 8px; }
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
Put a small checkbox inside its associated `label` to enlarge the clickable label without enlarging the icon. Use actual taps and `elementFromPoint()` to check edge hits; a declared `min-height` can still be shrunk, clipped or obscured by layout.
|
|
78
|
+
|
|
79
|
+
### Filters, tabs and inline actions
|
|
80
|
+
|
|
81
|
+
Long filter strips can wrap or use their own horizontally scrollable container; do not make the whole page overflow horizontally. Retain visible focus and enough padding to bring the last item fully into view:
|
|
82
|
+
|
|
83
|
+
```css
|
|
84
|
+
.plugin-panel .chips { display: flex; gap: 8px; overflow-x: auto; padding: 4px; }
|
|
85
|
+
.plugin-panel .chip { flex: 0 0 auto; min-height: 44px; }
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
An unambiguous inline action can become an icon on narrow panels, provided it keeps an accessible name and, where needed, a text explanation in a menu. Hover text cannot be the only explanation on a phone.
|
|
89
|
+
|
|
90
|
+
```js
|
|
91
|
+
h('button', { className: 'icon-button', 'aria-label': label }, h(Icon, { 'aria-hidden': true, name: 'play' }))
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
A narrow panel does not imply the absence of a keyboard. Decorative shortcut badges can collapse, but retain functioning shortcuts, help, Tab order and visible focus; do not remove keyboard-accessible behavior solely by width.
|
|
95
|
+
|
|
96
|
+
### Type, density and complete information
|
|
97
|
+
|
|
98
|
+
Inherit DSH's fonts and semantic colors. To follow the mobile page's text setting, a plugin can use `--dsh-content-font-size` on its content root and retain inheritance when the variable is absent:
|
|
99
|
+
|
|
100
|
+
```css
|
|
101
|
+
.plugin-panel { font-size: var(--dsh-content-font-size, inherit); line-height: 1.5; }
|
|
102
|
+
.plugin-panel .meta { color: var(--dsw-alias-label-secondary, currentColor); }
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
Compress decorative headings and whitespace, not touch targets. Let long titles wrap or offer an accessible way to view them in full. Errors, pending confirmations and essential action names must not exist only as truncated text. Check larger text, long paths and Chinese/English content.
|
|
106
|
+
|
|
107
|
+
### Overlays, forms and scrolling
|
|
108
|
+
|
|
109
|
+
Constrain overlays to their actual container and visible area, rather than using fixed dimensions that push actions off-screen. Reuse DSH's existing overlay components first; a custom overlay needs an accessible close action, focus management and Escape behavior.
|
|
110
|
+
|
|
111
|
+
```css
|
|
112
|
+
.plugin-panel .form-row { display: grid; grid-template-columns: minmax(0, 1fr); gap: 8px; }
|
|
113
|
+
.plugin-panel .scroll-body { min-height: 0; overflow: auto; overscroll-behavior: contain; }
|
|
114
|
+
.plugin-panel textarea { box-sizing: border-box; width: 100%; min-height: 96px; }
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
Add `env(safe-area-inset-*)` only where content really reaches a screen edge and the host has not already handled it, avoiding duplicate space. Save, Cancel and errors must remain visible or reachable by scrolling with the keyboard open. An independent scroll area should not move the page underneath.
|
|
118
|
+
|
|
119
|
+
## Verification: what code checks, browsers and devices establish
|
|
120
|
+
|
|
121
|
+
### Structural checks
|
|
122
|
+
|
|
123
|
+
Unit tests can check narrow branches, accessible names, retained state and unmount cleanup. Server rendering does not run browser layout measurement; supplying a test width or layout stub only establishes the chosen branch, not actual dimensions, hit testing or pixel-identical desktop output. A `44px` string in CSS is not touch acceptance.
|
|
124
|
+
|
|
125
|
+
### Real browser checks
|
|
126
|
+
|
|
127
|
+
Mount the plugin in an actual DSH page and cover at least 375px and 390px narrow viewports, landscape, full-width desktop and a narrow desktop sidebar. If a static preview is maintained, load it in a browser too and describe its differences from the real host.
|
|
128
|
+
|
|
129
|
+
- Cover list, detail, settings, empty, long-content and error states;
|
|
130
|
+
- Inspect element bounds, clipping ancestors and actual hit targets, including the first and last actions;
|
|
131
|
+
- Use a keyboard to check Tab, Escape and focus restoration, with no accidental background action while an overlay is open;
|
|
132
|
+
- Change width and text size, checking that drafts, selections and expanded state survive;
|
|
133
|
+
- Check light/dark themes and desktop baselines. Explain screenshot changes rather than demanding pixel identity for intentional improvements.
|
|
134
|
+
|
|
135
|
+
For example, after opening the real panel through its existing entry point, Playwright can check a control's geometry and hit testing. Replace the following selector with the plugin's own stable marker:
|
|
136
|
+
|
|
137
|
+
```js
|
|
138
|
+
const action = page.locator('[data-plugin-action="save"]')
|
|
139
|
+
await action.scrollIntoViewIfNeeded()
|
|
140
|
+
const box = await action.boundingBox()
|
|
141
|
+
if (box === null || box.width < 44 || box.height < 44) throw new Error('Save target is too small')
|
|
142
|
+
const hit = await action.evaluate(element => {
|
|
143
|
+
const box = element.getBoundingClientRect()
|
|
144
|
+
return element.contains(document.elementFromPoint(box.x + box.width / 2, box.y + box.height / 2))
|
|
145
|
+
})
|
|
146
|
+
if (!hit) throw new Error('Save target is obscured')
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
A center hit is a starting point, not a substitute for edge taps, scrolling, focus or state checks. See [CONTRIBUTING](../CONTRIBUTING.md#select-behavior-checks) for launch and verification procedures.
|
|
150
|
+
|
|
151
|
+
### Device follow-up
|
|
152
|
+
|
|
153
|
+
Browser emulation does not replace real WebView, keyboard, safe-area, momentum-scroll or external-keyboard acceptance. Record the device, App/WebView versions, connection and actual steps. State unverified parts directly instead of claiming all-platform success.
|
|
154
|
+
|
|
155
|
+
## Templates for plugin authors
|
|
156
|
+
|
|
157
|
+
### Issue
|
|
158
|
+
|
|
159
|
+
```markdown
|
|
160
|
+
## Plugin on a small screen
|
|
161
|
+
- Plugin name and version:
|
|
162
|
+
- DSH, DSH Mobile and App/browser versions:
|
|
163
|
+
- Panel location and available width (main / sidebar / overlay):
|
|
164
|
+
- Reproduction steps, expected and actual behavior:
|
|
165
|
+
- Screenshot and identifiable control (redact credentials and private content):
|
|
166
|
+
- Comparison with other optional frontend modules omitted, if tested:
|
|
167
|
+
|
|
168
|
+
## Acceptance goals
|
|
169
|
+
- [ ] Essential actions are visible and usable; long content is not clipped
|
|
170
|
+
- [ ] Actual touch areas, adjacent spacing and first/last items checked
|
|
171
|
+
- [ ] Keyboard focus, back/close behavior and drafts retained
|
|
172
|
+
- [ ] Overlays and forms work at narrow widths and larger text
|
|
173
|
+
- [ ] No desktop workflow regressions; unverified device behavior identified
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
### PR
|
|
177
|
+
|
|
178
|
+
- [ ] Describe affected entry points and content, without hard-splitting phone/desktop by UA;
|
|
179
|
+
- [ ] Reuse components and state; avoid duplicating business logic when arrangements differ;
|
|
180
|
+
- [ ] Supply real-browser narrow and desktop comparisons, steps and relevant tests;
|
|
181
|
+
- [ ] Check focus, hit testing, long content, errors and cleanup, not only CSS text;
|
|
182
|
+
- [ ] Distinguish verified and unverified device behavior; do not copy another version's results.
|
|
183
|
+
|
|
184
|
+
## Scope
|
|
185
|
+
|
|
186
|
+
This guide draws on community plugin adaptation and [discussion #279](https://github.com/saya-ch/dsh-mobile/discussions/279). It offers reusable implementation and acceptance ideas, not an independent verification of a new third-party release. For theme-specific questions, see [Skins and mobile layout](SKIN_COMPATIBILITY.en.md).
|
|
187
|
+
|
|
188
|
+
DSH Mobile does not maintain a universal override table keyed by third-party private class names, or guarantee that plugins requiring native windows work directly on remote pages. The plugin owning the component should maintain its adaptation through DSH's public extension points. Report missing host capabilities separately rather than modifying installed DSH artifacts to work around them.
|