From 578981b2d0b7219db9b30419e70511b47fa904ea Mon Sep 17 00:00:00 2001 From: Liam DeBeasi Date: Tue, 12 Sep 2023 16:00:53 -0400 Subject: [PATCH] fix(scroll-assist): improve input scroll accuracy --- .../utils/input-shims/hacks/scroll-assist.ts | 32 +++++++++++++++++-- .../utils/input-shims/hacks/scroll-data.ts | 9 ++++-- 2 files changed, 36 insertions(+), 5 deletions(-) diff --git a/core/src/utils/input-shims/hacks/scroll-assist.ts b/core/src/utils/input-shims/hacks/scroll-assist.ts index 97928d608ec..400b201f094 100644 --- a/core/src/utils/input-shims/hacks/scroll-assist.ts +++ b/core/src/utils/input-shims/hacks/scroll-assist.ts @@ -1,4 +1,5 @@ import type { KeyboardResizeOptions } from '@capacitor/keyboard'; +import { win } from '@utils/browser'; import { getScrollElement, scrollByPoint } from '../../content'; import { raf } from '../../helpers'; @@ -34,6 +35,21 @@ export const enableScrollAssist = ( const addScrollPadding = enableScrollPadding && (keyboardResize === undefined || keyboardResize.mode === KeyboardResize.None); + /** + * When adding scroll padding we need to know + * how much of the viewport the keyboard obscures. + * We do this by subtracting the keyboard height + * from the platform height. + * + * If we compute this value when switching between + * inputs then the webview may already be resized. + * At this point, `win.innerHeight` has already accounted + * for the keyboard meaning we would then subtract + * the keyboard height again. This will result in the input + * being scrolled more than it needs to. + */ + const platformHeight = win !== undefined ? win.innerHeight : 0; + /** * When the input is about to receive * focus, we need to move it to prevent @@ -50,7 +66,16 @@ export const enableScrollAssist = ( inputEl.removeAttribute(SKIP_SCROLL_ASSIST); return; } - jsSetFocus(componentEl, inputEl, contentEl, footerEl, keyboardHeight, addScrollPadding, disableClonedInput); + jsSetFocus( + componentEl, + inputEl, + contentEl, + footerEl, + keyboardHeight, + addScrollPadding, + disableClonedInput, + platformHeight + ); }; componentEl.addEventListener('focusin', focusIn, true); @@ -84,12 +109,13 @@ const jsSetFocus = async ( footerEl: HTMLIonFooterElement | null, keyboardHeight: number, enableScrollPadding: boolean, - disableClonedInput = false + disableClonedInput = false, + platformHeight = 0 ) => { if (!contentEl && !footerEl) { return; } - const scrollData = getScrollData(componentEl, (contentEl || footerEl)!, keyboardHeight); + const scrollData = getScrollData(componentEl, (contentEl || footerEl)!, keyboardHeight, platformHeight); if (contentEl && Math.abs(scrollData.scrollAmount) < 4) { // the text input is in a safe position that doesn't diff --git a/core/src/utils/input-shims/hacks/scroll-data.ts b/core/src/utils/input-shims/hacks/scroll-data.ts index 48b4a12007d..cc82553b559 100644 --- a/core/src/utils/input-shims/hacks/scroll-data.ts +++ b/core/src/utils/input-shims/hacks/scroll-data.ts @@ -9,13 +9,18 @@ export interface ScrollData { inputSafeY: number; } -export const getScrollData = (componentEl: HTMLElement, contentEl: HTMLElement, keyboardHeight: number): ScrollData => { +export const getScrollData = ( + componentEl: HTMLElement, + contentEl: HTMLElement, + keyboardHeight: number, + platformHeight: number +): ScrollData => { const itemEl = (componentEl.closest('ion-item,[ion-item]') as HTMLElement) ?? componentEl; return calcScrollData( itemEl.getBoundingClientRect(), contentEl.getBoundingClientRect(), keyboardHeight, - (componentEl as any).ownerDocument.defaultView.innerHeight // TODO(FW-2832): type + platformHeight ); };