import { SafeAreaProviderCompat } from '@react-navigation/elements'; import { ParamListBase, Route, StackActions, StackNavigationState, useTheme, } from '@react-navigation/native'; import * as React from 'react'; import { Platform, StyleSheet } from 'react-native'; import { Screen, ScreenStack, StackPresentationTypes, } from 'react-native-screens'; import warnOnce from 'warn-once'; import type { NativeStackDescriptorMap, NativeStackNavigationHelpers, NativeStackNavigationOptions, } from '../types'; import DebugContainer from './DebugContainer'; import HeaderConfig from './HeaderConfig'; const isAndroid = Platform.OS === 'android'; const MaybeNestedStack = ({ options, route, presentation, children, }: { options: NativeStackNavigationOptions; route: Route; presentation: Exclude | 'card'; children: React.ReactNode; }) => { const { colors } = useTheme(); const { headerShown = true, contentStyle } = options; const isHeaderInModal = isAndroid ? false : presentation !== 'card' && headerShown === true; const headerShownPreviousRef = React.useRef(headerShown); React.useEffect(() => { warnOnce( !isAndroid && presentation !== 'card' && headerShownPreviousRef.current !== headerShown, `Dynamically changing 'headerShown' in modals will result in remounting the screen and losing all local state. See options for the screen '${route.name}'.` ); headerShownPreviousRef.current = headerShown; }, [headerShown, presentation, route.name]); const content = ( {children} ); if (isHeaderInModal) { return ( {content} ); } return content; }; type Props = { state: StackNavigationState; navigation: NativeStackNavigationHelpers; descriptors: NativeStackDescriptorMap; }; function NativeStackViewInner({ state, navigation, descriptors }: Props) { return ( {state.routes.map((route, index) => { const { options, render: renderScene } = descriptors[route.key]; const { gestureEnabled, headerShown, animationTypeForReplace = 'pop', animation, orientation, statusBarAnimation, statusBarHidden, statusBarStyle, } = options; let { presentation = 'card' } = options; if (index === 0) { // first screen should always be treated as `card`, it resolves problems with no header animation // for navigator with first screen as `modal` and the next as `card` presentation = 'card'; } const isHeaderInPush = isAndroid ? headerShown : presentation === 'card' && headerShown !== false; return ( { navigation.emit({ type: 'transitionStart', data: { closing: false }, target: route.key, }); }} onWillDisappear={() => { navigation.emit({ type: 'transitionStart', data: { closing: true }, target: route.key, }); }} onAppear={() => { navigation.emit({ type: 'transitionEnd', data: { closing: false }, target: route.key, }); }} onDisappear={() => { navigation.emit({ type: 'transitionEnd', data: { closing: true }, target: route.key, }); }} onDismissed={() => { navigation.dispatch({ ...StackActions.pop(), source: route.key, target: state.key, }); }} > {renderScene()} ); })} ); } export default function NativeStackView(props: Props) { return ( ); } const styles = StyleSheet.create({ container: { flex: 1, }, });