import Constants from './constants' import React, { Fragment, useMemo, type FunctionComponent, type ReactNode } from 'react' import { Platform } from 'react-native' // import { GestureHandlerRootView as _GestureHandlerRootView } from 'react-native-gesture-handler' import { SafeAreaProvider } from 'react-native-safe-area-context' import type { NavigationAction, NavigationContainerProps } from '@react-navigation/native' import UpstreamNavigationContainer from './fork/NavigationContainer' import { useInitializeExpoRouter } from './global-state/useInitializeExpoRouter' import { ServerLocationContext } from './global-state/serverLocationContext' import { Head, HeadProvider } from './head' import type { RequireContext } from './types' import { SplashScreen } from './views/Splash' export type ExpoRootProps = { context: RequireContext location?: URL wrapper?: FunctionComponent<{ children: ReactNode }> navigationContainerProps?: NavigationContainerProps & { theme?: { dark: boolean colors: { primary: string background: string card: string text: string border: string notification: string } } } } // function getGestureHandlerRootView() { // try { // if (!_GestureHandlerRootView) { // return React.Fragment // } // // eslint-disable-next-line no-inner-declarations // function GestureHandler(props: any) { // return <_GestureHandlerRootView style={{ flex: 1 }} {...props} /> // } // if (process.env.NODE_ENV === 'development') { // // @ts-expect-error // GestureHandler.displayName = 'GestureHandlerRootView' // } // return GestureHandler // } catch { // return React.Fragment // } // } // const GestureHandlerRootView = getGestureHandlerRootView() const INITIAL_METRICS = { frame: { x: 0, y: 0, width: 0, height: 0 }, insets: { top: 0, left: 0, right: 0, bottom: 0 }, } const hasViewControllerBasedStatusBarAppearance = Platform.OS === 'ios' && !!Constants.expoConfig?.ios?.infoPlist?.UIViewControllerBasedStatusBarAppearance export function ExpoRoot({ wrapper = Fragment, navigationContainerProps, ...props }: ExpoRootProps) { return ( ) } const initialUrl = Platform.OS === 'web' && typeof window !== 'undefined' ? new URL(window.location.href) : undefined function ContextNavigator({ wrapper: ParentWrapper = Fragment, context, location: initialLocation = initialUrl, navigationContainerProps, }: ExpoRootProps) { const store = useInitializeExpoRouter(context, initialLocation) const headContext = useMemo(() => globalThis['vxrn__headContext__'] || {}, []) /* * Due to static rendering we need to wrap these top level views in second wrapper * View's like generate a
so if the parent wrapper * is a HTML document, we need to ensure its inside the */ const wrapper = (children: any) => { return ( {/* */} {children} {/* Users can override this by adding another StatusBar element anywhere higher in the component tree. */} {/* {!hasViewControllerBasedStatusBarAppearance && } */} {/* */} ) } if (store.shouldShowTutorial()) { SplashScreen.hideAsync() if (process.env.NODE_ENV === 'development') { return wrapper( <> {/* TODO */} {/* */} ) } // Ensure tutorial styles are stripped in production. return null } const Component = store.rootComponent if (!Component) { throw new Error(`No root component found`) } return ( {wrapper()} ) } let onUnhandledAction: (action: NavigationAction) => void if (process.env.NODE_ENV !== 'production') { onUnhandledAction = (action: NavigationAction) => { const payload: Record | undefined = action.payload let message = `The action '${action.type}'${ payload ? ` with payload ${JSON.stringify(action.payload)}` : '' } was not handled by any navigator.` switch (action.type) { case 'NAVIGATE': case 'PUSH': case 'REPLACE': case 'JUMP_TO': if (payload?.name) { message += `\n\nDo you have a route named '${payload.name}'?` } else { message += `\n\nYou need to pass the name of the screen to navigate to. This may be a bug.` } break case 'GO_BACK': case 'POP': case 'POP_TO_TOP': message += `\n\nIs there any screen to go back to?` break case 'OPEN_DRAWER': case 'CLOSE_DRAWER': case 'TOGGLE_DRAWER': message += `\n\nIs your screen inside a Drawer navigator?` break } message += `\n\nThis is a development-only warning and won't be shown in production.` if (process.env.NODE_ENV === 'test') { throw new Error(message) } console.error(message) } } else { onUnhandledAction = () => {} }