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. */
|
/** Ignore duplicate events (mousemove etc.) within this window. */
|
||||||
const ACTIVITY_THROTTLE_MS = 400;
|
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.
|
* After idle on /, /aktionen, or /filiale, cycles those routes slowly.
|
||||||
* Lives outside MainPageLayout so it is not reset when the route changes.
|
* 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 pathRef = useRef(location.pathname);
|
||||||
const wasOnMainPageRef = useRef(false);
|
const wasOnMainPageRef = useRef(false);
|
||||||
const lastActivityRef = useRef(0);
|
const lastActivityRef = useRef(0);
|
||||||
|
const ignoreActivityUntilRef = useRef(0);
|
||||||
|
|
||||||
|
const resetIdleRef = useRef(() => {});
|
||||||
|
const clearTimersRef = useRef(() => {});
|
||||||
|
|
||||||
pathRef.current = location.pathname;
|
pathRef.current = location.pathname;
|
||||||
|
|
||||||
@@ -39,11 +50,14 @@ export default function IdleMainPagesSlideshow() {
|
|||||||
}
|
}
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
clearTimersRef.current = clearTimers;
|
||||||
|
|
||||||
const startSlideshow = useCallback(() => {
|
const startSlideshow = useCallback(() => {
|
||||||
let idx = MAIN_PAGE_PATHS.indexOf(pathRef.current);
|
let idx = MAIN_PAGE_PATHS.indexOf(pathRef.current);
|
||||||
if (idx < 0) idx = 0;
|
if (idx < 0) idx = 0;
|
||||||
const advance = () => {
|
const advance = () => {
|
||||||
idx = (idx + 1) % MAIN_PAGE_PATHS.length;
|
idx = (idx + 1) % MAIN_PAGE_PATHS.length;
|
||||||
|
ignoreActivityUntilRef.current = Date.now() + POST_NAV_GRACE_MS;
|
||||||
navigate(MAIN_PAGE_PATHS[idx], { replace: true });
|
navigate(MAIN_PAGE_PATHS[idx], { replace: true });
|
||||||
};
|
};
|
||||||
slideTimerRef.current = setInterval(advance, SLIDESHOW_STEP_MS);
|
slideTimerRef.current = setInterval(advance, SLIDESHOW_STEP_MS);
|
||||||
@@ -58,6 +72,8 @@ export default function IdleMainPagesSlideshow() {
|
|||||||
}, IDLE_MS);
|
}, IDLE_MS);
|
||||||
}, [clearTimers, startSlideshow]);
|
}, [clearTimers, startSlideshow]);
|
||||||
|
|
||||||
|
resetIdleRef.current = resetIdle;
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const nowMain = MAIN_PAGE_PATHS.includes(location.pathname);
|
const nowMain = MAIN_PAGE_PATHS.includes(location.pathname);
|
||||||
if (!nowMain) {
|
if (!nowMain) {
|
||||||
@@ -73,10 +89,11 @@ export default function IdleMainPagesSlideshow() {
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const onActivity = () => {
|
const onActivity = () => {
|
||||||
const t = Date.now();
|
const now = Date.now();
|
||||||
if (t - lastActivityRef.current < ACTIVITY_THROTTLE_MS) return;
|
if (now < ignoreActivityUntilRef.current) return;
|
||||||
lastActivityRef.current = t;
|
if (now - lastActivityRef.current < ACTIVITY_THROTTLE_MS) return;
|
||||||
resetIdle();
|
lastActivityRef.current = now;
|
||||||
|
resetIdleRef.current();
|
||||||
};
|
};
|
||||||
|
|
||||||
const events = [
|
const events = [
|
||||||
@@ -96,9 +113,9 @@ export default function IdleMainPagesSlideshow() {
|
|||||||
return () => {
|
return () => {
|
||||||
events.forEach((ev) => window.removeEventListener(ev, onActivity));
|
events.forEach((ev) => window.removeEventListener(ev, onActivity));
|
||||||
window.removeEventListener("mousemove", onActivity);
|
window.removeEventListener("mousemove", onActivity);
|
||||||
clearTimers();
|
clearTimersRef.current();
|
||||||
};
|
};
|
||||||
}, [resetIdle, clearTimers]);
|
}, []);
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user