Extra scrolling logic to handle long tail of scroll events (#208341)

* special scrolling logic

* longer comment
This commit is contained in:
Aaron Munger 2024-03-22 07:34:29 -07:00 committed by GitHub
parent 7a8b6a8dd0
commit e67961480f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -521,13 +521,49 @@ async function webviewPreloads(ctx: PreloadContext) {
}
};
let previousDelta: number | undefined;
let scrollTimeout: any /* NodeJS.Timeout */ | undefined;
let scrolledElement: Element | undefined;
function flagRecentlyScrolled(node: Element) {
let lastTimeScrolled: number | undefined;
function flagRecentlyScrolled(node: Element, deltaY?: number) {
scrolledElement = node;
node.setAttribute('recentlyScrolled', 'true');
clearTimeout(scrollTimeout);
scrollTimeout = setTimeout(() => { scrolledElement?.removeAttribute('recentlyScrolled'); }, 300);
if (!deltaY) {
lastTimeScrolled = Date.now();
previousDelta = undefined;
node.setAttribute('recentlyScrolled', 'true');
clearTimeout(scrollTimeout);
scrollTimeout = setTimeout(() => { scrolledElement?.removeAttribute('recentlyScrolled'); }, 300);
return true;
}
if (node.hasAttribute('recentlyScrolled')) {
if (lastTimeScrolled && Date.now() - lastTimeScrolled > 300) {
// it has been a while since we actually scrolled
// if scroll velocity increases, it's likely a new scroll event
if (!!previousDelta && deltaY < 0 && deltaY < previousDelta - 2) {
clearTimeout(scrollTimeout);
scrolledElement?.removeAttribute('recentlyScrolled');
return false;
} else if (!!previousDelta && deltaY > 0 && deltaY > previousDelta + 2) {
clearTimeout(scrollTimeout);
scrolledElement?.removeAttribute('recentlyScrolled');
return false;
}
// the tail end of a smooth scrolling event (from a trackpad) can go on for a while
// so keep swallowing it, but we can shorten the timeout since the events occur rapidly
clearTimeout(scrollTimeout);
scrollTimeout = setTimeout(() => { scrolledElement?.removeAttribute('recentlyScrolled'); }, 50);
} else {
clearTimeout(scrollTimeout);
scrollTimeout = setTimeout(() => { scrolledElement?.removeAttribute('recentlyScrolled'); }, 300);
}
previousDelta = deltaY;
return true;
}
return false;
}
function eventTargetShouldHandleScroll(event: WheelEvent) {
@ -536,11 +572,6 @@ async function webviewPreloads(ctx: PreloadContext) {
return false;
}
if (node.hasAttribute('recentlyScrolled') && scrolledElement === node) {
flagRecentlyScrolled(node);
return true;
}
// scroll up
if (event.deltaY < 0 && node.scrollTop > 0) {
// there is still some content to scroll
@ -565,6 +596,10 @@ async function webviewPreloads(ctx: PreloadContext) {
flagRecentlyScrolled(node);
return true;
}
if (flagRecentlyScrolled(node, event.deltaY)) {
return true;
}
}
return false;