mirror of https://git.lenooby09.tech/LeNooby09/social-app.git
at offline-detection 151 lines 4.6 kB view raw
1import * as React from 'react' 2import {View} from 'react-native' 3import {PWI_ENABLED} from '#/lib/build-flags' 4 5// Based on @react-navigation/native-stack/src/createNativeStackNavigator.ts 6// MIT License 7// Copyright (c) 2017 React Navigation Contributors 8 9import { 10 createNavigatorFactory, 11 EventArg, 12 ParamListBase, 13 StackActionHelpers, 14 StackActions, 15 StackNavigationState, 16 StackRouter, 17 StackRouterOptions, 18 useNavigationBuilder, 19} from '@react-navigation/native' 20import type { 21 NativeStackNavigationEventMap, 22 NativeStackNavigationOptions, 23} from '@react-navigation/native-stack' 24import type {NativeStackNavigatorProps} from '@react-navigation/native-stack/src/types' 25import {NativeStackView} from '@react-navigation/native-stack' 26 27import {BottomBarWeb} from './bottom-bar/BottomBarWeb' 28import {DesktopLeftNav} from './desktop/LeftNav' 29import {DesktopRightNav} from './desktop/RightNav' 30import {useWebMediaQueries} from '#/lib/hooks/useWebMediaQueries' 31import {useOnboardingState} from '#/state/shell' 32import { 33 useLoggedOutView, 34 useLoggedOutViewControls, 35} from '#/state/shell/logged-out' 36import {useSession} from '#/state/session' 37import {isWeb} from 'platform/detection' 38import {LoggedOut} from '../com/auth/LoggedOut' 39import {Onboarding} from '../com/auth/Onboarding' 40 41type NativeStackNavigationOptionsWithAuth = NativeStackNavigationOptions & { 42 requireAuth?: boolean 43} 44 45function NativeStackNavigator({ 46 id, 47 initialRouteName, 48 children, 49 screenListeners, 50 screenOptions, 51 ...rest 52}: NativeStackNavigatorProps) { 53 // --- this is copy and pasted from the original native stack navigator --- 54 const {state, descriptors, navigation, NavigationContent} = 55 useNavigationBuilder< 56 StackNavigationState<ParamListBase>, 57 StackRouterOptions, 58 StackActionHelpers<ParamListBase>, 59 NativeStackNavigationOptionsWithAuth, 60 NativeStackNavigationEventMap 61 >(StackRouter, { 62 id, 63 initialRouteName, 64 children, 65 screenListeners, 66 screenOptions, 67 }) 68 React.useEffect( 69 () => 70 // @ts-expect-error: there may not be a tab navigator in parent 71 navigation?.addListener?.('tabPress', (e: any) => { 72 const isFocused = navigation.isFocused() 73 74 // Run the operation in the next frame so we're sure all listeners have been run 75 // This is necessary to know if preventDefault() has been called 76 requestAnimationFrame(() => { 77 if ( 78 state.index > 0 && 79 isFocused && 80 !(e as EventArg<'tabPress', true>).defaultPrevented 81 ) { 82 // When user taps on already focused tab and we're inside the tab, 83 // reset the stack to replicate native behaviour 84 navigation.dispatch({ 85 ...StackActions.popToTop(), 86 target: state.key, 87 }) 88 } 89 }) 90 }), 91 [navigation, state.index, state.key], 92 ) 93 94 // --- our custom logic starts here --- 95 const {hasSession} = useSession() 96 const activeRoute = state.routes[state.index] 97 const activeDescriptor = descriptors[activeRoute.key] 98 const activeRouteRequiresAuth = activeDescriptor.options.requireAuth ?? false 99 const onboardingState = useOnboardingState() 100 const {showLoggedOut} = useLoggedOutView() 101 const {setShowLoggedOut} = useLoggedOutViewControls() 102 const {isMobile} = useWebMediaQueries() 103 if ((!PWI_ENABLED || activeRouteRequiresAuth) && !hasSession) { 104 return <LoggedOut /> 105 } 106 if (showLoggedOut) { 107 return <LoggedOut onDismiss={() => setShowLoggedOut(false)} /> 108 } 109 if (onboardingState.isActive) { 110 return <Onboarding /> 111 } 112 const newDescriptors: typeof descriptors = {} 113 for (let key in descriptors) { 114 const descriptor = descriptors[key] 115 const requireAuth = descriptor.options.requireAuth ?? false 116 newDescriptors[key] = { 117 ...descriptor, 118 render() { 119 if (requireAuth && !hasSession) { 120 return <View /> 121 } else { 122 return descriptor.render() 123 } 124 }, 125 } 126 } 127 return ( 128 <NavigationContent> 129 <NativeStackView 130 {...rest} 131 state={state} 132 navigation={navigation} 133 descriptors={newDescriptors} 134 /> 135 {isWeb && isMobile && <BottomBarWeb />} 136 {isWeb && !isMobile && ( 137 <> 138 <DesktopLeftNav /> 139 <DesktopRightNav /> 140 </> 141 )} 142 </NavigationContent> 143 ) 144} 145 146export const createNativeStackNavigatorWithAuth = createNavigatorFactory< 147 StackNavigationState<ParamListBase>, 148 NativeStackNavigationOptionsWithAuth, 149 NativeStackNavigationEventMap, 150 typeof NativeStackNavigator 151>(NativeStackNavigator)