@co0ontty/wand 1.25.2 → 1.25.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.
@@ -1076,6 +1076,49 @@
1076
1076
  scheduleForegroundSync("android-resume", { immediate: true });
1077
1077
  ensureTerminalFitWithRetry("android-resume");
1078
1078
  });
1079
+
1080
+ // Bridge from Android IME animation. State values: "start" / "shown" / "hidden".
1081
+ // 原生层用 setPadding 在 WebView 父容器上 resize WebView, 视觉上键盘
1082
+ // 动画跟系统同步, 但带来一个副作用: window.innerHeight === visualViewport.height,
1083
+ // 导致 setupVisualViewportHandlers 里的 isKeyboardOpen 检测 (基于
1084
+ // offsetBottom) 永远是 false, 不会进 keyboard-open / keyboard-close 分支,
1085
+ // 终端 forceReplay 路径也就不跑了。
1086
+ //
1087
+ // 这里直接听原生层的"键盘动画收尾"事件, 触发 ensureTerminalFit
1088
+ // (forceReplay=true), 把 wterm 的网格按真实视口重排一遍。
1089
+ window.addEventListener("wand-ime-state", function(e) {
1090
+ var which = e && e.detail && e.detail.state;
1091
+ if (which === "shown" || which === "hidden") {
1092
+ try {
1093
+ ensureTerminalFit("native-ime-" + which, { forceReplay: true });
1094
+ maybeScrollTerminalToBottom("native-ime");
1095
+ } catch (_e) {}
1096
+ }
1097
+ });
1098
+
1099
+ // Bridge from Android ConnectivityManager.NetworkCallback. State values:
1100
+ // "available" — 默认网络刚刚可用 (启动期没网 → 接上)
1101
+ // "changed" — 已有网络切到另一个 (Wi-Fi ↔ 4G), socket 必死
1102
+ // "validated" — captive portal / VPN 验证完成, internet 才真正通
1103
+ // "lost" — 默认网络断了, 还没有备援网络
1104
+ // 前三种都强制重连; "lost" 不动 socket, 只更新 isOnline 让 UI 提示。
1105
+ // 这条路径比 navigator.online / visibilitychange 早 2-8 秒触发,
1106
+ // 切网后用户基本看不到断线提示。
1107
+ window.addEventListener("wand-android-network", function(e) {
1108
+ var which = e && e.detail && e.detail.state;
1109
+ if (which === "lost") {
1110
+ state.isOnline = false;
1111
+ try { updateOfflineBanner(); } catch (_e) {}
1112
+ return;
1113
+ }
1114
+ if (which === "available" || which === "changed" || which === "validated") {
1115
+ // 以原生信号为权威, 立刻翻 isOnline 给 UI; 有些 ROM 上
1116
+ // navigator.onLine 要等几秒才更新, 否则 banner 会闪一下。
1117
+ state.isOnline = true;
1118
+ try { updateOfflineBanner(); } catch (_e) {}
1119
+ forceReconnectWebSocket("android-network-" + which);
1120
+ }
1121
+ });
1079
1122
  }
1080
1123
 
1081
1124
  function restoreLoginSession() {
@@ -12868,20 +12911,31 @@
12868
12911
  // 这里在 visualViewport 检测到键盘收起的瞬间直接强制复位一次,
12869
12912
  // 并把 --app-viewport-height 兜底清掉,确保 .app-container 回到
12870
12913
  // 100dvh、input-panel 重新贴屏幕底部。
12914
+ //
12915
+ // Android APK (window.__wandImeNative=true) 跳过这段 iOS hack —
12916
+ // MainActivity 已经在 IME 动画 callback 里逐帧把 root setPadding,
12917
+ // WebView 直接被原生层 resize 推回到了正确位置, 这里再调
12918
+ // scrollTo(0,0) 反而会跟原生 padding 打架, 偶尔产生一帧抖。
12919
+ // 只保留 refit / 滚底两个纯展示动作。
12871
12920
  var rootEl = document.documentElement;
12872
- rootEl.style.removeProperty('--app-viewport-height');
12873
- window.scrollTo(0, 0);
12874
- if (document.scrollingElement) document.scrollingElement.scrollTop = 0;
12875
- rootEl.scrollTop = 0;
12876
- if (document.body) document.body.scrollTop = 0;
12877
- setTimeout(function() {
12878
- // 二次复位:等键盘收起动画 + iOS 自身的回滚跑完后再清一次,
12879
- // 防止 iOS 在动画过程中又把 scrollTop 推上去。
12921
+ var imeIsNative = !!window.__wandImeNative;
12922
+ if (!imeIsNative) {
12923
+ rootEl.style.removeProperty('--app-viewport-height');
12880
12924
  window.scrollTo(0, 0);
12881
12925
  if (document.scrollingElement) document.scrollingElement.scrollTop = 0;
12882
12926
  rootEl.scrollTop = 0;
12883
12927
  if (document.body) document.body.scrollTop = 0;
12884
- syncAppViewportHeight();
12928
+ }
12929
+ setTimeout(function() {
12930
+ if (!imeIsNative) {
12931
+ // 二次复位:等键盘收起动画 + iOS 自身的回滚跑完后再清一次,
12932
+ // 防止 iOS 在动画过程中又把 scrollTop 推上去。
12933
+ window.scrollTo(0, 0);
12934
+ if (document.scrollingElement) document.scrollingElement.scrollTop = 0;
12935
+ rootEl.scrollTop = 0;
12936
+ if (document.body) document.body.scrollTop = 0;
12937
+ syncAppViewportHeight();
12938
+ }
12885
12939
  ensureTerminalFit("keyboard-close", { forceReplay: true });
12886
12940
  maybeScrollTerminalToBottom("force");
12887
12941
  }, 200);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@co0ontty/wand",
3
- "version": "1.25.2",
3
+ "version": "1.25.3",
4
4
  "description": "A web terminal for local CLI tools like Claude.",
5
5
  "type": "module",
6
6
  "bin": {