diff --git a/src/app/styles/edgeToEdgeInsets.test.ts b/src/app/styles/edgeToEdgeInsets.test.ts index 522d31329..a5ef0e2df 100644 --- a/src/app/styles/edgeToEdgeInsets.test.ts +++ b/src/app/styles/edgeToEdgeInsets.test.ts @@ -73,9 +73,11 @@ describe('android edge-to-edge inset contract', () => { expect(indexTsx).toContain('installIosPwaViewportHeight();'); expect(iosPwaViewport).toContain("window.matchMedia('(display-mode: standalone)').matches"); expect(iosPwaViewport).toContain('const MIN_KEYBOARD_HEIGHT = 100'); - expect(iosPwaViewport).toContain('const keyboardOpen = fullHeight - visibleHeight'); - expect(iosPwaViewport).toContain('const height = keyboardOpen ? visibleBottom : fullHeight'); + expect(iosPwaViewport).toContain('isEditableFocused()'); + expect(iosPwaViewport).toContain('screenHeight - visibleHeight > MIN_KEYBOARD_HEIGHT'); expect(iosPwaViewport).toContain('window.setTimeout(updateHeight, 350)'); + expect(iosPwaViewport).not.toContain('fullHeight'); + expect(iosPwaViewport).not.toContain('viewportWidth'); }); it('removes the scattered safe-area css consumers', () => { diff --git a/src/app/utils/iosPwaViewport.ts b/src/app/utils/iosPwaViewport.ts index 326884273..b2e5c177b 100644 --- a/src/app/utils/iosPwaViewport.ts +++ b/src/app/utils/iosPwaViewport.ts @@ -5,13 +5,24 @@ const isStandaloneIosPwa = (): boolean => window.matchMedia('(display-mode: standalone)').matches && CSS.supports('-webkit-touch-callout: none'); +const isEditableFocused = (): boolean => { + const el = document.activeElement as HTMLElement | null; + if (!el) return false; + return el.tagName === 'INPUT' || el.tagName === 'TEXTAREA' || el.isContentEditable; +}; + +const fullScreenHeight = (): number => { + const { width, height } = window.screen; + return window.matchMedia('(orientation: portrait)').matches + ? Math.max(width, height) + : Math.min(width, height); +}; + export function installIosPwaViewportHeight(): void { if (!isStandaloneIosPwa()) return; let frame = 0; let settleTimer = 0; - let fullHeight = 0; - let viewportWidth = window.innerWidth; const updateHeight = () => { frame = 0; @@ -19,15 +30,10 @@ export function installIosPwaViewportHeight(): void { const visibleHeight = viewport?.height ?? window.innerHeight; const visibleBottom = visibleHeight + (viewport?.offsetTop ?? 0); - if (window.innerWidth !== viewportWidth) { - viewportWidth = window.innerWidth; - fullHeight = visibleBottom; - } - - const keyboardOpen = fullHeight - visibleHeight > MIN_KEYBOARD_HEIGHT; - if (!keyboardOpen) fullHeight = Math.max(fullHeight, visibleBottom); + const screenHeight = fullScreenHeight(); + const keyboardOpen = isEditableFocused() && screenHeight - visibleHeight > MIN_KEYBOARD_HEIGHT; + const height = keyboardOpen ? visibleBottom : screenHeight; - const height = keyboardOpen ? visibleBottom : fullHeight; document.documentElement.style.setProperty(IOS_PWA_VIEWPORT_HEIGHT, `${Math.round(height)}px`); };