New screens: - Category detail (workout/category/[id]): filtered workout list with SwiftUI segmented Picker for level sub-filter - Collection detail (collection/[id]): hero header with gradient, stats (workouts/minutes/calories), numbered workout list Root layout: - Inter font loading (400-900 weights) via @expo-google-fonts - SplashScreen integration for font loading gate - Route config for all screens with appropriate animations Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
89 lines
2.0 KiB
TypeScript
89 lines
2.0 KiB
TypeScript
/**
|
|
* TabataFit Root Layout
|
|
* Expo Router v3 + Inter font loading
|
|
*/
|
|
|
|
import { useCallback } from 'react'
|
|
import { Stack } from 'expo-router'
|
|
import { StatusBar } from 'expo-status-bar'
|
|
import { View } from 'react-native'
|
|
import * as SplashScreen from 'expo-splash-screen'
|
|
import {
|
|
useFonts,
|
|
Inter_400Regular,
|
|
Inter_500Medium,
|
|
Inter_600SemiBold,
|
|
Inter_700Bold,
|
|
Inter_900Black,
|
|
} from '@expo-google-fonts/inter'
|
|
|
|
import { DARK } from '@/src/shared/constants/colors'
|
|
|
|
SplashScreen.preventAutoHideAsync()
|
|
|
|
export default function RootLayout() {
|
|
const [fontsLoaded] = useFonts({
|
|
Inter_400Regular,
|
|
Inter_500Medium,
|
|
Inter_600SemiBold,
|
|
Inter_700Bold,
|
|
Inter_900Black,
|
|
})
|
|
|
|
const onLayoutRootView = useCallback(async () => {
|
|
if (fontsLoaded) {
|
|
await SplashScreen.hideAsync()
|
|
}
|
|
}, [fontsLoaded])
|
|
|
|
if (!fontsLoaded) {
|
|
return null
|
|
}
|
|
|
|
return (
|
|
<View style={{ flex: 1, backgroundColor: DARK.BASE }} onLayout={onLayoutRootView}>
|
|
<StatusBar style="light" />
|
|
<Stack
|
|
screenOptions={{
|
|
headerShown: false,
|
|
contentStyle: { backgroundColor: DARK.BASE },
|
|
animation: 'slide_from_right',
|
|
}}
|
|
>
|
|
<Stack.Screen name="(tabs)" />
|
|
<Stack.Screen
|
|
name="workout/[id]"
|
|
options={{
|
|
animation: 'slide_from_bottom',
|
|
}}
|
|
/>
|
|
<Stack.Screen
|
|
name="workout/category/[id]"
|
|
options={{
|
|
animation: 'slide_from_right',
|
|
}}
|
|
/>
|
|
<Stack.Screen
|
|
name="collection/[id]"
|
|
options={{
|
|
animation: 'slide_from_right',
|
|
}}
|
|
/>
|
|
<Stack.Screen
|
|
name="player/[id]"
|
|
options={{
|
|
presentation: 'fullScreenModal',
|
|
animation: 'fade',
|
|
}}
|
|
/>
|
|
<Stack.Screen
|
|
name="complete/[id]"
|
|
options={{
|
|
animation: 'fade',
|
|
}}
|
|
/>
|
|
</Stack>
|
|
</View>
|
|
)
|
|
}
|