import { DarkTheme, DefaultTheme, ThemeProvider } from '@react-navigation/native'; import { Stack, router, useRootNavigationState, useSegments } from 'expo-router'; import * as SplashScreen from 'expo-splash-screen'; import { StatusBar } from 'expo-status-bar'; import { useEffect, useRef } from 'react'; // import 'react-native-reanimated'; // Often causes issues on web if not configured perfectly, optional here import { Platform, StyleSheet, View } from 'react-native'; import { LoadingSpinner } from '@/components/ui/LoadingSpinner'; import { ToastProvider } from '@/components/ui/Toast'; import { AuthProvider, useAuth } from '@/contexts/AuthContext'; import { BeneficiaryProvider } from '@/contexts/BeneficiaryContext'; import { useColorScheme } from '@/hooks/use-color-scheme'; // Polyfill for $ to prevent ReferenceError: Cannot access '$' before initialization // This is a workaround for some web-specific bundling issues in this project. if (Platform.OS === 'web' && typeof window !== 'undefined') { // @ts-ignore if (typeof window.$ === 'undefined') { // @ts-ignore window.$ = undefined; } } // Prevent auto-hide, ignore errors if splash not available SplashScreen.preventAutoHideAsync().catch(() => { }); let splashHidden = false; function RootLayoutNav() { const colorScheme = useColorScheme(); const { isAuthenticated, isInitializing } = useAuth(); const segments = useSegments(); const navigationState = useRootNavigationState(); // Track if initial redirect was done const hasInitialRedirect = useRef(false); // Note: Token URL login feature not yet implemented // Would need api.setToken() method and AuthContext.refreshAuth() call useEffect(() => { if (!navigationState?.key) return; if (isInitializing) return; if (!splashHidden) { splashHidden = true; SplashScreen.hideAsync().catch(() => { }); } const inAuthGroup = segments[0] === '(auth)'; if (!hasInitialRedirect.current) { hasInitialRedirect.current = true; // URL Param Auth Check (Simple version) if (Platform.OS === 'web') { const url = new URL(window.location.href); const token = url.searchParams.get('token'); if (token) { // If we have a token, we might be authenticated now (race condition with AuthProvider). // If isAuthenticated is true, good. If not, maybe we need to wait. // But for now, let's allow the flow. } } if (!isAuthenticated && !inAuthGroup) { router.replace('/(auth)/login'); return; } } }, [isAuthenticated, isInitializing, navigationState?.key]); if (isInitializing) { return ; } return ( ); } export default function RootLayout() { return ( ); } const styles = StyleSheet.create({ webContainer: { flex: 1, backgroundColor: '#e5e5e5', // Light gray background for desktop alignItems: 'center', justifyContent: 'center', }, mobileWrapper: { flex: 1, width: '100%', maxWidth: 430, // Mobile width constraint backgroundColor: '#fff', shadowColor: '#000', shadowOffset: { width: 0, height: 2, }, shadowOpacity: 0.25, shadowRadius: 3.84, elevation: 5, overflow: 'hidden', // Clip content to rounded corners if we want } });