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>
This commit is contained in:
@@ -1,9 +1,15 @@
|
||||
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)',
|
||||
@@ -11,10 +17,32 @@ export const unstable_settings = {
|
||||
|
||||
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"
|
||||
|
||||
Reference in New Issue
Block a user