Fix scroll-triggered loading permanently stopping after one round

onScroll() throttled via requestAnimationFrame with a guard
(_scrollRaf) reset from *inside* the rAF callback -- if that callback
ever failed to fire (reproduced via a backgrounded/non-visible tab,
where browsers routinely throttle or suspend rAF), the guard stayed
true forever, silently dropping every future scroll event. Matches
exactly what was reported: the window extends once when scrolling
toward the past, then stops responding to scrolling at all.

detectCurrentYear()/checkEdges() are cheap (DOM reads + early-return
guards, do no real work themselves), so there's nothing worth
throttling here -- removed the rAF entirely and call both directly on
every scroll event. Verified live: repeated scroll-to-top no longer
gets stuck after the first extension, keeps loading older months
across many rounds.
This commit is contained in:
2026-09-05 21:39:47 +02:00
parent 0c9f8ca41f
commit 0479f3fbbb
@@ -1013,13 +1013,19 @@
this.loadCurrentYearTotals(); this.loadCurrentYearTotals();
} }
}, },
// No requestAnimationFrame throttle here anymore -- it used a
// "skip if a frame is already pending" guard reset from *inside*
// the rAF callback, which meant a single rAF callback that never
// fires (observed: a backgrounded/non-visible tab, where browsers
// routinely throttle or fully suspend rAF) permanently wedges the
// guard true, silently dropping every future scroll event forever
// -- exactly the "loads once then stops, can't scroll back" bug
// this replaces. detectCurrentYear()/checkEdges() are cheap (DOM
// reads + early-return guards, no work of their own), so calling
// them on every scroll event costs nothing worth throttling for.
onScroll() { onScroll() {
if (this._scrollRaf) return; this.detectCurrentYear();
this._scrollRaf = requestAnimationFrame(() => { this.checkEdges();
this._scrollRaf = null;
this.detectCurrentYear();
this.checkEdges();
});
}, },
// mounted() only runs once, but `v-if="loading"` swaps out the // mounted() only runs once, but `v-if="loading"` swaps out the
// <div ref="tableWrap"> for a fresh DOM node every time loading // <div ref="tableWrap"> for a fresh DOM node every time loading