import { BottomSheetModalProvider } from '@gorhom/bottom-sheet'; import { DefaultTheme, NavigationContainer, useNavigationContainerRef } from '@react-navigation/native'; import { QueryClient } from '@tanstack/react-query'; import dayjs from 'dayjs'; import advancedFormat from 'dayjs/plugin/advancedFormat'; import duration from 'dayjs/plugin/duration'; import relativeTime from 'dayjs/plugin/relativeTime'; import * as SplashScreen from 'expo-splash-screen'; import { StatusBar } from 'expo-status-bar'; import { useEffect, useRef, useState } from 'react'; import { GestureHandlerRootView } from 'react-native-gesture-handler'; import { MenuProvider } from 'react-native-popup-menu'; import { SafeAreaProvider } from 'react-native-safe-area-context'; import { useSnapshot } from 'valtio'; import { ClientContextProvider, LibraryContextProvider, RspcProvider, initPlausible, useClientContext, useInvalidateQuery, usePlausiblePageViewMonitor } from '@sd/client'; import { GlobalModals } from './components/modal/GlobalModals'; import { useTheme } from './hooks/useTheme'; import { changeTwTheme, tw } from './lib/tailwind'; import RootNavigator from './navigation'; import OnboardingNavigator from './navigation/OnboardingNavigator'; import { currentLibraryStore } from './utils/nav'; dayjs.extend(advancedFormat); dayjs.extend(relativeTime); dayjs.extend(duration); initPlausible({ platformType: 'mobile' }); // changeTwTheme(getThemeStore().theme); // TODO: Use above when light theme is ready changeTwTheme('dark'); function AppNavigation() { const { library } = useClientContext(); // TODO: Make sure library has actually been loaded by this point - precache with useCachedLibraries? // if (library === undefined) throw new Error("Tried to render AppNavigation before libraries fetched!") const navRef = useNavigationContainerRef(); const routeNameRef = useRef(); const [currentPath, setCurrentPath] = useState('/'); usePlausiblePageViewMonitor({ currentPath }); return ( { routeNameRef.current = navRef.getCurrentRoute()?.name; }} theme={{ ...DefaultTheme, colors: { ...DefaultTheme.colors, // Default screen background background: tw.color('app')! } }} onStateChange={async () => { const previousRouteName = routeNameRef.current; const currentRouteName = navRef.getCurrentRoute()?.name; if (previousRouteName !== currentRouteName) { // Save the current route name for later comparison routeNameRef.current = currentRouteName; // Don't track onboarding screens if (navRef.getRootState().routeNames.includes('GetStarted')) { return; } currentRouteName && setCurrentPath(currentRouteName); } }} > {!library ? ( ) : ( )} ); } function AppContainer() { useTheme(); useInvalidateQuery(); const { id } = useSnapshot(currentLibraryStore); return ( ); } const queryClient = new QueryClient(); export default function App() { useEffect(() => { SplashScreen.hideAsync(); }, []); return ( ); }