import { NavigationContainer , NavigationContainerRef , } from "@react-navigation/native" ; import * as Linking from "expo-linking" ; import React from "react" ; import { ErrorBoundary , FallbackProps } from "react-error-boundary" ; import { Clipboard , SafeAreaView , ScrollView } from "react-native" ; import { useQuery } from "react-query" ; import { useTheme } from "./hooks/useTheme" ; import { AuthStack } from "./modules/AuthStack" ; import { MainTabStack } from "./modules/MainTabStack" ; import { useShowTabs } from "./modules/MainTabStack/useShowTabs" ; import { MeResponse } from "./types" ; import { FullscreenLoading } from "./ui/FullscreenLoading" ; import { MyButton } from "./ui/MyButton" ; import { MyHeader } from "./ui/MyHeader" ; import { MyText } from "./ui/MyText" ; import { ScreenWrapper } from "./ui/ScreenWrapper" ; import { ReactQueryErrorResetBoundary } from "react-query" ; import { ProfileStack } from "./modules/ProfileStack" ; import * as Sentry from "sentry-expo" ; const prefix = Linking . makeUrl ( "/" ) ; interface RoutesProps { } const linking = { prefixes : [ prefix ] , config : { screens : { tokens : "tokens/:accessToken/:refreshToken" } } } ; function ErrorFallback ( { resetErrorBoundary , error } ) { return ( < ScreenWrapper > < ScrollView > < MyHeader > App Crashed : < /MyHeader> < MyText style = { { marginVertical : 40 , fontSize : 16 } } > { error ?. message } < /MyText> < MyButton style = { { marginBottom : 20 } } secondary onPress = { ( ) => Clipboard . setString ( error ?. stack || "" ) } > copy stacktrace to clipboard < /MyButton> < MyButton onPress = { resetErrorBoundary } > reload app < /MyButton> < /ScrollView> < /ScreenWrapper>); } const myErrorHandler = ( error ) => { Sentry . Native . captureException ( error ) ; } ; export const Routes = ( { } ) => { const { editorBackground } = useTheme ( ) ; const { data , isLoading } = useQuery < MeResponse > ( "/me" ) ; const routeNameRef = React . useRef < string | undefined > ( ) ; const navigationRef = React . useRef < NavigationContainerRef > ( null ) ; let body = null ; if ( isLoading ) { body = < FullscreenLoading />; } else if ( ! data ?. user ) { body = < AuthStack />; } else if ( data . user . goal && data . user . codeImgIds . length ) { body = < MainTabStack />; } else { body = < ProfileStack isNewUser / > ; } return ( < SafeAreaView style = { { flex : 1 , backgroundColor : editorBackground } } > < ReactQueryErrorResetBoundary > { ( { reset } ) => ( < ErrorBoundary onReset = { reset } FallbackComponent = { ErrorFallback } onError = { myErrorHandler } > < NavigationContainer ref = { navigationRef } onStateChange = { ( ) => { const previousRouteName = routeNameRef . current ; const currentRouteName = navigationRef . current ?. getCurrentRoute ( ) ?. name ; if ( previousRouteName !== currentRouteName ) { if ( ! [ "swiper" , "viewProfile" , "matchy" ] . includes ( currentRouteName || "" ) ) { useShowTabs . getState ( ) . set ( { show : false } ) ; } else { useShowTabs . getState ( ) . set ( { show : true } ) ; } } routeNameRef . current = currentRouteName ; } } linking = { linking } fallback = { < FullscreenLoading / > } > { body } < /NavigationContainer> < /ErrorBoundary>)} < /ReactQueryErrorResetBoundary> < /SafeAreaView>); } ;