@qzsy/dsh-bridge 3.4.3 → 3.4.4
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 +14 -0
- package/README.md +1 -1
- package/client/client.js +23 -19
- package/client/mobile.js +24 -15
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
# 更新日志
|
|
2
2
|
|
|
3
|
+
## [v3.4.4] - 2026-11-02
|
|
4
|
+
|
|
5
|
+
### 🐛 修复
|
|
6
|
+
|
|
7
|
+
- **模型 sheet 不再因 blur 关闭**:3.4.3 在 sheet 套用后 `blur` 搜索框,宿主菜单会因 focusout 直接关闭,看起来像「点模型没反应」。现在改为给搜索框加 `readonly` + `inputmode=none`:保留焦点、不弹键盘,宿主菜单稳定打开。
|
|
8
|
+
- **用户主动搜索时恢复输入**:监听搜索框 `pointerdown` / `touchstart`,用户主动点的时候恢复 `readonly` 和 `inputmode` 并聚焦,需要搜索仍可正常输入。
|
|
9
|
+
- 模型列表默认完整显示,不再被 iOS 键盘遮挡。
|
|
10
|
+
|
|
11
|
+
### 🧪 验证
|
|
12
|
+
|
|
13
|
+
- 模拟宿主自动 focus:sheet 保持打开,搜索框 `readOnly=true`、`inputmode=none`;用户 pointerdown 后 `readOnly=false` 且聚焦,4/4 通过。
|
|
14
|
+
- 运行中的 DSH:模型菜单打开后保持存在,sheet/遮罩正常。
|
|
15
|
+
|
|
16
|
+
|
|
3
17
|
## [v3.4.3] - 2026-11-02
|
|
4
18
|
|
|
5
19
|
### 🐛 修复
|
package/README.md
CHANGED
|
@@ -48,7 +48,7 @@ dsh plugin --profile <name> add @qzsy/dsh-bridge
|
|
|
48
48
|
|
|
49
49
|
- 内容区占满屏宽,左上角「菜单」按钮打开会话 / 工作区 / 插件入口;
|
|
50
50
|
- 支持手势:左缘向右滑打开、抽屉内向左滑关闭,拖动时跟手,松手吸附;
|
|
51
|
-
- 模型切换器在手机上改为底部 sheet
|
|
51
|
+
- 模型切换器在手机上改为底部 sheet:全宽、抓手、遮罩,支持下拉/点遮罩关闭;默认不弹键盘(搜索框 `readonly`),需要搜索时再点;
|
|
52
52
|
- 全面屏自动避开安全区:刘海 / 状态栏 / 底部 home indicator 不遮挡内容;
|
|
53
53
|
- 点遮罩、点会话行、按 Esc 或转回桌面宽度都会自动收起;
|
|
54
54
|
- 桌面端保持 DSH 原生布局,不受影响。
|
package/client/client.js
CHANGED
|
@@ -806,29 +806,33 @@ function setupMobileDrawer() {
|
|
|
806
806
|
const input = portal.querySelector('input[placeholder*="\u641C\u7D22\u6A21\u578B"], input[placeholder*="Search model"], input[type="search"], input');
|
|
807
807
|
if (input) {
|
|
808
808
|
let userIntent = false;
|
|
809
|
-
const
|
|
809
|
+
const originalReadOnly = input.readOnly;
|
|
810
|
+
const originalInputMode = input.getAttribute("inputmode");
|
|
811
|
+
const enableSearch = () => {
|
|
812
|
+
if (userIntent) return;
|
|
810
813
|
userIntent = true;
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
try {
|
|
818
|
-
input.blur();
|
|
819
|
-
} catch {
|
|
820
|
-
}
|
|
814
|
+
input.readOnly = originalReadOnly;
|
|
815
|
+
if (originalInputMode === null) input.removeAttribute("inputmode");
|
|
816
|
+
else input.setAttribute("inputmode", originalInputMode);
|
|
817
|
+
try {
|
|
818
|
+
input.focus({ preventScroll: true });
|
|
819
|
+
} catch {
|
|
821
820
|
}
|
|
822
821
|
};
|
|
823
|
-
|
|
824
|
-
|
|
822
|
+
input.addEventListener("pointerdown", enableSearch);
|
|
823
|
+
input.addEventListener("touchstart", enableSearch, { passive: true });
|
|
824
|
+
const enforceNoKeyboard = () => {
|
|
825
|
+
if (!input.isConnected || userIntent) return;
|
|
826
|
+
if (!input.readOnly) input.readOnly = true;
|
|
827
|
+
if (!input.hasAttribute("readonly")) input.setAttribute("readonly", "");
|
|
828
|
+
if (input.getAttribute("inputmode") !== "none") input.setAttribute("inputmode", "none");
|
|
825
829
|
};
|
|
826
|
-
input.addEventListener("focus",
|
|
827
|
-
|
|
828
|
-
window.
|
|
829
|
-
window.setTimeout(
|
|
830
|
-
window.setTimeout(
|
|
831
|
-
window.setTimeout(() => input.removeEventListener("focus",
|
|
830
|
+
input.addEventListener("focus", enforceNoKeyboard);
|
|
831
|
+
enforceNoKeyboard();
|
|
832
|
+
window.setTimeout(enforceNoKeyboard, 0);
|
|
833
|
+
window.setTimeout(enforceNoKeyboard, 80);
|
|
834
|
+
window.setTimeout(enforceNoKeyboard, 260);
|
|
835
|
+
window.setTimeout(() => input.removeEventListener("focus", enforceNoKeyboard), 1e3);
|
|
832
836
|
}
|
|
833
837
|
window.requestAnimationFrame(() => {
|
|
834
838
|
if (!disposed && modelPortal === portal) document.body.classList.add("qzsy-model-sheet-open");
|
package/client/mobile.js
CHANGED
|
@@ -628,26 +628,35 @@ export function setupMobileDrawer() {
|
|
|
628
628
|
ensureModelBackdrop();
|
|
629
629
|
|
|
630
630
|
// 宿主菜单默认会聚焦「搜索模型」,手机上会直接弹起键盘把 sheet 顶掉一半。
|
|
631
|
-
//
|
|
631
|
+
// 移动端模型数量通常很少:先把搜索框设为 readonly + inputmode=none,阻止键盘;
|
|
632
|
+
// 保留焦点,避免宿主因 focusout 关闭菜单。用户主动点搜索框时再恢复可输入。
|
|
632
633
|
const input = portal.querySelector('input[placeholder*="搜索模型"], input[placeholder*="Search model"], input[type="search"], input');
|
|
633
634
|
if (input) {
|
|
634
635
|
let userIntent = false;
|
|
635
|
-
const
|
|
636
|
-
input.
|
|
637
|
-
|
|
638
|
-
|
|
636
|
+
const originalReadOnly = input.readOnly;
|
|
637
|
+
const originalInputMode = input.getAttribute('inputmode');
|
|
638
|
+
const enableSearch = () => {
|
|
639
|
+
if (userIntent) return;
|
|
640
|
+
userIntent = true;
|
|
641
|
+
input.readOnly = originalReadOnly;
|
|
642
|
+
if (originalInputMode === null) input.removeAttribute('inputmode');
|
|
643
|
+
else input.setAttribute('inputmode', originalInputMode);
|
|
644
|
+
try { input.focus({ preventScroll: true }); } catch { /* 忽略 */ }
|
|
645
|
+
};
|
|
646
|
+
input.addEventListener('pointerdown', enableSearch);
|
|
647
|
+
input.addEventListener('touchstart', enableSearch, { passive: true });
|
|
648
|
+
const enforceNoKeyboard = () => {
|
|
639
649
|
if (!input.isConnected || userIntent) return;
|
|
640
|
-
if (
|
|
641
|
-
|
|
642
|
-
|
|
650
|
+
if (!input.readOnly) input.readOnly = true;
|
|
651
|
+
if (!input.hasAttribute('readonly')) input.setAttribute('readonly', '');
|
|
652
|
+
if (input.getAttribute('inputmode') !== 'none') input.setAttribute('inputmode', 'none');
|
|
643
653
|
};
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
window.
|
|
648
|
-
window.setTimeout(
|
|
649
|
-
window.setTimeout(
|
|
650
|
-
window.setTimeout(() => input.removeEventListener('focus', onFocus), 900);
|
|
654
|
+
input.addEventListener('focus', enforceNoKeyboard);
|
|
655
|
+
enforceNoKeyboard();
|
|
656
|
+
window.setTimeout(enforceNoKeyboard, 0);
|
|
657
|
+
window.setTimeout(enforceNoKeyboard, 80);
|
|
658
|
+
window.setTimeout(enforceNoKeyboard, 260);
|
|
659
|
+
window.setTimeout(() => input.removeEventListener('focus', enforceNoKeyboard), 1000);
|
|
651
660
|
}
|
|
652
661
|
|
|
653
662
|
window.requestAnimationFrame(() => {
|
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@qzsy/dsh-bridge",
|
|
3
|
-
"version": "3.4.
|
|
3
|
+
"version": "3.4.4",
|
|
4
4
|
"description": "DSH 远程隧道云官方客户端插件:一条命令把本机 DeepSeek Harness 接入云端隧道(设备码绑定、短期令牌、本地门禁代理、HTTP/SSE/WebSocket 反向隧道)。",
|
|
5
|
-
"releaseNotes": "【v3.4.
|
|
5
|
+
"releaseNotes": "【v3.4.4】模型 sheet 默认不弹键盘\\n• 用 readonly + inputmode=none 替代 blur:保留焦点、不弹 iOS 键盘,宿主菜单不会因 focusout 关闭\\n• 用户主动点搜索框时恢复输入并聚焦;模型列表默认完整显示\\n• 修复 3.4.3 点「模型」后菜单直接消失的问题",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"main": "lib/index.js",
|
|
8
8
|
"exports": {
|