fix(chat): scope keyboard fallback to Xiaomi Facebook IAB
This commit is contained in:
@@ -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 {
|
||||
|
||||
@@ -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 "";
|
||||
|
||||
Reference in New Issue
Block a user