Skip to content
68 linesCodeBlameRaw
1import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
2import { DarkTheme, DefaultTheme, Stack, ThemeProvider } from "expo-router";
3import * as SplashScreen from "expo-splash-screen";
4import { StatusBar } from "expo-status-bar";
5import { useEffect, useState } from "react";
6import { useColorScheme } from "react-native";
7
8import { ApiError } from "@/lib/client";
9import { SessionProvider, useSession } from "@/lib/session";
10import { useColors } from "@/theme";
11
12void SplashScreen.preventAutoHideAsync();
13
14export default function RootLayout() {
15 const [queries] = useState(
16 () =>
17 new QueryClient({
18 defaultOptions: {
19 queries: {
20 staleTime: 30_000,
21 // Signed out, not found and refused are answers, not hiccups.
22 retry: (count, error) => !(error instanceof ApiError && error.code !== "offline") && count < 2,
23 },
24 },
25 }),
26 );
27 return (
28 <QueryClientProvider client={queries}>
29 <SessionProvider>
30 <Navigation />
31 </SessionProvider>
32 </QueryClientProvider>
33 );
34}
35
36function Navigation() {
37 const { state } = useSession();
38 const scheme = useColorScheme();
39 const colors = useColors();
40 const base = scheme === "light" ? DefaultTheme : DarkTheme;
41 const theme = {
42 ...base,
43 colors: { ...base.colors, primary: colors.accent, background: colors.bg, card: colors.surface, text: colors.fg, border: colors.line },
44 };
45
46 useEffect(() => {
47 if (state.status !== "loading") void SplashScreen.hideAsync();
48 }, [state.status]);
49
50 if (state.status === "loading") return null;
51 const signedIn = state.status === "signed-in";
52
53 return (
54 <ThemeProvider value={theme}>
55 <StatusBar style={scheme === "light" ? "dark" : "light"} />
56 <Stack screenOptions={{ headerShown: false, contentStyle: { backgroundColor: colors.bg } }}>
57 <Stack.Protected guard={signedIn}>
58 <Stack.Screen name="(app)" />
59 </Stack.Protected>
60 <Stack.Protected guard={!signedIn}>
61 <Stack.Screen name="sign-in" />
62 </Stack.Protected>
63 <Stack.Screen name="oauth/callback" />
64 <Stack.Screen name="open" />
65 </Stack>
66 </ThemeProvider>
67 );
68}