expo-duooomi-app/app/_layout.tsx

129 lines
4.0 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import '../global.css'
import 'react-native-reanimated'
import { DarkTheme, DefaultTheme, ThemeProvider } from '@react-navigation/native'
import * as Sentry from '@sentry/react-native'
import { Stack, useNavigationContainerRef } from 'expo-router'
import { StatusBar } from 'expo-status-bar'
import { useEffect } from 'react'
import { GestureHandlerRootView } from 'react-native-gesture-handler'
import { KeyboardProvider } from 'react-native-keyboard-controller'
import { SafeAreaProvider, SafeAreaView } from 'react-native-safe-area-context'
import { ModalPortal } from '@/@share/components'
import { bleManager } from '@/ble/managers/bleManager'
import { HotUpdate } from '@/components/hot-update'
import { useColorScheme } from '@/hooks/use-color-scheme'
import { setupGlobalFetchLogger } from '@/lib/fetch-logger'
import { useUserSession } from '@/stores/UserStore'
Sentry.init({
dsn: 'https://ef710a118839b1e86e38a3833a9a3c6c@o4507705403965440.ingest.us.sentry.io/4510576286302208',
sendDefaultPii: true,
enableLogs: true,
enabled: !__DEV__,
})
if (__DEV__) {
setupGlobalFetchLogger()
}
export const unstable_settings = {
anchor: '(tabs)',
}
function RootLayout() {
const ref = useNavigationContainerRef()
useEffect(() => {
if (!ref?.current) return
const unsubscribe = ref.addListener('state', (e) => {
try {
const routes = e.data.state?.routes
if (!routes || routes.length === 0) return
const currentRoute = routes[routes.length - 1]
if (!currentRoute) return
let screenName = currentRoute.name
let params = currentRoute.params
// 处理嵌套路由
if (currentRoute.state?.routes) {
const nestedRoutes = currentRoute.state.routes
const activeNestedRoute = nestedRoutes[nestedRoutes.length - 1]
if (activeNestedRoute && activeNestedRoute.name !== '__root') {
screenName = activeNestedRoute.name
params = activeNestedRoute.params
}
}
// 使用 debug 而非 warn避免噪音
if (__DEV__) {
console.debug(`📍 Navigation: ${screenName}`, params ? `(${JSON.stringify(params)})` : '')
}
// 上报到 Sentry可选
Sentry.captureMessage(`Navigation: ${screenName}`, 'info')
} catch (error) {
console.error('❌ Navigation listener error:', error)
Sentry.captureException(error)
}
})
return unsubscribe
}, [ref])
useEffect(() => {
bleManager.initialize()
return () => {
bleManager.destroy()
}
}, [])
return (
<Providers>
<Stack>
<Stack.Screen name="(tabs)" options={{ headerShown: false }} />
<Stack.Screen name="auth" options={{ headerShown: false }} />
<Stack.Screen name="forgot-password" options={{ headerShown: false }} />
<Stack.Screen name="pointList" options={{ headerShown: false }} />
</Stack>
</Providers>
)
}
function Providers({ children }: { children: React.ReactNode }) {
const colorScheme = useColorScheme()
useUserSession()
return (
<SafeAreaProvider>
<GestureHandlerRootView style={{ flex: 1 }}>
<KeyboardProvider>
<ThemeProvider value={colorScheme === 'dark' ? DarkTheme : DefaultTheme}>
<SafeAreaView
className="flex-1"
edges={['top']}
style={{ backgroundColor: colorScheme === 'dark' ? '#21221D' : '#ffffff' }}
>
<StatusBar />
<HotUpdate />
{children}
</SafeAreaView>
<ModalPortal ref={(ref) => ((global as any).actionSheet = ref)} />
<ModalPortal ref={(ref) => ((global as any).modal = ref)} />
<ModalPortal ref={(ref) => ((global as any).loading = ref)} />
<ModalPortal ref={(ref) => ((global as any).toast = ref)} />
</ThemeProvider>
</KeyboardProvider>
</GestureHandlerRootView>
</SafeAreaProvider>
)
}
export default Sentry.wrap(RootLayout)