dsh-zen-remote 1.1.0 → 1.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +12 -2
- package/docs/interface.md +1 -1
- package/docs/research-ime-keyboard-occlusion.md +321 -0
- package/lib/client.js +238 -26
- package/lib/index.js +20 -0
- package/lib/index.js.map +1 -1
- package/lib/types/client/effects/keyboard-avoid.d.ts +48 -0
- package/lib/types/client/effects/keyboard-avoid.d.ts.map +1 -0
- package/lib/types/client/effects/turn-fold.d.ts +3 -1
- package/lib/types/client/effects/turn-fold.d.ts.map +1 -1
- package/lib/types/client/index.d.ts.map +1 -1
- package/lib/types/client/styles/composer.css.d.ts +1 -1
- package/lib/types/client/styles/composer.css.d.ts.map +1 -1
- package/lib/types/client/styles/turn-fold.css.d.ts +1 -1
- package/lib/types/client/styles/turn-fold.css.d.ts.map +1 -1
- package/lib/types/index.d.ts +9 -1
- package/lib/types/index.d.ts.map +1 -1
- package/package.json +2 -2
- package/scripts/check-keyboard-avoid.mjs +38 -0
- package/src/client/effects/keyboard-avoid.ts +134 -0
- package/src/client/effects/turn-fold.ts +59 -2
- package/src/client/index.tsx +6 -0
- package/src/client/styles/composer.css.ts +11 -0
- package/src/client/styles/turn-fold.css.ts +35 -24
- package/src/index.ts +26 -1
package/README.md
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
|
|
4
4
|
<p align="center">
|
|
5
5
|
<a href="LICENSE"><img src="https://img.shields.io/badge/license-MIT-0B7285?style=flat-square" alt="MIT"></a>
|
|
6
|
-
<img src="https://img.shields.io/badge/release-v1.1.
|
|
6
|
+
<img src="https://img.shields.io/badge/release-v1.1.1-5B4CF0?style=flat-square" alt="v1.1.1">
|
|
7
7
|
<img src="https://img.shields.io/badge/DSH-Web%20Profile-5B4CF0?style=flat-square" alt="DSH Web Profile">
|
|
8
8
|
</p>
|
|
9
9
|
|
|
@@ -39,7 +39,7 @@ dsh plugin add dsh-zen-remote
|
|
|
39
39
|
```jsonc
|
|
40
40
|
{
|
|
41
41
|
"dependencies": {
|
|
42
|
-
"dsh-zen-remote": "^1.1.
|
|
42
|
+
"dsh-zen-remote": "^1.1.1" // 本地开发换成 "link:/path/to/dsh-zen-remote"
|
|
43
43
|
},
|
|
44
44
|
"dsh": { "profile": { "bundles": [
|
|
45
45
|
"@deepseek-ai/dsh-base",
|
|
@@ -191,6 +191,16 @@ open http://127.0.0.1:3088/lan-gate/admin
|
|
|
191
191
|
|
|
192
192
|
上传大小上限(默认 20MB)在插件行的 `config.maxUploadBytes` 里改。
|
|
193
193
|
|
|
194
|
+
想在电脑端也启用回合过程折叠(默认只在手机宽度生效),在插件行的 `config.turnFoldDesktop` 里设 `true`——即在 profile 的 `cordis.patch.yml` 加一条:
|
|
195
|
+
|
|
196
|
+
```yaml
|
|
197
|
+
- id: dsh-zen-remote
|
|
198
|
+
config:
|
|
199
|
+
turnFoldDesktop: true
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
改完重启 `dsh web`。不改服务端配置的话,单个浏览器也可以访问一次 `?mobile-nav-turn-fold=1` 自己开启(`=0` 关闭,按浏览器记忆)。
|
|
203
|
+
|
|
194
204
|
---
|
|
195
205
|
|
|
196
206
|
## 通知什么时候会响
|
package/docs/interface.md
CHANGED
|
@@ -52,7 +52,7 @@ v1.0.0(fork 自 [mexiaosqwq/dsh-web-mobile](https://github.com/mexiaosqwq/dsh-
|
|
|
52
52
|
|
|
53
53
|
### 回合过程折叠
|
|
54
54
|
|
|
55
|
-
Chat 视图里,同一回合内的推理块、工具调用块默认折叠成一条「过程 · N
|
|
55
|
+
Chat 视图里,同一回合内的推理块、工具调用块默认折叠成一条「过程 · N 步」摘要行,点开才展开;最终回复文本永远直接可见。运行中的回合摘要行会跟着步数实时更新。默认仅手机断点生效;插件行配置 `config.turnFoldDesktop: true` 可让所有客户端在任意宽度下启用折叠(见 README 配置一节),单个浏览器也可以访问一次 `?mobile-nav-turn-fold=1` 自行开启(按浏览器记忆,`=0` 关闭)。
|
|
56
56
|
|
|
57
57
|
### 手势
|
|
58
58
|
|
|
@@ -0,0 +1,321 @@
|
|
|
1
|
+
# 调研:Android 软键盘弹出时输入框被遮挡(小米 + 微信输入法必现)
|
|
2
|
+
|
|
3
|
+
2026-08-21 调研。对应现象:手机 Chrome / 系统 WebView 访问本 PWA,点击底部
|
|
4
|
+
composer textarea,微信输入法(WeType)弹出后页面不上移,输入内容被键盘挡住;
|
|
5
|
+
其他环境(如 Gboard、iOS)表现正常。
|
|
6
|
+
|
|
7
|
+
置信度标注约定:
|
|
8
|
+
|
|
9
|
+
- **[规范/官方]** —— 规范原文、官方文档、官方博客、官方 bug tracker 结论
|
|
10
|
+
- **[源码]** —— 浏览器 / 项目源码直接读到
|
|
11
|
+
- **[社区]** —— 社区帖子 / 第三方 issue,属案例线索,未经一手证实
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## 一、问题概述
|
|
16
|
+
|
|
17
|
+
页面底部有一个 textarea(composer,`position: sticky; bottom: 0`,位于内部滚动
|
|
18
|
+
容器中;`html/body` 是 `overflow: hidden`,本插件刻意不做 visualViewport JS,
|
|
19
|
+
依赖浏览器自己把聚焦元素挪进可视区 —— 见 `src/client/styles/home.css.ts` 注释
|
|
20
|
+
**[源码]**)。在「小米手机 + 微信输入法」组合下,键盘弹出后视口没有任何变化,
|
|
21
|
+
浏览器也没有把光标滚进可视区,文字被键盘盖住。
|
|
22
|
+
|
|
23
|
+
要理解根因,关键是弄清一条完整的信息链:
|
|
24
|
+
|
|
25
|
+
> Android IME 弹出 → 系统把键盘占用的高度以 window insets 形式发给应用
|
|
26
|
+
> → Chrome 读取 insets 算出键盘高度 → 缩小 visual viewport(视觉视口)
|
|
27
|
+
> → 触发 `visualViewport` resize 事件 + 自动把聚焦的输入框滚进可视区。
|
|
28
|
+
|
|
29
|
+
这条链上**任何一环断掉**,页面都不会上移。下面逐环给出平台事实。
|
|
30
|
+
|
|
31
|
+
---
|
|
32
|
+
|
|
33
|
+
## 二、平台机制事实(带来源)
|
|
34
|
+
|
|
35
|
+
### 2.1 Chrome 108 起的键盘-视口行为
|
|
36
|
+
|
|
37
|
+
- **[规范/官方]** Chrome 108(2022-11)起,Android Chrome 键盘弹出时**不再缩小
|
|
38
|
+
layout viewport(布局视口)**,只缩小 visual viewport。`window.innerHeight`、
|
|
39
|
+
`100vh/100dvh`、`position: fixed` 元素的位置都不再随键盘变化。此行为与
|
|
40
|
+
iOS Safari 对齐。
|
|
41
|
+
来源:[Chrome 官方博客 viewport-resize-behavior](https://developer.chrome.com/blog/viewport-resize-behavior)、
|
|
42
|
+
[blink-dev Intent to Ship](https://groups.google.com/a/chromium.org/g/blink-dev/c/ge7xTu-VhJ0)
|
|
43
|
+
- **[规范/官方]** 同版本引入 viewport meta 的 `interactive-widget` 键,三个值:
|
|
44
|
+
- `resizes-visual`(**默认**):只缩 visual viewport;
|
|
45
|
+
- `resizes-content`:布局视口一起缩(等于 108 之前的老行为);
|
|
46
|
+
- `overlays-content`:什么都不缩,键盘纯覆盖。
|
|
47
|
+
规范条文见 [CSS Viewport Module Level 1](https://drafts.csswg.org/css-viewport/)
|
|
48
|
+
(`interactive-widget` 属性;无值或非法值按 `resizes-visual` 处理),值语义另见
|
|
49
|
+
[MDN viewport meta](https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/meta/name/viewport)。
|
|
50
|
+
- **[规范/官方]** 支持版本(MDN BCD 数据,`html/elements/meta/name/viewport/interactive-widget.json`):
|
|
51
|
+
Chrome Android **108+**,Firefox Android **133+**(Firefox Android 132 先把默认行为
|
|
52
|
+
改成 resizes-visual,见 [Firefox 132 for Android release notes](https://www.mozilla.org/en-US/firefox/android/132.0/releasenotes/)),
|
|
53
|
+
桌面各浏览器与 Safari 均不支持(桌面无 OSK 概念,Safari iOS 未实现)。
|
|
54
|
+
来源:[mdn/browser-compat-data](https://github.com/mdn/browser-compat-data/blob/main/html/elements/meta/name/viewport/interactive-widget.json)。
|
|
55
|
+
- **[源码]** Chrome Android 端的键盘高度是这样算出来的:
|
|
56
|
+
`KeyboardUtils.calculateKeyboardHeightFromWindowInsets()` 读
|
|
57
|
+
`getRootWindowInsets()` → `WindowInsetsCompat.Type.ime().bottom` 再减去
|
|
58
|
+
`systemBars().bottom`;`isAndroidSoftKeyboardShowing()` 就是「算出的高度 > 0」。
|
|
59
|
+
源码注释原话:*"This is a best guess based on the height of the keyboard as
|
|
60
|
+
there is no standardized/foolproof way to do this."*(“这是基于键盘高度的
|
|
61
|
+
最佳猜测,没有标准化的万无一失的办法”)。
|
|
62
|
+
来源:[base/android/.../KeyboardUtils.java](https://chromium.googlesource.com/chromium/src/+/refs/heads/main/base/android/java/src/org/chromium/base/ui/KeyboardUtils.java)、
|
|
63
|
+
[ui/android/.../KeyboardVisibilityDelegate.java](https://chromium.googlesource.com/chromium/src/+/refs/heads/main/ui/android/java/src/org/chromium/ui/KeyboardVisibilityDelegate.java)。
|
|
64
|
+
**推论:键盘高度完全取决于 IME 通过系统 window insets 上报的数值。IME(或被
|
|
65
|
+
OEM 定制过的系统)报 0,Chrome 就认为没有键盘。**
|
|
66
|
+
- **[规范/官方]** 键盘弹出时把聚焦输入框挪进可视区,是浏览器侧
|
|
67
|
+
`ScrollFocusedEditableNodeIntoRect` 这条 IME 专用通道做的("used by IMEs
|
|
68
|
+
(on-screen keyboards) to bring an element into view"),同样由键盘几何信息驱动。
|
|
69
|
+
来源:[crbug 40774196(EditContext scroll into view)](https://issues.chromium.org/issues/40774196)。
|
|
70
|
+
|
|
71
|
+
### 2.2 visualViewport API 的事件语义
|
|
72
|
+
|
|
73
|
+
- **[规范/官方]** CSSOM View §13.1 "Resizing viewports" 原文:只有当
|
|
74
|
+
VisualViewport 的 *scale / width / height 相比上次 run the resize steps 时
|
|
75
|
+
发生了变化*,才在 VisualViewport 上 fire `resize`。
|
|
76
|
+
来源:[drafts.csswg.org/cssom-view §13.1](https://drafts.csswg.org/cssom-view/#resizing-viewports)。
|
|
77
|
+
**推论:如果键盘弹出但视口尺寸根本没被改(上一节的 insets 链断了),不触发
|
|
78
|
+
resize 是"符合规范"的 —— 事件不来不是 bug,而是视口真的没变。任何"只监听
|
|
79
|
+
事件"的方案在这种设备上天然失效。**
|
|
80
|
+
- **[规范/官方]** 已知相关事件 bug(都不是"键盘弹出完全无事件",而是时序/数值噪声):
|
|
81
|
+
- [crbug 40924170](https://issues.chromium.org/issues/40924170):使用
|
|
82
|
+
`interactive-widget=overlays-content`(VirtualKeyboard API 通道)时,键盘
|
|
83
|
+
动画期间 `window.innerHeight` 短暂变成无意义的大/小值。2024-04 修复
|
|
84
|
+
(CL [5431673](https://chromium-review.googlesource.com/c/chromium/src/+/5431673)),
|
|
85
|
+
2025-10 又有人在 Chrome 141 复现,追踪新 bug 450752874。
|
|
86
|
+
- [crbug 41343106](https://issues.chromium.org/issues/41343106):URL 栏动画期间
|
|
87
|
+
visualViewport resize 不触发(旧案)。
|
|
88
|
+
- [crbug 40768751](https://issues.chromium.org/issues/40768751):iframe 里
|
|
89
|
+
visualViewport 不发 resize。
|
|
90
|
+
- 第三方 IME 是否影响事件触发:**没有找到 Chromium 官方就"某第三方 IME 导致
|
|
91
|
+
visualViewport 事件不触发"立案的一手记录**。但按 2.1 的源码链,IME insets
|
|
92
|
+
上报异常 ⇒ 视口不缩 ⇒ 无事件,逻辑上成立且与本 bug 症状吻合(**[源码]推论**,
|
|
93
|
+
非官方结论)。
|
|
94
|
+
|
|
95
|
+
### 2.3 第三方 IME / OEM 定制的特殊性
|
|
96
|
+
|
|
97
|
+
- **[规范/官方]** 原生层的两种老模式:`android:windowSoftInputMode` 的
|
|
98
|
+
`adjustResize`(窗口整体缩小)与 `adjustPan`(窗口整体上平移、不缩小、
|
|
99
|
+
**不产生任何页面内 resize**)。
|
|
100
|
+
来源:[Android activity-element 文档](https://developer.android.com/guide/topics/manifest/activity-element#wsoft)。
|
|
101
|
+
Chrome 浏览器本体不走这套(自己读 insets),但 **WebView 完全由宿主 App 的
|
|
102
|
+
这个设置决定**(见 2.4)。
|
|
103
|
+
- **[社区]** 第三方 IME 键盘高度与系统上报不一致的公开案例:搜狗输入法键盘比默认
|
|
104
|
+
输入法高约 30px,导致输入框被压住一截
|
|
105
|
+
([CSDN:固定在 H5 底部的输入框的兼容性问题](https://blog.csdn.net/kill370354/article/details/128390440))。
|
|
106
|
+
- **[社区]** 小米设备网页端键盘遮挡的公开案例:
|
|
107
|
+
- [CSDN:小米手机浏览器的 input/textarea 底部被遮挡](https://blog.csdn.net/wngzhem/article/details/102524828)
|
|
108
|
+
(小米自带浏览器,聚焦后键盘盖住吸底输入框);
|
|
109
|
+
- [微信开放社区:小程序 webview 中 fixed 定位 input,小米 6 软键盘遮挡必现](https://developers.weixin.qq.com/community/develop/doc/0002ee32d84c1020523aaeab75b000);
|
|
110
|
+
- [微信开放社区:web-view 在 Android 检测不到键盘弹出,造成遮挡](https://developers.weixin.qq.com/community/develop/doc/167b6d37a9efaffb0722c7950ede5adc);
|
|
111
|
+
- [微信开放社区:软键盘弹出状态影响页面显示(安卓兼容)](https://developers.weixin.qq.com/community/develop/doc/000042e586c698167262e4b1961400)。
|
|
112
|
+
- **微信输入法(WeType)+ 小米的组合,没有检索到公开的一手 bug 记录**(Chromium
|
|
113
|
+
tracker、微信开放社区、GitHub 均未见立案)。“WeType 在 MIUI/HyperOS 上 insets
|
|
114
|
+
上报异常”目前只能算**与源码机制吻合的假设**,需要在设备上实测证实(见第四节
|
|
115
|
+
的判别方法)。此点如实标注:**传闻/未证实**。
|
|
116
|
+
- **[社区]** WeType 与微信键盘生态的杂项 bug 汇总(非本问题直接证据):
|
|
117
|
+
[知乎:微信输入法发布 1 月了,你发现了哪些 bug](https://zhuanlan.zhihu.com/p/599576914)。
|
|
118
|
+
|
|
119
|
+
### 2.4 系统 WebView 的差异(重要)
|
|
120
|
+
|
|
121
|
+
- **[规范/官方]** Chrome 108 的行为变化**明确不适用于 WebView**。blink-dev 原话:
|
|
122
|
+
*"There is no intended behavior change for Android WebView. The Android app is
|
|
123
|
+
responsible for sizing the WebView and can implement either mode via
|
|
124
|
+
windowSoftInputMode."*
|
|
125
|
+
来源:[blink-dev](https://groups.google.com/a/chromium.org/g/blink-dev/c/ge7xTu-VhJ0/m/hq_kcusHAQAJ),
|
|
126
|
+
转引自 [crbug 40287394](https://issues.chromium.org/issues/40287394)。
|
|
127
|
+
- **[规范/官方]** crbug 40287394(Adobe 报告,Feature Request)实测映射关系:
|
|
128
|
+
- 宿主 App `adjustResize` ⇒ 等价 `resizes-content`(布局+视觉一起缩);
|
|
129
|
+
- 宿主 App `adjustPan` / `adjustUnspecified` ⇒ 等价 `overlays-content`
|
|
130
|
+
(**什么都不缩、页面完全不知道键盘存在**);
|
|
131
|
+
- Chrome 默认的 `resizes-visual` 在 WebView 里**无法实现**;
|
|
132
|
+
- **VirtualKeyboard API 在 WebView 里不可用**:boundingRect 全零、
|
|
133
|
+
`geometrychange` 永不触发(issue 原文)。
|
|
134
|
+
该 issue 2025 年标记 Fixed(CL [6616171](https://chromium-review.googlesource.com/6616171)),
|
|
135
|
+
但报告者在 WebView Canary 139 实测仍未见效(issue #21 楼),落地状态存疑。
|
|
136
|
+
- **推论:如果"系统 WebView 访问"指从某个 App(如微信、小米自带应用)内打开,
|
|
137
|
+
且宿主是 adjustPan/unspecified,则遮挡是设计使然,与 IME 无关。** 判别方法见
|
|
138
|
+
第四节。
|
|
139
|
+
|
|
140
|
+
### 2.5 PWA standalone 模式的差异
|
|
141
|
+
|
|
142
|
+
- **[社区]** 有零散反馈称同一站点"浏览器 tab 正常、装成 PWA 后键盘行为异常":
|
|
143
|
+
- [code-server #7149](https://github.com/coder/code-server/issues/7149)
|
|
144
|
+
(Android 15 / Chrome 131,PWA 内键盘输入异常,"the regular chrome website
|
|
145
|
+
doesn't have these issues";已关闭,归为上游问题);
|
|
146
|
+
- [PWABuilder #2572](https://github.com/pwa-builder/PWABuilder/issues/2572)
|
|
147
|
+
(TWA 中键盘收起后视口卡在缩小状态)。
|
|
148
|
+
- **没有找到"standalone 下键盘视口行为与 tab 系统性不同"的 Chromium 官方一手
|
|
149
|
+
记录**。WebAPK 安装的 PWA 仍由 Chrome 渲染,理论上走 Chrome 的 insets 链而非
|
|
150
|
+
WebView 的 windowSoftInputMode 链。此点标注:**社区案例,未证实**。
|
|
151
|
+
|
|
152
|
+
### 2.6 VirtualKeyboard API
|
|
153
|
+
|
|
154
|
+
- **[规范/官方]** `navigator.virtualKeyboard`:设 `overlaysContent = true` 后浏览器
|
|
155
|
+
完全不再为键盘调整视口,改由页面用 `geometrychange` 事件 + `boundingRect` +
|
|
156
|
+
CSS `env(keyboard-inset-*)` 自己布局。**只有 opt-in 之后这些能力才生效**。
|
|
157
|
+
来源:[MDN VirtualKeyboard API](https://developer.mozilla.org/en-US/docs/Web/API/VirtualKeyboard_API)、
|
|
158
|
+
[Chrome 官方文档](https://developer.chrome.com/docs/web-platform/virtual-keyboard)、
|
|
159
|
+
[W3C 草案](https://w3c.github.io/editing/docs/virtualkeyboard/)。
|
|
160
|
+
- **[规范/官方]** 支持范围(MDN BCD `api/VirtualKeyboard.json`):Chromium 系
|
|
161
|
+
**94+**(含 Android Chrome);Firefox、Safari 均未实现(分别见
|
|
162
|
+
[bugzil.la/1730568](https://bugzilla.mozilla.org/show_bug.cgi?id=1730568)、
|
|
163
|
+
[webkit.org/b/230225](https://bugs.webkit.org/show_bug.cgi?id=230225))。
|
|
164
|
+
非 Baseline、标注实验性。
|
|
165
|
+
- **[规范/官方]** WebView 中名义上存在但实际不可用(boundingRect 全零,见 2.4)。
|
|
166
|
+
- **适用性结论:它的键盘几何数据和 visual viewport 用的是同一条 insets 链
|
|
167
|
+
([源码]推论),所以对"IME 不上报高度"这类根因**同样无能为力**,还把 Firefox/
|
|
168
|
+
Safari 排除在外。本场景不推荐作为主方案。**
|
|
169
|
+
|
|
170
|
+
### 2.7 业界聊天 UI 的实际做法(源码)
|
|
171
|
+
|
|
172
|
+
- **[源码]** Telegram Web A([Ajaxy/telegram-tt](https://github.com/Ajaxy/telegram-tt)):
|
|
173
|
+
- viewport meta **没有** `interactive-widget`(`index.html`);
|
|
174
|
+
- [`src/util/windowSize.ts`](https://github.com/Ajaxy/telegram-tt/blob/master/src/util/windowSize.ts):
|
|
175
|
+
iOS 用 `visualViewport.height + visualViewport.pageTop` 维护 `--vh` CSS 变量并监听
|
|
176
|
+
`visualViewport resize`;**Android 只听 `window.resize`**,即在 Android 上
|
|
177
|
+
基本信任浏览器默认的 resizes-visual 自动行为(跟本插件目前思路一致);
|
|
178
|
+
- 键盘可见性判断就是「innerHeight 比初值小」的启发式。
|
|
179
|
+
- **[社区]** 通用做法参考:用 visualViewport 把底栏 `translateY` 到
|
|
180
|
+
`innerHeight - vv.height - vv.offsetTop` 处
|
|
181
|
+
([dev.to: Fix mobile keyboard overlap with visualViewport](https://dev.to/franciscomoretti/fix-mobile-keyboard-overlap-with-visualviewport-3a4a))。
|
|
182
|
+
|
|
183
|
+
---
|
|
184
|
+
|
|
185
|
+
## 三、已知案例 / 相关 bug 清单
|
|
186
|
+
|
|
187
|
+
| 编号/链接 | 内容 | 状态 | 置信度 |
|
|
188
|
+
| --- | --- | --- | --- |
|
|
189
|
+
| [crbug 40287394](https://issues.chromium.org/issues/40287394) | WebView 无法只缩 visual viewport;adjustPan≈overlays-content;VirtualKeyboard API 在 WebView 全零 | Fixed(2025,落地存疑) | 官方 |
|
|
190
|
+
| [crbug 40924170](https://issues.chromium.org/issues/40924170) | overlays-content 下键盘动画期间 innerHeight 出现瞬时错误值 | Fixed,2025-10 复发报告 → bug 450752874 | 官方 |
|
|
191
|
+
| [crbug 41176235](https://issues.chromium.org/issues/41176235) | 108 之前"键盘缩窗口打乱 SPA 布局"的历史诉求 | 历史参考 | 官方 |
|
|
192
|
+
| [crbug 41343106](https://issues.chromium.org/issues/41343106) / [40768751](https://issues.chromium.org/issues/40768751) | visualViewport 事件在 URL 栏动画 / iframe 场景不触发 | — | 官方 |
|
|
193
|
+
| [微信开放社区(小米 6 webview fixed input 必现遮挡)](https://developers.weixin.qq.com/community/develop/doc/0002ee32d84c1020523aaeab75b000) 等 3 帖 | 小米/华为设备上 webview 检测不到键盘、fixed 输入框被盖 | 无官方结论 | 社区 |
|
|
194
|
+
| [CSDN 小米浏览器输入框被盖](https://blog.csdn.net/wngzhem/article/details/102524828)、[搜狗键盘高 30px](https://blog.csdn.net/kill370354/article/details/128390440) | OEM 浏览器 / 第三方 IME 高度不一致案例 | — | 社区 |
|
|
195
|
+
| [code-server #7149](https://github.com/coder/code-server/issues/7149)、[PWABuilder #2572](https://github.com/pwa-builder/PWABuilder/issues/2572) | PWA/TWA 形态下键盘视口异常 | 关闭/未决 | 社区 |
|
|
196
|
+
| WeType + 小米组合 | **未检索到公开一手记录** | — | 传闻/未证实 |
|
|
197
|
+
|
|
198
|
+
---
|
|
199
|
+
|
|
200
|
+
## 四、根因候选排序(附判别性预期)
|
|
201
|
+
|
|
202
|
+
按可能性从高到低。每条给出「如果是它,会观察到什么」,用项目自带的
|
|
203
|
+
`?debug` 面板(`src/client/debug.ts` 已经显示 visualViewport 数据)即可判别。
|
|
204
|
+
|
|
205
|
+
1. **WeType(或 MIUI/HyperOS 对其的 insets 处理)没有把键盘高度报进
|
|
206
|
+
`WindowInsets.ime()`,Chrome 端算得键盘高度为 0。**([源码]链推论;
|
|
207
|
+
WeType 环节本身未证实)
|
|
208
|
+
预期观察:键盘弹出前后 `visualViewport.height` **纹丝不动**、无 resize 事件、
|
|
209
|
+
`innerHeight` 不变、浏览器也不自动滚动光标。切回 Gboard 立即正常。
|
|
210
|
+
若再验证:同一设备上 Chrome 换成 Firefox Android(走自己的 insets 消费逻辑)
|
|
211
|
+
看是否同样失效,可区分"IME 没报"还是"Chrome 没读到"。
|
|
212
|
+
2. **WeType 处于悬浮/迷你键盘等特殊窗口形态**(悬浮键盘本来就不占 insets,
|
|
213
|
+
overlay 是预期行为)。
|
|
214
|
+
预期观察:键盘不是全宽贴底的常规形态;改回标准全键盘模式立刻正常。
|
|
215
|
+
3. **访问入口实为某 App 内嵌 WebView,宿主 windowSoftInputMode 是
|
|
216
|
+
adjustPan/unspecified** ⇒ 等价 overlays-content,设计如此([官方] crbug 40287394)。
|
|
217
|
+
预期观察:同一页面在独立 Chrome 里正常,仅从该 App 打开时遮挡;且此时换
|
|
218
|
+
Gboard 也一样遮挡(与 IME 无关)。
|
|
219
|
+
4. **visualViewport 缩了、事件也来了,但页面结构令浏览器自动滚动失效**
|
|
220
|
+
(sticky 底栏 + `html/body overflow:hidden`,浏览器把光标滚进可视区时
|
|
221
|
+
没有可滚的祖先)。
|
|
222
|
+
预期观察:debug 面板里 `vv.height` 明显变小、resize 有触发,但 composer
|
|
223
|
+
仍在键盘下面。此时问题在我们页面侧,走第五节方案 2 必能修。
|
|
224
|
+
5. **PWA standalone 形态特有 bug**([社区],未证实)。
|
|
225
|
+
预期观察:同一 Chrome、同一输入法,浏览器 tab 里正常、仅"添加到主屏幕"的
|
|
226
|
+
窗口里遮挡。
|
|
227
|
+
6. **Chrome 版本撞上瞬时高度 bug 族**(crbug 40924170 / 450752874,
|
|
228
|
+
仅在用了 overlays-content / VirtualKeyboard API 时相关)。本项目没用这些
|
|
229
|
+
模式,基本可排除;若未来启用需注意。
|
|
230
|
+
|
|
231
|
+
> 注:候选 1/2 里"页面完全不知道键盘存在"时,**不触发事件是符合 CSSOM View
|
|
232
|
+
> 规范的**(§13.1 只有尺寸真变了才 fire),所以"补监听"类方案救不了它们。
|
|
233
|
+
|
|
234
|
+
---
|
|
235
|
+
|
|
236
|
+
## 五、解决路径清单(按性价比排序)
|
|
237
|
+
|
|
238
|
+
1. **先做 10 分钟判别实验,再选方案**(零代码)。
|
|
239
|
+
在故障机上开 `?debug` 面板:点 textarea,看 `visualViewport.height` 变不变。
|
|
240
|
+
变 ⇒ 根因 4,走下面第 2 条,必修得好;不变 ⇒ 根因 1/2/3,第 2 条的事件监听
|
|
241
|
+
部分对它无效,需要第 3/4 条兜底。同时记录:换 Gboard 是否正常、WeType 是否
|
|
242
|
+
悬浮模式、入口是 Chrome 还是 App 内。
|
|
243
|
+
依据:CSSOM View §13.1(事件只在尺寸变化时触发)+ KeyboardUtils 源码链。
|
|
244
|
+
2. **visualViewport `resize` + `scroll` 双监听,把 composer 平移到可视区底边**
|
|
245
|
+
(适用:根因 4,以及所有"视口确实缩了"的环境;iOS 也受益)。
|
|
246
|
+
公式:`offset = innerHeight - vv.height - vv.offsetTop`,对 composer 施加
|
|
247
|
+
`translateY(-offset)` 或把它的容器高度设为 `vv.height`。
|
|
248
|
+
注意:要同时听 `scroll`(visual viewport 平移时 offsetTop 变化不发 resize,
|
|
249
|
+
规范 §13.2);用 rAF 合并;键盘收起时归零。
|
|
250
|
+
来源:[MDN VisualViewport](https://developer.mozilla.org/en-US/docs/Web/API/VisualViewport)、
|
|
251
|
+
[dev.to 实现示例](https://dev.to/franciscomoretti/fix-mobile-keyboard-overlap-with-visualviewport-3a4a)、
|
|
252
|
+
telegram-tt iOS 分支同思路([windowSize.ts](https://github.com/Ajaxy/telegram-tt/blob/master/src/util/windowSize.ts))。
|
|
253
|
+
风险:低;纯增量,事件不来时等于没装。
|
|
254
|
+
3. **meta viewport 加 `interactive-widget=resizes-content`**
|
|
255
|
+
(适用:想回到"键盘顶起整个布局"的老行为,让 sticky/fixed 底栏天然可见;
|
|
256
|
+
Chrome Android 108+ / Firefox Android 133+,其他浏览器安全忽略)。
|
|
257
|
+
来源:[Chrome 博客](https://developer.chrome.com/blog/viewport-resize-behavior)、
|
|
258
|
+
[MDN](https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/meta/name/viewport)。
|
|
259
|
+
风险:a) 它依赖同一条 insets 链,**对根因 1/2 大概率同样无效**(键盘高度
|
|
260
|
+
为 0 时无从缩起)—— 但值得实测,因为 resizes-content 在 Chrome 内部走
|
|
261
|
+
`adjustResize` 型窗口缩放路径,与 visual-viewport 路径不完全相同;
|
|
262
|
+
b) 键盘弹出时 `100vh/dvh`、媒体查询、整页布局都会跳一次,本插件大量
|
|
263
|
+
"document 永不滚动"的假设要回归测试。工作量:一行 meta + 回归测试。
|
|
264
|
+
4. **focus 后轮询兜底(专治"事件不来"的 IME)**
|
|
265
|
+
(适用:根因 1/2 确诊,又不能要求用户换输入法时)。
|
|
266
|
+
focusin 到 composer 后,短周期(如每 100ms,持续 ~1.5s)比对
|
|
267
|
+
`vv.height`/`innerHeight`;若始终没变化,视为"哑键盘",给 composer 加一段
|
|
268
|
+
估计高度的底部让位(如 `min(40vh, 320px)`),blur 后撤掉。
|
|
269
|
+
这是社区通行的启发式([微信开放社区案例](https://developers.weixin.qq.com/community/develop/doc/167b6d37a9efaffb0722c7950ede5adc)
|
|
270
|
+
即"监听 focus 前后 window 高度变化"思路的引申,**[社区]**,无官方背书)。
|
|
271
|
+
风险:估高不准(键盘高度因输入法/表情面板而异);必现误判面(外接键盘用户
|
|
272
|
+
会被白白顶起 —— 可用 `navigator.virtualKeyboard`/触摸能力启发式减噪)。
|
|
273
|
+
建议只在「判别实验证实事件确实不来」后再上。
|
|
274
|
+
5. **focus 时 `scrollIntoView` 兜底**:对本项目**基本无效** —— composer 已经
|
|
275
|
+
sticky 在滚动容器底部、document 又 `overflow:hidden`,没有可滚的余地;它只
|
|
276
|
+
对"输入框在长文档中部"的常规页面有意义。列出仅为完整性(**[社区]** 通行做法)。
|
|
277
|
+
6. **VirtualKeyboard API(`overlaysContent` + `env(keyboard-inset-*)`)**:
|
|
278
|
+
本场景不推荐。仅 Chromium 94+、WebView 全零([crbug 40287394](https://issues.chromium.org/issues/40287394))、
|
|
279
|
+
与根因 1/2 同链失效,且曾有瞬时高度 bug 族([crbug 40924170](https://issues.chromium.org/issues/40924170))。
|
|
280
|
+
7. **运维/用户侧路径**(正规修复之外的现实选项):让该用户在 WeType 里关闭
|
|
281
|
+
悬浮键盘、或临时切 Gboard 验证;升级 Android System WebView / Chrome;
|
|
282
|
+
若确诊是 WeType insets 问题,向微信输入法反馈(其 Android 端无公开 tracker,
|
|
283
|
+
走 App 内反馈)。**[社区/操作建议]**
|
|
284
|
+
|
|
285
|
+
推荐组合:**路径 1(判别)→ 路径 2(无条件先装上,覆盖大多数环境并给 iOS
|
|
286
|
+
兜底)→ 视判别结果决定是否加 3 或 4**。
|
|
287
|
+
|
|
288
|
+
---
|
|
289
|
+
|
|
290
|
+
## 六、参考链接汇总
|
|
291
|
+
|
|
292
|
+
规范 / 官方文档:
|
|
293
|
+
|
|
294
|
+
- CSS Viewport Module Level 1(interactive-widget):<https://drafts.csswg.org/css-viewport/>
|
|
295
|
+
- CSSOM View §13 事件触发条件:<https://drafts.csswg.org/cssom-view/#resizing-viewports>
|
|
296
|
+
- Chrome 108 视口行为变更官方博客:<https://developer.chrome.com/blog/viewport-resize-behavior>
|
|
297
|
+
- blink-dev Intent(含 WebView 不适用声明):<https://groups.google.com/a/chromium.org/g/blink-dev/c/ge7xTu-VhJ0>
|
|
298
|
+
- MDN viewport meta / interactive-widget:<https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/meta/name/viewport>
|
|
299
|
+
- MDN VirtualKeyboard API:<https://developer.mozilla.org/en-US/docs/Web/API/VirtualKeyboard_API>
|
|
300
|
+
- Chrome VirtualKeyboard 文档:<https://developer.chrome.com/docs/web-platform/virtual-keyboard>
|
|
301
|
+
- W3C VirtualKeyboard 草案:<https://w3c.github.io/editing/docs/virtualkeyboard/>
|
|
302
|
+
- Android windowSoftInputMode:<https://developer.android.com/guide/topics/manifest/activity-element#wsoft>
|
|
303
|
+
- BCD 支持数据:<https://github.com/mdn/browser-compat-data>(interactive-widget、api/VirtualKeyboard)
|
|
304
|
+
|
|
305
|
+
源码:
|
|
306
|
+
|
|
307
|
+
- Chromium 键盘高度计算:<https://chromium.googlesource.com/chromium/src/+/refs/heads/main/base/android/java/src/org/chromium/base/ui/KeyboardUtils.java>
|
|
308
|
+
- Chromium KeyboardVisibilityDelegate:<https://chromium.googlesource.com/chromium/src/+/refs/heads/main/ui/android/java/src/org/chromium/ui/KeyboardVisibilityDelegate.java>
|
|
309
|
+
- telegram-tt 视口处理:<https://github.com/Ajaxy/telegram-tt/blob/master/src/util/windowSize.ts>
|
|
310
|
+
- viewport-resize-behavior explainer(bramus,Chrome DevRel):<https://github.com/bramus/viewport-resize-behavior/blob/main/explainer.md>
|
|
311
|
+
|
|
312
|
+
Bug tracker:
|
|
313
|
+
|
|
314
|
+
- crbug 40287394(WebView 视口/VK API):<https://issues.chromium.org/issues/40287394>
|
|
315
|
+
- crbug 40924170(overlays-content 瞬时高度):<https://issues.chromium.org/issues/40924170>
|
|
316
|
+
- crbug 41176235 / 41343106 / 40768751(历史与事件类):见第三节表格
|
|
317
|
+
|
|
318
|
+
社区案例(未证实):
|
|
319
|
+
|
|
320
|
+
- 微信开放社区三帖、CSDN 两文、知乎 WeType bug 汇总、code-server #7149、
|
|
321
|
+
PWABuilder #2572 —— 链接见第二、三节行内。
|