import {useRef, useCallback, useEffect} from 'react'; import type {Dispatch, SetStateAction} from 'react'; interface ControlTimeoutProps { controlTimeoutDelay: number; mounted: boolean; showControls: boolean; setShowControls: Dispatch>; alwaysShowControls: boolean; } export const useControlTimeout = ({ controlTimeoutDelay, mounted, showControls, setShowControls, alwaysShowControls, }: ControlTimeoutProps) => { // Use refs to avoid re‑renders when these change const timerRef = useRef | null>(null); const latest = useRef({ mounted, showControls, alwaysShowControls, setShowControls, }); // Keep the latest values fresh without forcing re‑renders latest.current.mounted = mounted; latest.current.showControls = showControls; latest.current.alwaysShowControls = alwaysShowControls; latest.current.setShowControls = setShowControls; const clearControlTimeout = useCallback(() => { if (timerRef.current) { clearTimeout(timerRef.current); timerRef.current = null; } }, []); const hideControls = useCallback(() => { const {mounted, showControls, alwaysShowControls, setShowControls} = latest.current; if (mounted && showControls && !alwaysShowControls) { setShowControls(false); } }, []); const setControlTimeout = useCallback(() => { clearControlTimeout(); timerRef.current = setTimeout(() => { hideControls(); }, controlTimeoutDelay); }, [clearControlTimeout, controlTimeoutDelay, hideControls]); const resetControlTimeout = useCallback(() => { clearControlTimeout(); // Optionally restart the timer after reset? Usually we just clear. }, [clearControlTimeout]); // Cleanup on unmount useEffect(() => { return () => { clearControlTimeout(); }; }, [clearControlTimeout]); return { clearControlTimeout, resetControlTimeout, hideControls, setControlTimeout, }; };