dsh-mobile-access 1.1.2 → 1.1.3

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.
Files changed (3) hide show
  1. package/README.md +20 -4
  2. package/client.js +51 -1
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -79,7 +79,7 @@ iPhone 打开「设置 → 无线局域网」,确认和 Mac 连的是同一个
79
79
  ### 第 2 步:在 Mac 终端执行一条命令
80
80
 
81
81
  ```bash
82
- dsh plugin --profile web add dsh-mobile-access@1.1.2 --registry=https://registry.npmjs.org/
82
+ dsh plugin --profile web add dsh-mobile-access@1.1.3 --registry=https://registry.npmjs.org/
83
83
  ```
84
84
 
85
85
  这条命令做三件事:
@@ -175,6 +175,19 @@ Safari 分享按钮 → 添加到主屏幕
175
175
  - 插件只在 iPhone / iPad 上安装「Return 换行」监听,Mac 和非 Apple 平台不会安装;
176
176
  - 左边栏只多一个「手机访问」入口,其他入口和面板保持原样。
177
177
 
178
+ ### iPhone 上切换左侧栏会话为什么要两次点击
179
+
180
+ 如果你在左侧栏已经展开、能看到会话标题的情况下,点第一下没有切换、点第二下才切换,
181
+ 这是官方会话行的触摸行为:每一行是 `role="treeitem"`、`tabindex="0"` 的可聚焦元素,
182
+ iOS Safari 会把第一次触摸先用去聚焦,第二次才派发 `click`。
183
+
184
+ 从 `1.1.3` 起,插件只在 iPhone / iPad 上、在你触摸会话行的那一刻临时移除该行的
185
+ `tabindex`,400 毫秒后自动恢复;同时给会话行加 `touch-action: manipulation`,
186
+ 避免旧式双击缩放延迟。Mac 和键盘操作不受影响。展开侧栏后,点一次会话标题即可切换。
187
+
188
+ 如果左侧栏仍然是窄窄的图标条,第一下是展开侧栏——这是官方布局,不是会话行的问题;
189
+ 展开后每个会话只需单击一次。
190
+
178
191
  ### iPhone 上切换大模型时页面放大、键盘自动弹出怎么办
179
192
 
180
193
  从 `1.1.2` 起不需要改 DSH,也不需要关掉 Safari 的缩放:
@@ -351,7 +364,7 @@ iPhone 软键盘没有可用的 Shift 键,因此插件在 **iOS / iPadOS** 上
351
364
  ### 推荐:npm 官方命令
352
365
 
353
366
  ```bash
354
- dsh plugin --profile web add dsh-mobile-access@1.1.2 --registry=https://registry.npmjs.org/
367
+ dsh plugin --profile web add dsh-mobile-access@1.1.3 --registry=https://registry.npmjs.org/
355
368
  ```
356
369
 
357
370
  ### 使用 `@latest`
@@ -466,7 +479,7 @@ dsh plugin --profile web remove dsh-mobile-access
466
479
  - 左侧栏入口消失;
467
480
  - `/m` 恢复为普通 SPA fallback(不再是配对页);
468
481
  - `/api/mobile-access/*` 不再注册;
469
- - iOS 剪贴板回退和 Return 换行监听被清理。
482
+ - iOS 剪贴板回退、Return 换行监听、16px 缩放守卫和模型搜索焦点守卫被清理。
470
483
 
471
484
  已签发的登录 Cookie 可能仍留在浏览器中,直到过期;这是 DSH 认证层的行为,不是插件额外写入的凭证。
472
485
 
@@ -478,7 +491,10 @@ dsh plugin --profile web remove dsh-mobile-access
478
491
  - `1.0.1` — 安装文档与 npm 发布元数据。
479
492
  - `1.0.2` — iPhone / iPad 自带键盘 Return 换行。
480
493
  - `1.0.3` — Safari 不支持改写键盘事件时的换行回退。
