import * as React from "react"; import { View, findNodeHandle } from "react-native"; import { noop } from "@applicaster/zapp-react-native-utils/functionUtils"; import { platformSelect } from "@applicaster/zapp-react-native-utils/reactUtils"; import { MasterCellAsyncRenderManager } from "./MasterCellAsyncRenderManager"; const layoutMeasure = (viewRef, onMeasure) => { viewRef?.measureLayout?.( findNodeHandle(viewRef), (_x, _y, width, height) => { onMeasure({ width, height }); }, noop ); }; const regularMeasure = (viewRef, onMeasure) => { viewRef?.measure?.((_x, _y, width, height) => { onMeasure({ width, height }); }); }; const measure = platformSelect({ android: layoutMeasure, android_tv: layoutMeasure, default: regularMeasure, }); type Dimensions = { width: Option; height: Option; }; type Return = { emitAsyncElementRegistrate: () => void; emitAsyncElementLayout: () => void; onCellLayout: () => void; dimensions: Dimensions; resetDimensions: () => void; }; const initialDimensions = () => ({ width: undefined, height: undefined, }); export const useAsyncRendering = (viewRef: React.RefObject): Return => { const [dimensions, setDimensions] = React.useState(initialDimensions()); const managerRef = React.useRef( new MasterCellAsyncRenderManager(() => { measure(viewRef?.current, ({ width, height }) => { setDimensions({ width, height: Math.ceil(height), }); }); }) ); React.useEffect(() => { return managerRef.current.start(); }, []); const resetDimensions = React.useCallback(() => { setDimensions(initialDimensions()); }, []); return React.useMemo( () => ({ emitAsyncElementRegistrate: managerRef.current?.emitAsyncElementRegistrate, emitAsyncElementLayout: managerRef.current.emitAsyncElementLayout, dimensions, onCellLayout: managerRef.current.onCellLayout, resetDimensions, }), [dimensions, resetDimensions] ); };