feat: Add grace period for user activity handling in IdleMainPagesSlideshow to prevent premature slideshow reset after navigation
This commit is contained in:
@@ -13,6 +13,13 @@ const SLIDESHOW_STEP_MS = 14_000;
|
||||
/** Ignore duplicate events (mousemove etc.) within this window. */
|
||||
const ACTIVITY_THROTTLE_MS = 400;
|
||||
|
||||
/**
|
||||
* After auto-navigation, ignore user-activity handlers briefly — route changes
|
||||
* often emit scroll / mousemove / focus events that would call resetIdle() and
|
||||
* clear the slideshow interval (only one slide before stopping).
|
||||
*/
|
||||
const POST_NAV_GRACE_MS = 3_000;
|
||||
|
||||
/**
|
||||
* After idle on /, /aktionen, or /filiale, cycles those routes slowly.
|
||||
* Lives outside MainPageLayout so it is not reset when the route changes.
|
||||
@@ -25,6 +32,10 @@ export default function IdleMainPagesSlideshow() {
|
||||
const pathRef = useRef(location.pathname);
|
||||
const wasOnMainPageRef = useRef(false);
|
||||
const lastActivityRef = useRef(0);
|
||||
const ignoreActivityUntilRef = useRef(0);
|
||||
|
||||
const resetIdleRef = useRef(() => {});
|
||||
const clearTimersRef = useRef(() => {});
|
||||
|
||||
pathRef.current = location.pathname;
|
||||
|
||||
@@ -39,11 +50,14 @@ export default function IdleMainPagesSlideshow() {
|
||||
}
|
||||
}, []);
|
||||
|
||||
clearTimersRef.current = clearTimers;
|
||||
|
||||
const startSlideshow = useCallback(() => {
|
||||
let idx = MAIN_PAGE_PATHS.indexOf(pathRef.current);
|
||||
if (idx < 0) idx = 0;
|
||||
const advance = () => {
|
||||
idx = (idx + 1) % MAIN_PAGE_PATHS.length;
|
||||
ignoreActivityUntilRef.current = Date.now() + POST_NAV_GRACE_MS;
|
||||
navigate(MAIN_PAGE_PATHS[idx], { replace: true });
|
||||
};
|
||||
slideTimerRef.current = setInterval(advance, SLIDESHOW_STEP_MS);
|
||||
@@ -58,6 +72,8 @@ export default function IdleMainPagesSlideshow() {
|
||||
}, IDLE_MS);
|
||||
}, [clearTimers, startSlideshow]);
|
||||
|
||||
resetIdleRef.current = resetIdle;
|
||||
|
||||
useEffect(() => {
|
||||
const nowMain = MAIN_PAGE_PATHS.includes(location.pathname);
|
||||
if (!nowMain) {
|
||||
@@ -73,10 +89,11 @@ export default function IdleMainPagesSlideshow() {
|
||||
|
||||
useEffect(() => {
|
||||
const onActivity = () => {
|
||||
const t = Date.now();
|
||||
if (t - lastActivityRef.current < ACTIVITY_THROTTLE_MS) return;
|
||||
lastActivityRef.current = t;
|
||||
resetIdle();
|
||||
const now = Date.now();
|
||||
if (now < ignoreActivityUntilRef.current) return;
|
||||
if (now - lastActivityRef.current < ACTIVITY_THROTTLE_MS) return;
|
||||
lastActivityRef.current = now;
|
||||
resetIdleRef.current();
|
||||
};
|
||||
|
||||
const events = [
|
||||
@@ -96,9 +113,9 @@ export default function IdleMainPagesSlideshow() {
|
||||
return () => {
|
||||
events.forEach((ev) => window.removeEventListener(ev, onActivity));
|
||||
window.removeEventListener("mousemove", onActivity);
|
||||
clearTimers();
|
||||
clearTimersRef.current();
|
||||
};
|
||||
}, [resetIdle, clearTimers]);
|
||||
}, []);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user