Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: fixed i-lock-page-scroll on ios #1059

Merged
merged 14 commits into from
Dec 7, 2023
6 changes: 5 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,11 @@ Changelog

_Note: Gaps between patch versions are faulty, broken or test releases._

## v3.??.? (2023-??-??)
## v3.62.2 (2023-12-07)

#### :bug: Bug Fix

* Fixed a bug with clearing event listeners on ios `traits/i-lock-page-scroll`

#### :house: Internal

Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"main": "src/core/index.js",
"typings": "index.d.ts",
"license": "MIT",
"version": "3.62.1",
"version": "3.62.2",
"author": {
"name": "kobezzza",
"email": "[email protected]",
Expand Down
6 changes: 6 additions & 0 deletions src/traits/i-lock-page-scroll/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,12 @@ Changelog
> - :house: [Internal]
> - :nail_care: [Polish]

## v3.62.2 (2023-12-07)

#### :bug: Bug Fix

* Fixed a bug with clearing event listeners on ios

## v3.57.0 (2023-08-28)

#### :bug: Bug Fix
Expand Down
120 changes: 71 additions & 49 deletions src/traits/i-lock-page-scroll/i-lock-page-scroll.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,14 @@ export default abstract class iLockPageScroll {
r: {unsafe: {async: $a}}
} = component;

if (is.mobile !== false && is.iOS !== false) {
iLockPageScroll.initIOSScrollableNodeListeners(component, scrollableNode);
}

let
promise = Promise.resolve();

if (r[$$.isLocked] === true) {
$a.clearAll({group});
Gannicus91 marked this conversation as resolved.
Show resolved Hide resolved
return promise;
}

Expand All @@ -49,52 +52,6 @@ export default abstract class iLockPageScroll {

if (is.mobile !== false) {
if (is.iOS !== false) {
if (scrollableNode) {
const
onTouchStart = (e: TouchEvent) => component[$$.initialY] = e.targetTouches[0].clientY;

$a.on(scrollableNode, 'touchstart', onTouchStart, {
group,
label: $$.touchstart
});

const onTouchMove = (e: TouchEvent) => {
let
scrollTarget = <HTMLElement>(e.target ?? scrollableNode);

while (scrollTarget !== scrollableNode) {
if (scrollTarget.scrollHeight > scrollTarget.clientHeight || !scrollTarget.parentElement) {
break;
}

scrollTarget = scrollTarget.parentElement;
}

const {
scrollTop,
scrollHeight,
clientHeight
} = scrollTarget;

const
clientY = e.targetTouches[0].clientY - component[$$.initialY],
isOnTop = clientY > 0 && scrollTop === 0,
isOnBottom = clientY < 0 && scrollTop + clientHeight + 1 >= scrollHeight;

if ((isOnTop || isOnBottom) && e.cancelable) {
return e.preventDefault();
}

e.stopPropagation();
};

$a.on(scrollableNode, 'touchmove', onTouchMove, {
group,
label: $$.touchmove,
options: {passive: false}
});
}

$a.on(document, 'touchmove', (e: TouchEvent) => e.cancelable && e.preventDefault(), {
group,
label: $$.preventTouchMove,
Expand All @@ -114,7 +71,7 @@ export default abstract class iLockPageScroll {
body.scrollTop;

r[$$.scrollTop] = scrollTop;
body.style.top = `-${scrollTop}px`;
body.style.top = (-scrollTop).px;
r.setRootMod('lockScrollMobile', true);

r[$$.isLocked] = true;
Expand All @@ -133,7 +90,7 @@ export default abstract class iLockPageScroll {
scrollBarWidth = globalThis.innerWidth - body.clientWidth;

r[$$.paddingRight] = body.style.paddingRight;
body.style.paddingRight = `${scrollBarWidth}px`;
body.style.paddingRight = scrollBarWidth.px;
r.setRootMod('lockScrollDesktop', true);

r[$$.isLocked] = true;
Expand Down Expand Up @@ -164,6 +121,7 @@ export default abstract class iLockPageScroll {
r.removeRootMod('lockScrollMobile', true);
r.removeRootMod('lockScrollDesktop', true);
r[$$.isLocked] = false;
iLockPageScroll.scrollableNodes = new WeakSet<Element>();

if (is.mobile !== false) {
globalThis.scrollTo(0, r[$$.scrollTop]);
Expand Down Expand Up @@ -211,6 +169,70 @@ export default abstract class iLockPageScroll {
});
}

/**
* A set of scrollable nodes for the iOS platform
*/
protected static scrollableNodes: WeakSet<Element> = new WeakSet<Element>();

/**
* Initializes touch event listeners for the provided node on the iOS platform
* @see https://stackoverflow.com/questions/59193062/how-to-disable-scrolling-on-body-in-ios-13-safari-when-saved-as-pwa-to-the-hom
*
* @param component
* @param [scrollableNode]
*/
protected static initIOSScrollableNodeListeners(component: iBlock, scrollableNode?: Element): void {
Gannicus91 marked this conversation as resolved.
Show resolved Hide resolved
const
{r: {unsafe: {async: $a}}} = component;

if (scrollableNode == null || iLockPageScroll.scrollableNodes.has(scrollableNode)) {
return;
}

iLockPageScroll.scrollableNodes.add(scrollableNode);

const
onTouchStart = (e: TouchEvent) => component[$$.initialY] = e.targetTouches[0].clientY;

$a.on(scrollableNode, 'touchstart', onTouchStart, {
group
});

const onTouchMove = (e: TouchEvent) => {
let
scrollTarget = <HTMLElement>(e.target ?? scrollableNode);

while (
scrollTarget !== scrollableNode &&
scrollTarget.scrollHeight <= scrollTarget.clientHeight && scrollTarget.parentElement
) {
scrollTarget = scrollTarget.parentElement;
}

const {
scrollTop,
scrollHeight,
clientHeight
} = scrollTarget;

const
clientY = e.targetTouches[0].clientY - component[$$.initialY],
isOnTop = clientY > 0 && scrollTop === 0,
isOnBottom = clientY < 0 && scrollTop + clientHeight + 1 >= scrollHeight;

if ((isOnTop || isOnBottom) && e.cancelable) {
return e.preventDefault();
}

e.stopPropagation();
};

$a.on(scrollableNode, 'touchmove', onTouchMove, {
group,
options: {passive: false}
});
}

/**
* Locks the document scroll, i.e.,
* it prevents any scrolling on the document except withing the specified node
Expand Down
Loading