UNPKG

@applicaster/zapp-react-native-utils

Version:

Applicaster Zapp React Native utilities package

72 lines (57 loc) 2.38 kB
import { useCallback, useEffect, useMemo, useState } from "react"; import { useScreenTrackedViewPositionsContext } from "@applicaster/zapp-react-native-ui-components/Contexts/ScreenTrackedViewPositionsContext"; import { useDimensions } from "@applicaster/zapp-react-native-utils/reactHooks/layout"; import { findTrackedView } from "./utils/findTrackedView"; import { isNil } from "ramda"; import { withTimeout } from "@applicaster/zapp-react-native-utils/idleUtils"; const TIMEOUT_FOR_DELAY_ON_VIEWPORT_ENTER_EVENT = 500; // ms const getNormalizedRect = (rect, componentId, screenWidth, screenHeight) => { if (!rect) { return null; } const { left, right, top, bottom } = rect; return { left: left / screenWidth, right: right / screenWidth, top: top / screenHeight, bottom: bottom / screenHeight, centerX: (left + right) / 2 / screenWidth, centerY: (top + bottom) / 2 / screenHeight, componentId, }; }; export const useTrackedView = (componentId: string) => { const [inViewPort, setInViewPort] = useState(false); const { updateComponentsPositions } = useScreenTrackedViewPositionsContext(); const { width: screenWidth, height: screenHeight } = useDimensions("screen", { fullDimensions: true, }); const normalizedRect = useCallback( (componentId, rect) => getNormalizedRect(rect, componentId, screenWidth, screenHeight), [screenWidth, screenHeight, componentId] ); const onPositionUpdated = useCallback( async ({ rect }) => { const currentPosition = normalizedRect(componentId, rect); // There is an issue on the native side where they are unable to guarantee // that the order of onViewportLeave and onViewportEnter events is always correct. // This workaround/hack delays the onViewportEnter event to ensure it is received last. if (!isNil(currentPosition)) { await withTimeout(TIMEOUT_FOR_DELAY_ON_VIEWPORT_ENTER_EVENT); } updateComponentsPositions(componentId, currentPosition as any); setInViewPort(!!currentPosition); }, [findTrackedView, normalizedRect, componentId, updateComponentsPositions] ); useEffect(() => { return () => { updateComponentsPositions(componentId, null); }; }, []); return useMemo( () => ({ inViewPort, onPositionUpdated }), [inViewPort, onPositionUpdated] ); };