diff --git a/src/hooks/use-keyboard-height.ts b/src/hooks/use-keyboard-height.ts index b80e53ed..4f541d86 100644 --- a/src/hooks/use-keyboard-height.ts +++ b/src/hooks/use-keyboard-height.ts @@ -24,6 +24,14 @@ const FALLBACK_KEYBOARD_MIN = 260; const FALLBACK_KEYBOARD_MAX = 380; const FALLBACK_CLOSE_GRACE_MS = 900; const RECHECK_DELAYS_MS = [0, 50, 120, 240, 420, 700]; +const FALLBACK_RELEASE_EVENT_TYPES = new Set([ + "resize", + "scroll", + "geometrychange", + "focusout", + "blur", + "visibilitychange", +]); const RECHECK_EVENT = "cozsweet:keyboard-recheck"; const log = new Logger("HooksUseKeyboardHeight"); @@ -57,6 +65,7 @@ export function useKeyboardHeight({ let lastViewportHeight = -1; let lastInputLift = -1; let lastMayBeKeyboardClose = false; + let fallbackWasApplied = false; const environment = getKeyboardAdaptEnvironment(); log.debug("[keyboard] environment", environment); @@ -81,6 +90,7 @@ export function useKeyboardHeight({ shouldReleaseFallback(metrics, focusedAtRef.current) ) { fallbackAllowedRef.current = false; + blurKeyboardTarget(targetRef?.current); log.debug("[keyboard] fallback released", { reason: "keyboard-close-detected", environment, @@ -102,6 +112,8 @@ export function useKeyboardHeight({ ) : 0, ); + fallbackWasApplied = + fallbackLift > 0 && inputLift >= fallbackLift && fallbackAllowedRef.current; if (keyboardHeight !== lastKeyboardHeight) { lastKeyboardHeight = keyboardHeight; @@ -144,7 +156,7 @@ export function useKeyboardHeight({ }; const scheduleRechecks = (event?: Event) => { - if (event && isPossibleKeyboardCloseEvent(event)) { + if (event && isPossibleKeyboardCloseEvent(event, fallbackWasApplied)) { lastMayBeKeyboardClose = true; } timeoutIds.forEach((id) => window.clearTimeout(id)); @@ -164,6 +176,8 @@ export function useKeyboardHeight({ window.addEventListener("orientationchange", scheduleRechecks); window.addEventListener("focusin", scheduleRechecks); window.addEventListener("focusout", scheduleRechecks); + window.addEventListener("blur", scheduleRechecks); + document.addEventListener("visibilitychange", scheduleRechecks); window.addEventListener(RECHECK_EVENT, scheduleRechecks); scheduleRechecks(); @@ -180,6 +194,8 @@ export function useKeyboardHeight({ window.removeEventListener("orientationchange", scheduleRechecks); window.removeEventListener("focusin", scheduleRechecks); window.removeEventListener("focusout", scheduleRechecks); + window.removeEventListener("blur", scheduleRechecks); + document.removeEventListener("visibilitychange", scheduleRechecks); window.removeEventListener(RECHECK_EVENT, scheduleRechecks); resetVars(); }; @@ -270,8 +286,14 @@ function hasDetectedKeyboard(metrics: ViewportMetrics): boolean { ); } -function isPossibleKeyboardCloseEvent(event: Event): boolean { - return event.type === "resize" || event.type === "geometrychange"; +function isPossibleKeyboardCloseEvent( + event: Event, + fallbackWasApplied: boolean, +): boolean { + if (!fallbackWasApplied) { + return event.type === "resize" || event.type === "geometrychange"; + } + return FALLBACK_RELEASE_EVENT_TYPES.has(event.type); } function isKeyboardTargetActive( @@ -281,6 +303,11 @@ function isKeyboardTargetActive( return reactActive || (target != null && document.activeElement === target); } +function blurKeyboardTarget(target: HTMLElement | null | undefined): void { + if (!target || document.activeElement !== target) return; + target.blur(); +} + function shouldUseInAppKeyboardFallback(): boolean { if (typeof navigator === "undefined") return false; const ua = navigator.userAgent;