import { useCallback, useEffect, useRef, useState } from 'react'; import { View, Dimensions } from 'react-native'; const { height: SCREEN_HEIGHT, width: SCREEN_WIDTH } = Dimensions.get('window'); export function useSharedVisibility(threshold: number, dwellTime: number) { const [isVisible, setIsVisible] = useState(false); const [shouldPlay, setShouldPlay] = useState(false); const ref = useRef(null); const timerRef = useRef(undefined); const visibilityCheckRef = useRef(undefined); const isMountedRef = useRef(true); const checkVisibility = useCallback(() => { if (!ref.current || !isMountedRef.current) return; ref.current.measureInWindow((x, y, width, height) => { if (!isMountedRef.current) return; const isInViewport = y + height * threshold >= 0 && y <= SCREEN_HEIGHT - height * threshold && x + width * threshold >= 0 && x <= SCREEN_WIDTH; setIsVisible((prev) => { if (prev === isInViewport) return prev; if (isInViewport) { if (timerRef.current) clearTimeout(timerRef.current); timerRef.current = setTimeout(() => { if (isMountedRef.current) { setShouldPlay(true); } }, dwellTime); } else { if (timerRef.current) clearTimeout(timerRef.current); setShouldPlay(false); } return isInViewport; }); }); }, [threshold, dwellTime]); useEffect(() => { isMountedRef.current = true; checkVisibility(); visibilityCheckRef.current = setInterval(checkVisibility, 1000); return () => { isMountedRef.current = false; if (timerRef.current) clearTimeout(timerRef.current); if (visibilityCheckRef.current) clearInterval(visibilityCheckRef.current); }; }, [checkVisibility]); return { ref, isVisible, shouldPlay }; }