Files
tabatago/app/_layout.tsx
Millian Lamiaux fa189fe72e feat: onboarding flow (6 screens) + audio engine + design system
Onboarding:
- 6-screen flow: Problem → Empathy → Solution → Wow → Personalization → Paywall
- useOnboarding hook with Zustand + AsyncStorage persistence
- MiniTimerDemo with live 20s timer + haptics
- Auto-redirect for first-time users
- Mock RevenueCat for dev testing

Audio:
- useAudioEngine hook with expo-av
- Phase sounds (count_3/2/1, beep, bell, fanfare)
- Placeholder music tracks

Design System:
- Typography component + constants
- GlassView component
- Spacing, shadows, animations, borderRadius constants
- Extended color palette (phase gradients, glass, surfaces)

Timer:
- Fix: handle 0-duration phases (immediate advance)
- Enhanced TimerDisplay with phase gradients

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 21:52:23 +01:00

61 lines
1.8 KiB
TypeScript

import { useEffect } from 'react';
import { DarkTheme, DefaultTheme, ThemeProvider } from '@react-navigation/native';
import { Stack } from 'expo-router';
import { StatusBar } from 'expo-status-bar';
import * as SplashScreen from 'expo-splash-screen';
import 'react-native-reanimated';
import { useColorScheme } from '@/hooks/use-color-scheme';
import { useIsOnboardingComplete } from '@/src/features/onboarding/hooks/useOnboarding';
// Prevent splash screen from auto-hiding
SplashScreen.preventAutoHideAsync();
export const unstable_settings = {
anchor: '(tabs)',
};
export default function RootLayout() {
const colorScheme = useColorScheme();
const isOnboardingComplete = useIsOnboardingComplete();
// Hide splash screen once we have a definite state
useEffect(() => {
if (isOnboardingComplete !== undefined) {
SplashScreen.hideAsync();
}
}, [isOnboardingComplete]);
// Show nothing while Zustand hydrates from AsyncStorage
if (isOnboardingComplete === undefined) {
return null;
}
return (
<ThemeProvider value={colorScheme === 'dark' ? DarkTheme : DefaultTheme}>
<Stack>
<Stack.Screen
name="onboarding"
options={{
headerShown: false,
presentation: 'fullScreenModal',
animation: 'fade',
gestureEnabled: false,
}}
/>
<Stack.Screen name="(tabs)" options={{ headerShown: false }} />
<Stack.Screen
name="timer"
options={{
headerShown: false,
presentation: 'fullScreenModal',
animation: 'fade',
}}
/>
<Stack.Screen name="modal" options={{ presentation: 'modal', title: 'Modal' }} />
</Stack>
<StatusBar style="auto" />
</ThemeProvider>
);
}