Fix mobile scroll through slider sections
This commit is contained in:
@@ -12,17 +12,21 @@
|
||||
const MEDIA_HANDLE_BOUND_FLAG = "__nodedcMediaHandleBound";
|
||||
const DOCK_LINK_BOUND_FLAG = "__nodedcDockLinkBound";
|
||||
const ORDERED_SLIDER_BOUND_FLAG = "__nodedcOrderedSliderBound";
|
||||
const SLIDER_TOUCH_GUARD_FLAG = "__nodedcSliderTouchGuardBound";
|
||||
const LAZY_MEDIA_VIDEO_BOUND_FLAG = "__nodedcLazyMediaVideoBound";
|
||||
const SCROLL_HEIGHT_SYNC_FLAG = "__nodedcScrollHeightSyncBound";
|
||||
const NOTIFICATION_STACK_BOUND_FLAG = "__nodedcNotificationStackBound";
|
||||
const SCROLL_HEIGHT_SYNC_WARMUP_MS = 14000;
|
||||
const SCROLL_HEIGHT_SYNC_INTERVAL_MS = 90;
|
||||
const SLIDER_TOUCH_INTENT_DISTANCE = 8;
|
||||
const SLIDER_HORIZONTAL_INTENT_RATIO = 1.35;
|
||||
const IMAGE_EXTENSIONS = new Set(["avif", "gif", "jpeg", "jpg", "png", "svg", "webp"]);
|
||||
const VIDEO_EXTENSIONS = new Set(["m4v", "mov", "mp4", "webm"]);
|
||||
let lastDocumentScrollHeight = 0;
|
||||
let scrollHeightSyncFrame = 0;
|
||||
let scrollHeightSyncShouldForce = false;
|
||||
let scrollHeightDeferredSync = 0;
|
||||
let activeSliderTouch = null;
|
||||
|
||||
function isDesktopPointer() {
|
||||
return window.matchMedia?.("(pointer: fine)").matches ?? true;
|
||||
@@ -333,6 +337,61 @@
|
||||
document.querySelectorAll('[data-module="mail-list"]').forEach(bindMailListWheel);
|
||||
}
|
||||
|
||||
function bindSliderTouchGuard() {
|
||||
if (document[SLIDER_TOUCH_GUARD_FLAG]) return;
|
||||
document[SLIDER_TOUCH_GUARD_FLAG] = true;
|
||||
|
||||
window.addEventListener(
|
||||
"touchstart",
|
||||
(event) => {
|
||||
const slider = event.target?.closest?.('[data-module="slider"]');
|
||||
const touch = event.touches?.[0];
|
||||
activeSliderTouch = slider && touch
|
||||
? {
|
||||
identifier: touch.identifier,
|
||||
startX: touch.clientX,
|
||||
startY: touch.clientY,
|
||||
intent: "",
|
||||
}
|
||||
: null;
|
||||
},
|
||||
{ capture: true, passive: true },
|
||||
);
|
||||
|
||||
window.addEventListener(
|
||||
"touchmove",
|
||||
(event) => {
|
||||
if (!activeSliderTouch) return;
|
||||
const touch = Array.from(event.touches || []).find(
|
||||
(candidate) => candidate.identifier === activeSliderTouch.identifier,
|
||||
);
|
||||
if (!touch) return;
|
||||
|
||||
const deltaX = Math.abs(touch.clientX - activeSliderTouch.startX);
|
||||
const deltaY = Math.abs(touch.clientY - activeSliderTouch.startY);
|
||||
|
||||
if (!activeSliderTouch.intent) {
|
||||
if (Math.max(deltaX, deltaY) < SLIDER_TOUCH_INTENT_DISTANCE) {
|
||||
event.stopImmediatePropagation();
|
||||
return;
|
||||
}
|
||||
activeSliderTouch.intent = deltaX > deltaY * SLIDER_HORIZONTAL_INTENT_RATIO ? "horizontal" : "vertical";
|
||||
}
|
||||
|
||||
if (activeSliderTouch.intent === "vertical") {
|
||||
event.stopImmediatePropagation();
|
||||
}
|
||||
},
|
||||
{ capture: true, passive: false },
|
||||
);
|
||||
|
||||
const clearTouch = () => {
|
||||
activeSliderTouch = null;
|
||||
};
|
||||
window.addEventListener("touchend", clearTouch, { capture: true, passive: true });
|
||||
window.addEventListener("touchcancel", clearTouch, { capture: true, passive: true });
|
||||
}
|
||||
|
||||
function bindOrderedSlider(surface) {
|
||||
if (!surface || surface[ORDERED_SLIDER_BOUND_FLAG]) return;
|
||||
|
||||
@@ -582,6 +641,7 @@
|
||||
}
|
||||
|
||||
bindScrollHeightSync();
|
||||
bindSliderTouchGuard();
|
||||
hydrateMediaHandles();
|
||||
bindNotificationStacks();
|
||||
|
||||
@@ -590,6 +650,7 @@
|
||||
"DOMContentLoaded",
|
||||
() => {
|
||||
bindScrollHeightSync();
|
||||
bindSliderTouchGuard();
|
||||
hydrateMediaHandles();
|
||||
bindInteractiveScroll();
|
||||
bindOrderedSliders();
|
||||
@@ -603,6 +664,7 @@
|
||||
);
|
||||
} else {
|
||||
bindScrollHeightSync();
|
||||
bindSliderTouchGuard();
|
||||
hydrateMediaHandles();
|
||||
bindInteractiveScroll();
|
||||
bindOrderedSliders();
|
||||
@@ -615,6 +677,7 @@
|
||||
|
||||
window.addEventListener("load", () => {
|
||||
bindScrollHeightSync();
|
||||
bindSliderTouchGuard();
|
||||
hydrateMediaHandles();
|
||||
bindInteractiveScroll();
|
||||
bindOrderedSliders();
|
||||
|
||||
Reference in New Issue
Block a user