import inRange from "lodash/inRange"; import React, { useCallback, useEffect, useRef } from "react"; import type { LayoutChangeEvent, ViewStyle } from "react-native"; import { ActivityIndicator, Platform, StyleSheet, View } from "react-native"; import shallow from "zustand/shallow"; import { loadingStyleSheet } from "./loading"; import { AreEqualProvider, ResponsiveProvider } from "./providers"; import type { ResponsiveStore } from "./store"; import { createScreenResponsiveStore } from "./store"; import type { EqualityFunctionStore } from "../library"; import { createEqualityFunctionStore, round, Else, Fallback, If, Then} from "../library"; import { onViewSizeChangeEvent } from "../library/event/bus"; import { ResponsiveStore as ResponsivePrivateStore } from "../responsive"; import type { equalityFunctionStore, ResponsiveState, ScreenUtilDesignSize } from "../type"; import { equalityFunctionEnum, OrientationType } from "../type"; type responsiveContainerStyle2 = { rootView: ViewStyle; }; const rootViewStyle = StyleSheet.create({ rootView: { flexGrow: 1 } }); export interface ScreenResponsiveProvider { option: ScreenUtilDesignSize; loading: boolean; autoInset: boolean; } type ScreenResponsiveProviderProps = React.PropsWithChildren; export function ScreenResponsiveProvider({ children, option, loading, autoInset }: ScreenResponsiveProviderProps): JSX.Element { const areEqualRef = useRef<[Function, equalityFunctionEnum]>([shallow, equalityFunctionEnum.shallow]); const rootViewRef = useRef(null); const storeRef = useRef(); const areEqualStoreRef = useRef(); if (!storeRef.current) { storeRef.current = createScreenResponsiveStore(); } if (!areEqualStoreRef.current) { areEqualStoreRef.current = createEqualityFunctionStore(); } if (!option.equality) { option.equality = equalityFunctionEnum.shallow; } useEffect(() => { let unSubcribeResponsive: () => void; let unSubcribeAreEqual: () => void; onViewSizeChangeEvent.on("onChangeInsideEvent", () => { const view = rootViewRef.current; if (!view) { return; } if (autoInset && Platform.OS === "ios") { const orientation = ResponsivePrivateStore.getAction().getOrientation(); if (orientation === OrientationType.POTTRAIT) { view.setNativeProps({ top: ResponsivePrivateStore._____getInset(orientation) }); } if (orientation === OrientationType.LANDSCAPE) { view.setNativeProps({ left: ResponsivePrivateStore._____getInset(orientation) }); } } }); const responsiveRefCurrent = storeRef.current; const areEqualRefCurrent = areEqualStoreRef.current; if (!responsiveRefCurrent) { return; } if (!areEqualRefCurrent) { return; } responsiveRefCurrent .getState() .setScreenResponsiveInitialize(option) .then((v) => { if (v.error) { return; } unSubcribeResponsive = responsiveRefCurrent.subscribe( (state: ResponsiveState) => state, (next, _prev) => { ResponsivePrivateStore.getAction().copyData(next); }, { equalityFn: (a, b) => areEqualRef.current[0](a, b), fireImmediately: true } ); unSubcribeAreEqual = areEqualRefCurrent.subscribe( (state: equalityFunctionStore) => state, (next, _prev) => { if (next.type === areEqualRef.current[1]) { return; } areEqualRef.current = [next.areEqual, next.type]; }, { equalityFn: (a, b) => areEqualRef.current[0](a, b) } ); }); return () => { unSubcribeResponsive(); unSubcribeAreEqual(); onViewSizeChangeEvent.removeAllListeners("onChangeInsideEvent"); }; }, []); useEffect(() => { ResponsivePrivateStore.getAction() .getInitialize() .then(() => { onViewSizeChangeEvent.emit("onChangeInsideEvent"); }); }, []); const getSize = useCallback((event: LayoutChangeEvent) => { if (!storeRef.current) { return; } if (inRange(event.nativeEvent.layout.height, 0, 100)) { return; } const width = round(event.nativeEvent.layout.width); const height = round(event.nativeEvent.layout.height); storeRef.current.getState().setScreenReScreeenSizeRatio(width, height); }, []); return ( { // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore } {(): any => children} {children} ); }