81 lines
2.6 KiB
TypeScript
81 lines
2.6 KiB
TypeScript
import { DarkTheme, DefaultTheme, ThemeProvider } from "@react-navigation/native";
|
|
import { Stack } from "expo-router";
|
|
import * as SplashScreen from "expo-splash-screen";
|
|
import { StatusBar } from "expo-status-bar";
|
|
import "react-native-reanimated";
|
|
import { GestureHandlerRootView } from "react-native-gesture-handler";
|
|
import { useColorScheme } from "@/hooks/useColorScheme";
|
|
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
|
|
import { cloneDeep } from "lodash";
|
|
import { SplashScreenController } from "@/components/Splash";
|
|
import { useInitializeApp } from "@/hooks/auth";
|
|
import { LoadingView } from "@/components/LoadingView";
|
|
import { supabase } from "@/lib/supabase";
|
|
import { AppState } from "react-native";
|
|
|
|
window.structuredClone = cloneDeep;
|
|
|
|
// Prevent the splash screen from auto-hiding before asset loading is complete.
|
|
SplashScreen.preventAutoHideAsync();
|
|
|
|
const queryClient = new QueryClient({
|
|
defaultOptions: {
|
|
queries: {
|
|
// 3 total attempts (1 initial + 2 retries)
|
|
retry: 2,
|
|
// 0s -> 1s, 1s → 5s. Little resiliency 😁
|
|
retryDelay: (attemptIndex) => Math.min(1000 * 5 ** attemptIndex, 10000),
|
|
},
|
|
},
|
|
});
|
|
|
|
// Tells Supabase Auth to continuously refresh the session automatically if
|
|
// the app is in the foreground. When this is added, you will continue to receive
|
|
// `onAuthStateChange` events with the `TOKEN_REFRESHED` or `SIGNED_OUT` event
|
|
// if the user's session is terminated. This should only be registered once.
|
|
AppState.addEventListener("change", (state) => {
|
|
if (state === "active") {
|
|
supabase.auth.startAutoRefresh();
|
|
} else {
|
|
supabase.auth.stopAutoRefresh();
|
|
}
|
|
});
|
|
|
|
export default function RootLayout() {
|
|
const colorScheme = useColorScheme();
|
|
|
|
return (
|
|
<GestureHandlerRootView style={{ flex: 1 }}>
|
|
<QueryClientProvider client={queryClient}>
|
|
<ThemeProvider value={colorScheme === "dark" ? DarkTheme : DefaultTheme}>
|
|
<SplashScreenController />
|
|
<RootNavigator />
|
|
<StatusBar style="auto" />
|
|
</ThemeProvider>
|
|
</QueryClientProvider>
|
|
</GestureHandlerRootView>
|
|
);
|
|
}
|
|
|
|
const RootNavigator = () => {
|
|
const { isLoading, isLoggedIn } = useInitializeApp();
|
|
|
|
if (isLoading) {
|
|
return <LoadingView />;
|
|
}
|
|
|
|
return (
|
|
<Stack>
|
|
<Stack.Protected guard={isLoggedIn}>
|
|
<Stack.Screen name="(app)" options={{ headerShown: false }} />
|
|
</Stack.Protected>
|
|
|
|
<Stack.Protected guard={!isLoggedIn}>
|
|
<Stack.Screen name="login" options={{ headerShown: false }} />
|
|
<Stack.Screen name="signup" options={{ headerShown: false }} />
|
|
</Stack.Protected>
|
|
|
|
<Stack.Screen name="+not-found" />
|
|
</Stack>
|
|
);
|
|
};
|