import FontAwesome from '@expo/vector-icons/FontAwesome'; import { DarkTheme, DefaultTheme, ThemeProvider } from '@react-navigation/native'; import { useFonts } from 'expo-font'; import { Stack } from 'expo-router'; import * as SplashScreen from 'expo-splash-screen'; import { useEffect, useState } from 'react'; import 'react-native-reanimated'; import { useColorScheme } from '@/components/useColorScheme'; import { initI18n } from '@/src/i18n'; 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: 'index', }; // Prevent the splash screen from auto-hiding before asset loading is complete. SplashScreen.preventAutoHideAsync(); export default function RootLayout() { const [loaded, error] = useFonts({ SpaceMono: require('../assets/fonts/SpaceMono-Regular.ttf'), ...FontAwesome.font, }); const [i18nReady, setI18nReady] = useState(false); // Expo Router uses Error Boundaries to catch errors in the navigation tree. useEffect(() => { if (error) throw error; }, [error]); useEffect(() => { initI18n() .catch((e) => { // i18n 初始化失败不应阻塞 App 启动,先打印错误再继续 console.error('i18n 初始化失败', e); }) .finally(() => setI18nReady(true)); }, []); useEffect(() => { // 等字体与 i18n 都准备好后再隐藏启动页,避免文案闪烁 if (loaded && i18nReady) { SplashScreen.hideAsync(); } }, [loaded, i18nReady]); if (!loaded || !i18nReady) { return null; } return ; } function RootLayoutNav() { const colorScheme = useColorScheme(); return ( {/* 启动分发页:根据 onboarding 状态跳转 */} {/* Onboarding 分组 */} {/* 主应用分组(不使用 Tabs) */} {/* 其他 */} ); }