481
- - `1.1.0` — 回环监听自动局域网网关(macOS / Windows,HTTP + `/api/remote.mux` WebSocket);当前 npm `latest`。
494
+ - `1.1.0` — 回环监听自动局域网网关(macOS / Windows,HTTP + `/api/remote.mux` WebSocket)。
495
+ - `1.1.1` — iPhone / iPad 上模型选择页 16px 缩放守卫。
496
+ - `1.1.2` — 打开模型选择时不自动弹键盘、不整体上移。
497
+ - `1.1.3` — iPhone / iPad 上会话行第一次点击即可切换;当前 npm `latest`。
482
498
 
483
499
  ## 许可证
484
500
 
package/client.js CHANGED
@@ -167,8 +167,11 @@ const IOS_INPUT_ZOOM_GUARD_CSS = `@media (hover: none) and (pointer: coarse) {
167
167
  button,
168
168
  [role="button"],
169
169
  [role="menuitem"],
170
- [role="menuitemradio"] {
170
+ [role="menuitemradio"],
171
+ [data-row-key^="session:"],
172
+ [role="treeitem"] {
171
173
  touch-action: manipulation;
174
+ -webkit-user-drag: none;
172
175
  }
173
176
  }`;
174
177
  function installIOSInputZoomGuard() {
@@ -188,6 +191,47 @@ function installIOSInputZoomGuard() {
188
191
  * the user deliberately taps that field; blur a focused composer control before
189
192
  * any composer menu opens. Native taps still focus normally, and Mac is untouched.
190
193
  */
194
+ /**
195
+ * Safari treats a touch on a focusable, non-button row as a focus step: the
196
+ * first tap focuses the row and only the second tap reaches its click handler.
197
+ * Official session rows are `role="treeitem"` divs with `tabIndex={0}`, so
198
+ * switching sessions on iPhone takes two taps. Remove that one attribute for
199
+ * the duration of the tap on iOS only; React restores it on the next render and
200
+ * this hook restores it after a short delay, leaving Mac and keyboard access
201
+ * untouched. `touch-action: manipulation` is also applied in the iOS stylesheet
202
+ * to avoid the legacy double-tap-zoom delay.
203
+ */
204
+ function installIOSSidebarTapGuard() {
205
+ if (!isAppleMobile())
206
+ return () => undefined;
207
+ const doc = document;
208
+ const timers = new Set();
209
+ const onTouchStart = (event) => {
210
+ const target = event.target;
211
+ if (target === null || typeof target.closest !== 'function')
212
+ return;
213
+ const row = target.closest('[data-row-key^="session:"]');
214
+ if (row === null)
215
+ return;
216
+ const tabindex = row.getAttribute('tabindex');
217
+ if (tabindex === null)
218
+ return;
219
+ row.removeAttribute('tabindex');
220
+ const timer = window.setTimeout(() => {
221
+ timers.delete(timer);
222
+ if (row.isConnected)
223
+ row.setAttribute('tabindex', tabindex);
224
+ }, 400);
225
+ timers.add(timer);
226
+ };
227
+ doc.addEventListener('touchstart', onTouchStart, true);
228
+ return () => {
229
+ doc.removeEventListener('touchstart', onTouchStart, true);
230
+ for (const timer of timers)
231
+ window.clearTimeout(timer);
232
+ timers.clear();
233
+ };
234
+ }
191
235
  function installIOSModelKeyboardGuard() {
192
236
  if (!isAppleMobile())
193
237
  return () => undefined;
@@ -521,6 +565,12 @@ function factory(require) {
521
565
  catch (error) {
522
566
  ctx.logger?.warn?.(`[mobile-access] iOS model keyboard guard unavailable: ${String(error)}`);
523
567
  }
568
+ try {
569
+ cleanups.push(installIOSSidebarTapGuard());
570
+ }
571
+ catch (error) {
572
+ ctx.logger?.warn?.(`[mobile-access] iOS sidebar tap guard unavailable: ${String(error)}`);
573
+ }
524
574
  return () => {
525
575
  for (const cleanup of cleanups.reverse()) {
526
576
  try {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-mobile-access",
3
- "version": "1.1.2",
3
+ "version": "1.1.3",
4
4
  "description": "Independent DSH bundle that pairs iPhones and iPads with the official DeepSeek Harness Web GUI over the local network.",
5
5
  "type": "module",
6
6
  "license": "MIT",