fix(keyboard): support OPPO Facebook fallback

This commit is contained in:
2026-07-01 17:30:29 +08:00
parent fa5b380577
commit 94bb6adbb5
5 changed files with 42 additions and 52 deletions
@@ -7,42 +7,42 @@ function makeEnvironment(
overrides: Partial<KeyboardAdaptEnvironment> = {},
): KeyboardAdaptEnvironment {
return {
platform: "android",
osName: "Android",
osVersion: "16",
deviceVendor: "Xiaomi",
deviceModel: "2211133C",
isAndroid: true,
isIOS: false,
isMobile: true,
browserName: "Facebook",
browserVersion: "566.0.0.48.73",
isInAppBrowser: true,
inAppBrowserName: "facebook",
isXiaomiFamilyDevice: true,
isOppoFamilyDevice: false,
isFacebookInAppBrowser: true,
hasVisualViewport: true,
usesXiaomiFacebookFallback: true,
usesAndroidFacebookFallback: true,
...overrides,
};
}
describe("shouldEnableKeyboardAdaptation", () => {
it("enables only for Xiaomi Android Facebook in-app browser fallback", () => {
it("enables for Xiaomi Android Facebook in-app browser fallback", () => {
expect(shouldEnableKeyboardAdaptation(makeEnvironment())).toBe(true);
});
it("enables for OPPO Android Facebook in-app browser fallback", () => {
expect(
shouldEnableKeyboardAdaptation(
makeEnvironment({
platform: "ios",
osName: "iOS",
osVersion: "18",
deviceVendor: "Apple",
deviceModel: "iPhone",
isAndroid: false,
isIOS: true,
isXiaomiFamilyDevice: false,
usesXiaomiFacebookFallback: false,
isOppoFamilyDevice: true,
usesAndroidFacebookFallback: true,
}),
),
).toBe(true);
});
it("disables for non-target platforms, browsers, and devices", () => {
expect(
shouldEnableKeyboardAdaptation(
makeEnvironment({
isAndroid: false,
isXiaomiFamilyDevice: false,
isOppoFamilyDevice: false,
usesAndroidFacebookFallback: false,
}),
),
).toBe(false);
@@ -50,10 +50,9 @@ describe("shouldEnableKeyboardAdaptation", () => {
expect(
shouldEnableKeyboardAdaptation(
makeEnvironment({
browserName: "Instagram",
inAppBrowserName: "instagram",
isFacebookInAppBrowser: false,
usesXiaomiFacebookFallback: false,
usesAndroidFacebookFallback: false,
}),
),
).toBe(false);
@@ -61,10 +60,9 @@ describe("shouldEnableKeyboardAdaptation", () => {
expect(
shouldEnableKeyboardAdaptation(
makeEnvironment({
deviceVendor: "Samsung",
deviceModel: "SM-G991B",
isXiaomiFamilyDevice: false,
usesXiaomiFacebookFallback: false,
isOppoFamilyDevice: false,
usesAndroidFacebookFallback: false,
}),
),
).toBe(false);
+8 -13
View File
@@ -8,32 +8,27 @@ export function getKeyboardAdaptEnvironment(
const platform = PlatformDetector.getPlatformInfo(ua);
const browser = BrowserDetector.getBrowserInfo(ua);
const isXiaomiFamilyDevice = PlatformDetector.isXiaomiFamilyDevice(ua);
const isOppoFamilyDevice = PlatformDetector.isOppoFamilyDevice(ua);
const isFacebookInAppBrowser = BrowserDetector.isFacebookInAppBrowser(ua);
const usesAndroidFacebookFallback =
platform.isAndroid &&
(isXiaomiFamilyDevice || isOppoFamilyDevice) &&
isFacebookInAppBrowser;
return {
platform: platform.platform,
osName: platform.osName,
osVersion: platform.osVersion,
deviceVendor: platform.deviceVendor,
deviceModel: platform.deviceModel,
isAndroid: platform.isAndroid,
isIOS: platform.isIOS,
isMobile: platform.isMobile,
browserName: browser.name,
browserVersion: browser.version,
isInAppBrowser: browser.isInAppBrowser,
inAppBrowserName: browser.inAppBrowserName,
isXiaomiFamilyDevice,
isOppoFamilyDevice,
isFacebookInAppBrowser,
hasVisualViewport:
typeof window !== "undefined" && window.visualViewport != null,
usesXiaomiFacebookFallback:
platform.isAndroid && isXiaomiFamilyDevice && isFacebookInAppBrowser,
usesAndroidFacebookFallback,
};
}
export function shouldEnableKeyboardAdaptation(
environment: KeyboardAdaptEnvironment,
): boolean {
return environment.usesXiaomiFacebookFallback;
return environment.usesAndroidFacebookFallback;
}
+3 -3
View File
@@ -1,13 +1,13 @@
"use client";
/**
* 小米 Android + Facebook IAB 专用输入框避让 hook。
* 特定 Android 设备 + Facebook IAB 专用输入框避让 hook。
*
* 这不是通用软键盘方案。它只解决一个已知 WebView 问题:
* 输入框 focus 后键盘弹出,但 Facebook IAB 没有稳定调整页面 viewport
* 导致底部输入框被键盘遮挡。
*
* 策略:
* - 非小米 Android Facebook IAB:完全不生效。
* - 非目标 Android Facebook IAB 设备:完全不生效。
* - focus 后短期多次测量输入框是否被 visibleViewport 遮挡。
* - 若 viewport 没有可靠变化,则使用固定 fallback 抬升。
* - 聚焦期间轻量轮询;一旦检测到 viewport 恢复,主动 blur 并清除抬升。
@@ -67,7 +67,7 @@ export function useKeyboardHeight({
if (!shouldEnableKeyboardAdaptation(environment)) {
resetInputLiftVar();
log.debug("[keyboard] disabled", {
reason: "not-xiaomi-facebook-iab",
reason: "not-android-facebook-fallback-device",
environment,
});
return;
+2 -11
View File
@@ -7,20 +7,11 @@ export interface UseKeyboardHeightOptions {
}
export interface KeyboardAdaptEnvironment {
platform: string;
osName: string;
osVersion: string;
deviceVendor: string;
deviceModel: string;
isAndroid: boolean;
isIOS: boolean;
isMobile: boolean;
browserName: string;
browserVersion: string;
isInAppBrowser: boolean;
inAppBrowserName: string | null;
isXiaomiFamilyDevice: boolean;
isOppoFamilyDevice: boolean;
isFacebookInAppBrowser: boolean;
hasVisualViewport: boolean;
usesXiaomiFacebookFallback: boolean;
usesAndroidFacebookFallback: boolean;
}
+6
View File
@@ -91,6 +91,12 @@ export class PlatformDetector {
return /\b(Xiaomi|Redmi|POCO|Mi\s|MIX|MIUI)\b/i.test(target);
}
static isOppoFamilyDevice(ua: string | null = null): boolean {
const info = PlatformDetector.getPlatformInfo(ua);
const target = `${info.deviceVendor} ${info.deviceModel} ${info.userAgent}`;
return /\b(OPPO|OPlus|ColorOS|CPH\d{3,})\b/i.test(target);
}
private static getUserAgent(ua: string | null = null): string {
if (ua) return ua;
if (typeof navigator === "undefined") return "";