mirror of
https://github.com/SrIzan10/featheroom.git
synced 2026-06-06 00:56:49 +00:00
123 lines
3.3 KiB
TypeScript
123 lines
3.3 KiB
TypeScript
import { MaterialCommunityIcons } from '@expo/vector-icons'
|
|
import {
|
|
useFonts,
|
|
JetBrainsMono_400Regular,
|
|
} from '@expo-google-fonts/jetbrains-mono'
|
|
import { NotoSans_400Regular } from '@expo-google-fonts/noto-sans'
|
|
import * as Localization from 'expo-localization'
|
|
import { SplashScreen, Stack } from 'expo-router'
|
|
import * as SecureStore from 'expo-secure-store'
|
|
import React from 'react'
|
|
import { Platform, useColorScheme } from 'react-native'
|
|
import { PaperProvider } from 'react-native-paper'
|
|
|
|
import Locales from '@/lib/locales'
|
|
import { Setting } from '@/lib/types'
|
|
import { StackHeader, Themes } from '@/lib/ui'
|
|
|
|
export {
|
|
// Catch any errors thrown by the Layout component.
|
|
ErrorBoundary,
|
|
} from 'expo-router'
|
|
|
|
export const unstable_settings = {
|
|
// Ensure that reloading on `/modal` keeps a back button present.
|
|
initialRouteName: '(tabs)',
|
|
}
|
|
|
|
// Prevent the splash screen from auto-hiding before asset loading is complete.
|
|
SplashScreen.preventAutoHideAsync()
|
|
|
|
const RootLayout = () => {
|
|
const [loaded, error] = useFonts({
|
|
NotoSans_400Regular,
|
|
JetBrainsMono_400Regular,
|
|
...MaterialCommunityIcons.font,
|
|
})
|
|
|
|
// Expo Router uses Error Boundaries to catch errors in the navigation tree.
|
|
React.useEffect(() => {
|
|
if (error) throw error
|
|
}, [error])
|
|
|
|
React.useEffect(() => {
|
|
if (loaded) {
|
|
SplashScreen.hideAsync()
|
|
}
|
|
}, [loaded])
|
|
|
|
if (!loaded) {
|
|
return null
|
|
}
|
|
|
|
return <RootLayoutNav />
|
|
}
|
|
|
|
const RootLayoutNav = () => {
|
|
const colorScheme = useColorScheme()
|
|
const [settings, setSettings] = React.useState<Setting>({
|
|
theme: 'auto',
|
|
color: 'default',
|
|
language: 'auto',
|
|
})
|
|
|
|
// Load settings from the device
|
|
React.useEffect(() => {
|
|
if (Platform.OS !== 'web') {
|
|
SecureStore.getItemAsync('settings').then((result) => {
|
|
if (result === null) {
|
|
SecureStore.setItemAsync('settings', JSON.stringify(settings)).then(
|
|
(res) => console.log(res),
|
|
)
|
|
}
|
|
|
|
setSettings(JSON.parse(result ?? JSON.stringify(settings)))
|
|
})
|
|
} else {
|
|
setSettings({ ...settings, theme: colorScheme ?? 'light' })
|
|
}
|
|
|
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
}, [])
|
|
|
|
React.useEffect(() => {
|
|
if (settings.language === 'auto') {
|
|
Locales.locale = Localization.getLocales()[0].languageCode ?? 'en'
|
|
} else {
|
|
Locales.locale = settings.language
|
|
}
|
|
|
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
}, [])
|
|
|
|
return (
|
|
<PaperProvider
|
|
theme={
|
|
Themes[
|
|
settings.theme === 'auto' ? (colorScheme ?? 'dark') : settings.theme
|
|
][settings.color]
|
|
}
|
|
>
|
|
<Stack
|
|
screenOptions={{
|
|
animation: 'slide_from_bottom',
|
|
header: (props) => (
|
|
<StackHeader navProps={props} children={undefined} />
|
|
),
|
|
}}
|
|
>
|
|
<Stack.Screen name="(auth)" options={{ headerShown: false }} />
|
|
<Stack.Screen name="(tabs)" options={{ headerShown: false }} />
|
|
<Stack.Screen name="drawer" options={{ headerShown: false }} />
|
|
<Stack.Screen name="search" options={{ title: Locales.t('search') }} />
|
|
<Stack.Screen
|
|
name="modal"
|
|
options={{ title: Locales.t('titleModal'), presentation: 'modal' }}
|
|
/>
|
|
</Stack>
|
|
</PaperProvider>
|
|
)
|
|
}
|
|
|
|
export default RootLayout
|