Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 29 additions & 3 deletions core/src/utils/input-shims/hacks/scroll-assist.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import type { KeyboardResizeOptions } from '@capacitor/keyboard';
import { win } from '@utils/browser';

import { getScrollElement, scrollByPoint } from '../../content';
import { raf } from '../../helpers';
Expand Down Expand Up @@ -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
Expand All @@ -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);

Expand Down Expand Up @@ -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
Expand Down
9 changes: 7 additions & 2 deletions core/src/utils/input-shims/hacks/scroll-data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ownerDocument gives you the document for a node: https://developer.mozilla.org/en-US/docs/Web/API/Node/ownerDocument

defaultView gives you the window associated with the document if available: https://developer.mozilla.org/en-US/docs/Web/API/Document/defaultView

I opted to simplify this by using our win util since that accounts for SSR: https://github.com/ionic-team/ionic-framework/pull/28169/files#diff-ebd08eae5669c5c10420cdb5d258ee6db362b7796cc76ee15e34441a84d48888R51

platformHeight
);
};

Expand Down