UNPKG

@applicaster/zapp-react-native-ui-components

Version:

Applicaster Zapp React Native ui components for the Quick Brick App

124 lines (101 loc) 3.82 kB
import { usePickFromState } from "@applicaster/zapp-react-native-redux/hooks"; import { useGetScreenOrientation, isOrientationCompatible, } from "@applicaster/zapp-react-native-utils/appUtils/orientationHelper"; import { useCurrentScreenData, useRoute, useIsTablet, useIsScreenActive, } from "@applicaster/zapp-react-native-utils/reactHooks"; import { useMemo, useEffect, useState } from "react"; import { useSafeAreaFrame } from "react-native-safe-area-context"; type MemoizedSafeAreaFrameWithActiveStateOptions = { updateForInactiveScreens?: boolean; isActive: boolean; }; /** * Base hook that wraps useSafeAreaFrame with memoization and inactive screen filtering. * Requires isActive to be passed explicitly - use useMemoizedSafeAreaFrame for automatic detection. * * @param options.updateForInactiveScreens - If false, frame won't update when screen is inactive (default: true) * @param options.isActive - Whether the screen is currently active * @returns The memoized safe area frame { x, y, width, height } */ export const useMemoizedSafeAreaFrameWithActiveState = ( options: MemoizedSafeAreaFrameWithActiveStateOptions ) => { const { updateForInactiveScreens = true, isActive } = options; const frame = useSafeAreaFrame(); const [memoFrame, setMemoFrame] = useState(frame); useEffect(() => { const shouldUpdate = isActive || updateForInactiveScreens; const dimensionsChanged = frame.width !== memoFrame.width || frame.height !== memoFrame.height; if (shouldUpdate && dimensionsChanged) { setMemoFrame(frame); } }, [ frame.width, frame.height, isActive, updateForInactiveScreens, frame, memoFrame.width, memoFrame.height, ]); return memoFrame; }; type MemoizedSafeAreaFrameOptions = { updateForInactiveScreens?: boolean; }; /** * Hook that wraps useSafeAreaFrame with memoization and inactive screen filtering. * Uses useIsScreenActive() internally to determine active state - use useMemoizedSafeAreaFrameWithActiveState * if you need to pass isActive explicitly. * * @param options.updateForInactiveScreens - If false, frame won't update when screen is inactive (default: true) * @returns The memoized safe area frame { x, y, width, height } */ export const useMemoizedSafeAreaFrame = ( options: MemoizedSafeAreaFrameOptions = {} ) => { const { updateForInactiveScreens = true } = options; const isActive = useIsScreenActive(); return useMemoizedSafeAreaFrameWithActiveState({ updateForInactiveScreens, isActive, }); }; export const useWaitForValidOrientation = () => { // Use memoized safe area frame to synchronize with Scene's dimension source // This prevents race conditions where the orientation check passes before // Scene's memoFrame has updated to the new dimensions const { width: screenWidth, height } = useMemoizedSafeAreaFrame({ updateForInactiveScreens: false, }); const currentScreenData = useCurrentScreenData(); const { screenData } = useRoute(); const [readyState, setReadyState] = useState(false); const isTablet = useIsTablet(); const { appData } = usePickFromState(["appData"]); const isTabletPortrait = appData?.isTabletPortrait; const layoutData = useMemo( () => ({ isTablet, isTabletPortrait, width: screenWidth, height }), [isTablet, isTabletPortrait, screenWidth, height] ); const targetScreenData = currentScreenData || (screenData as any)?.targetScreen || screenData; const orientation = useGetScreenOrientation(targetScreenData); const isReadyForDisplay = isOrientationCompatible({ orientation, layoutData, }); useEffect(() => { if (isReadyForDisplay && !readyState) { setReadyState(true); } }, [readyState, orientation, layoutData]); return readyState; };