fix(chat): scope keyboard fallback to Xiaomi Facebook IAB

This commit is contained in:
2026-06-24 15:40:16 +08:00
parent 08c954903f
commit a229dcf7d1
2 changed files with 17 additions and 5 deletions
+11 -5
View File
@@ -2,17 +2,17 @@
/**
* 软键盘避让 hook。
*
* 目标环境:Facebook IAB / 小米 WebView 等软键盘覆盖页面但 viewport 信号不稳定的浏览器。
* 目标环境:小米系设备上的 Facebook IAB 等软键盘覆盖页面但 viewport 信号不稳定的浏览器。
*
* 策略:
* 1. 持续写入 --app-viewport-height,聊天页高度不再只依赖 100dvh。
* 2. 优先使用 visualViewport 计算键盘高度。
* 3. 输入框聚焦后测量目标元素是否越过可见底部,计算额外抬升。
* 4. Android 应用内浏览器若 viewport 未可靠变化,启用保守 fallback 抬升。
* 4. 小米系 Android + Facebook IAB 若 viewport 未可靠变化,启用保守 fallback 抬升。
*/
import { type RefObject, useEffect, useRef } from "react";
import { BrowserDetector, Logger } from "@/utils";
import { BrowserDetector, Logger, PlatformDetector } from "@/utils";
const KEYBOARD_VAR = "--keyboard-height";
const VIEWPORT_VAR = "--app-viewport-height";
@@ -57,11 +57,12 @@ export function useKeyboardHeight({
const metrics = readViewportMetrics();
const keyboardHeight = Math.round(metrics.keyboardHeight);
const viewportHeight = Math.round(metrics.visibleHeight);
const fallbackLift = computeFallbackLift(metrics);
const inputLift = Math.round(
activeRef.current
? Math.max(
computeTargetOverlap(targetRef?.current, metrics.visibleBottom),
computeFallbackLift(metrics),
fallbackLift,
)
: 0,
);
@@ -93,6 +94,7 @@ export function useKeyboardHeight({
keyboardHeight,
viewportHeight,
inputLift,
fallbackLift,
visualViewport: metrics.hasVisualViewport,
});
}
@@ -198,7 +200,11 @@ function computeFallbackLift(metrics: ViewportMetrics): number {
function shouldUseInAppKeyboardFallback(): boolean {
if (typeof navigator === "undefined") return false;
const ua = navigator.userAgent;
return /Android/i.test(ua) && BrowserDetector.isInAppBrowser(ua);
return (
PlatformDetector.isAndroid(ua) &&
PlatformDetector.isXiaomiFamilyDevice(ua) &&
BrowserDetector.isFacebookInAppBrowser(ua)
);
}
function clamp(value: number, min: number, max: number): number {
+6
View File
@@ -85,6 +85,12 @@ export class PlatformDetector {
return PlatformDetector.getPlatformInfo(ua).isDesktop;
}
static isXiaomiFamilyDevice(ua: string | null = null): boolean {
const info = PlatformDetector.getPlatformInfo(ua);
const target = `${info.deviceVendor} ${info.deviceModel} ${info.userAgent}`;
return /\b(Xiaomi|Redmi|POCO|Mi\s|MIX|MIUI)\b/i.test(target);
}
private static getUserAgent(ua: string | null = null): string {
if (ua) return ua;
if (typeof navigator === "undefined") return "";