Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 | 1x 11x 11x 11x 11x 11x 11x 11x 5x 11x 11x 11x 11x 11x 9x 11x 5x 5x 5x 11x 6x 6x 6x 11x 1x 10x 1x | import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import { ActivityIndicator, StyleSheet, View } from 'react-native';
import { NavigationContainerRef } from '@react-navigation/native';
import { CoreNavigation } from '@repo/core/navigation/CoreNavigation';
import { useAuth } from '@/contexts/AuthContext';
import { DeepLinkProvider } from '@/contexts/DeepLinkContext';
import { linkingConfig, useNavigateDeepLinks } from '@/hooks/deeplink';
import type { AppStackParamList } from '@/types/navigation';
import { AuthNavigator } from './AuthStackNavigation';
import { Navigation as AppNavigator } from './Navigation';
type TimeoutHandle = number | { cancel: () => void };
export const Navigation = () => {
const { user, loading } = useAuth();
const prevUserRef = useRef(user);
const navigationRef = useRef<NavigationContainerRef<AppStackParamList>>(null);
const isNavigationReadyRef = useRef(false);
const timeoutRefsRef = useRef<TimeoutHandle[]>([]);
// Derive isLoggedOut during render to avoid one-render delay from state update
const isLoggedOut = !!prevUserRef.current && !user;
useEffect(() => {
prevUserRef.current = user;
}, [user]);
const { processPendingDeepLink, setPendingDeepLink, navigateFromDeepLink } = useNavigateDeepLinks(
navigationRef,
isNavigationReadyRef,
timeoutRefsRef,
);
const contextValueRef = useRef({ setPendingDeepLink, navigateFromDeepLink });
contextValueRef.current = { setPendingDeepLink, navigateFromDeepLink };
const [isNavigationReadyState, setIsNavigationReadyState] = useState(false);
const contextValue = useMemo(
() => ({
setPendingDeepLink: (url: string) => contextValueRef.current.setPendingDeepLink(url),
navigateFromDeepLink: (url: string) => contextValueRef.current.navigateFromDeepLink(url),
navigationRef,
isNavigationReady: isNavigationReadyState,
}),
[isNavigationReadyState],
);
useEffect(() => {
return () => {
timeoutRefsRef.current.forEach(handle => {
typeof handle === 'number' ? cancelAnimationFrame(handle) : handle.cancel();
});
timeoutRefsRef.current = [];
};
}, []);
const handleNavigationReady = useCallback(() => {
isNavigationReadyRef.current = true;
setIsNavigationReadyState(true);
processPendingDeepLink();
}, [processPendingDeepLink]);
if (loading) {
return (
<View style={styles.loadingContainer} testID="loading-indicator">
<ActivityIndicator size="large" />
</View>
);
}
return (
<DeepLinkProvider value={contextValue}>
<CoreNavigation
navigationRef={navigationRef}
linking={linkingConfig}
onReady={handleNavigationReady}
>
{user ? <AppNavigator /> : <AuthNavigator isLoggedOut={isLoggedOut} />}
</CoreNavigation>
</DeepLinkProvider>
);
};
const styles = StyleSheet.create({
loadingContainer: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
},
});
|