expo-popcore-old/components/sker/video-player/useSharedVisibility.native.ts

61 lines
1.9 KiB
TypeScript

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<View>(null);
const timerRef = useRef<number | undefined>(undefined);
const visibilityCheckRef = useRef<number | undefined>(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 };
}