"use client"; import { useState, useEffect, useCallback, useRef, RefObject } from "react"; export function useIdle( timeoutMs: number, videoRef: RefObject, onIdle?: () => void, ) { const [showOverlays, setShowOverlays] = useState(true); const [needsInteraction, setNeedsInteraction] = useState(false); const idleTimer = useRef | null>(null); // Keep onIdle in a ref so resetIdle doesn't need it as a dep const onIdleRef = useRef(onIdle); useEffect(() => { onIdleRef.current = onIdle; }); const resetIdle = useCallback(() => { setShowOverlays(true); setNeedsInteraction(false); if (idleTimer.current) clearTimeout(idleTimer.current); idleTimer.current = setTimeout(() => { setShowOverlays(false); onIdleRef.current?.(); }, timeoutMs); videoRef.current?.play().catch(() => {}); }, [timeoutMs, videoRef]); // Start the idle timer on mount without calling setState // (default state values already set by useState above) useEffect(() => { idleTimer.current = setTimeout(() => { setShowOverlays(false); onIdleRef.current?.(); }, timeoutMs); return () => { if (idleTimer.current) clearTimeout(idleTimer.current); }; // eslint-disable-next-line react-hooks/exhaustive-deps }, []); return { showOverlays, needsInteraction, setNeedsInteraction, resetIdle }; }