From fe51e90efdc216df00378f5644c44f665c6d315c Mon Sep 17 00:00:00 2001 From: mortezaei Date: Thu, 20 Aug 2026 15:38:56 +0330 Subject: [PATCH] fix: calibrate initial keyboard estimate dynamically based on viewport height and latch intermediate animation frames --- .../question-viewport-coordinator.ts | 38 +++++++++++++------ 1 file changed, 26 insertions(+), 12 deletions(-) diff --git a/src/components/Componentes/question-viewport-coordinator.ts b/src/components/Componentes/question-viewport-coordinator.ts index 2364896..e63b281 100644 --- a/src/components/Componentes/question-viewport-coordinator.ts +++ b/src/components/Componentes/question-viewport-coordinator.ts @@ -82,6 +82,14 @@ export function isActiveQuestionKeyboardInput( ); } +function getDefaultKeyboardHeight(): number { + if (typeof window !== "undefined" && window.innerHeight > 0) { + // 37.5% of screen height matches standard mobile soft keyboards (e.g. 287px on 765px screen, 316px on 844px screen) + return Math.round(window.innerHeight * 0.375); + } + return 285; +} + function setLift(nextLift: number) { const prevLift = currentLift; currentLift = Math.max(0, Math.round(nextLift)); @@ -94,9 +102,8 @@ function setLift(nextLift: number) { function getKeyboardTop() { if (!keyboardVisible || !activeQuestionInput) return null; - // Expected full keyboard height for mobile devices is ~320px const fullKeyboardHeight = - lastKeyboardHeight > 250 ? lastKeyboardHeight : 320; + lastKeyboardHeight > 200 ? lastKeyboardHeight : getDefaultKeyboardHeight(); const targetHeight = Math.max(keyboardHeight, fullKeyboardHeight); const flutterTop = window.innerHeight - targetHeight; @@ -180,17 +187,20 @@ export function updateQuestionKeyboardHeight(height: number) { if (nextHeight > 0) { keyboardVisible = true; - if (nextHeight > 250) { - lastKeyboardHeight = Math.max(lastKeyboardHeight, nextHeight); - keyboardHeight = nextHeight; - } else if (activeQuestionInput) { - // Keyboard is opening with incremental animation frames (e.g. Samsung 11.3px, 26.3px, 32px) - // Keep expected target height so lift doesn't bounce/collapse during animation frames. - const expectedHeight = lastKeyboardHeight > 250 ? lastKeyboardHeight : 320; - keyboardHeight = Math.max(nextHeight, expectedHeight); + const defaultKHeight = getDefaultKeyboardHeight(); + const expectedHeight = + lastKeyboardHeight > 200 ? lastKeyboardHeight : defaultKHeight; + + if (activeQuestionInput && nextHeight < expectedHeight - 15) { + // Keyboard is in the middle of opening animation frames (e.g. Samsung 8.7px, 182px, 205px, 246px, 262px, 273px) + // Keep keyboardHeight at expectedHeight so lift doesn't stutter/jitter during intermediate animation frames. + keyboardHeight = expectedHeight; } else { + // Settled at or above target height + lastKeyboardHeight = Math.max(lastKeyboardHeight, nextHeight); keyboardHeight = nextHeight; } + if (isActiveQuestionKeyboardInput(document.activeElement)) { activeQuestionInput = document.activeElement; } @@ -216,7 +226,11 @@ export function resetQuestionKeyboardState() { window.cancelAnimationFrame(geometryFrame); geometryFrame = null; } - if (isActiveQuestionKeyboardInput(document.activeElement)) { + if ( + typeof document !== "undefined" && + document.activeElement instanceof HTMLElement && + isActiveQuestionKeyboardInput(document.activeElement) + ) { document.activeElement.blur(); } keyboardVisible = false; @@ -233,7 +247,7 @@ export function useQuestionViewportCoordinator() { if (!isActiveQuestionKeyboardInput(event.target)) return; activeQuestionInput = event.target; const expectedHeight = - lastKeyboardHeight > 250 ? lastKeyboardHeight : 320; + lastKeyboardHeight > 200 ? lastKeyboardHeight : getDefaultKeyboardHeight(); keyboardHeight = expectedHeight; keyboardVisible = true; console.log('[Coord] focusin on input:', (event.target as HTMLElement).tagName, 'targetKHeight:', expectedHeight);