diff --git a/src/hooks/use-keyboard-height.ts b/src/hooks/use-keyboard-height.ts index 1b3e28d1..b5f09b2a 100644 --- a/src/hooks/use-keyboard-height.ts +++ b/src/hooks/use-keyboard-height.ts @@ -57,6 +57,9 @@ export function useKeyboardHeight({ let lastViewportHeight = -1; let lastInputLift = -1; let lastMayBeKeyboardClose = false; + const environment = getKeyboardAdaptEnvironment(); + + log.debug("[keyboard] environment", environment); const apply = () => { rafId = null; @@ -69,6 +72,11 @@ export function useKeyboardHeight({ shouldReleaseFallback(metrics, focusedAtRef.current) ) { fallbackAllowedRef.current = false; + log.debug("[keyboard] fallback released", { + reason: "keyboard-close-detected", + environment, + metrics: formatMetrics(metrics), + }); } lastMayBeKeyboardClose = false; @@ -109,14 +117,13 @@ export function useKeyboardHeight({ `${inputLift}px`, ); log.debug("[keyboard] apply", { + environment, active: activeRef.current, - keyboardHeight, - viewportHeight, inputLift, fallbackLift, fallbackAllowed: fallbackAllowedRef.current, - visualViewport: metrics.hasVisualViewport, - virtualKeyboard: metrics.hasVirtualKeyboard, + source: getLiftSource(inputLift, fallbackLift), + metrics: formatMetrics(metrics), }); } }; @@ -261,11 +268,7 @@ function isPossibleKeyboardCloseEvent(event: Event): boolean { function shouldUseInAppKeyboardFallback(): boolean { if (typeof navigator === "undefined") return false; const ua = navigator.userAgent; - return ( - PlatformDetector.isAndroid(ua) && - PlatformDetector.isXiaomiFamilyDevice(ua) && - BrowserDetector.isFacebookInAppBrowser(ua) - ); + return getKeyboardAdaptEnvironment(ua).usesXiaomiFacebookFallback; } function clamp(value: number, min: number, max: number): number { @@ -278,6 +281,53 @@ function resetVars(): void { document.documentElement.style.setProperty(INPUT_LIFT_VAR, "0px"); } +function getKeyboardAdaptEnvironment(ua: string | null = null) { + const platform = PlatformDetector.getPlatformInfo(ua); + const browser = BrowserDetector.getBrowserInfo(ua); + const isXiaomiFamilyDevice = PlatformDetector.isXiaomiFamilyDevice(ua); + const isFacebookInAppBrowser = BrowserDetector.isFacebookInAppBrowser(ua); + + 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, + isFacebookInAppBrowser, + hasVisualViewport: + typeof window !== "undefined" && window.visualViewport != null, + hasVirtualKeyboard: getVirtualKeyboard() != null, + usesXiaomiFacebookFallback: + platform.isAndroid && isXiaomiFamilyDevice && isFacebookInAppBrowser, + }; +} + +function formatMetrics(metrics: ViewportMetrics) { + return { + hasVisualViewport: metrics.hasVisualViewport, + hasVirtualKeyboard: metrics.hasVirtualKeyboard, + layoutHeight: Math.round(metrics.layoutHeight), + visibleHeight: Math.round(metrics.visibleHeight), + visibleBottom: Math.round(metrics.visibleBottom), + keyboardHeight: Math.round(metrics.keyboardHeight), + }; +} + +function getLiftSource(inputLift: number, fallbackLift: number): string { + if (inputLift <= 0) return "none"; + if (fallbackLift > 0 && inputLift === fallbackLift) return "xiaomi-facebook-fallback"; + if (fallbackLift > 0) return "overlap-and-fallback"; + return "target-overlap"; +} + interface VirtualKeyboardLike extends EventTarget { readonly boundingRect: DOMRectReadOnly; }