import { useEffect, useState } from 'react'; import { Stack } from 'expo-router'; import { StatusBar } from 'expo-status-bar'; import { StripeProvider } from '@stripe/stripe-react-native'; import AsyncStorage from '@react-native-async-storage/async-storage'; import { AppProvider, useApp } from '../context/AppContext'; import { CoachMarksProvider } from '../context/CoachMarksContext'; import { CoachMarksOverlay } from '../components/CoachMarksOverlay'; import { useColors } from '../constants/Colors'; import { AuthService } from '../services/authService'; import { initDatabase, AppMetaDb } from '../services/database'; import * as SecureStore from 'expo-secure-store'; type InitialRoute = 'onboarding' | 'auth/login' | '(tabs)'; const STRIPE_PUBLISHABLE_KEY = (process.env.EXPO_PUBLIC_STRIPE_PUBLISHABLE_KEY || 'pk_test_mock_key').trim(); const SECURE_INSTALL_MARKER = 'greenlens_install_v1'; const ensureInstallConsistency = async (): Promise => { try { const [sqliteMarker, secureMarker] = await Promise.all([ Promise.resolve(AppMetaDb.get('install_marker_v2')), SecureStore.getItemAsync(SECURE_INSTALL_MARKER).catch(() => null), ]); if (sqliteMarker && secureMarker) return false; // Kein Fresh Install // Fresh Install: Alles zurücksetzen await AuthService.logout(); await AsyncStorage.removeItem('greenlens_show_tour'); AppMetaDb.set('install_marker_v2', '1'); await SecureStore.setItemAsync(SECURE_INSTALL_MARKER, '1'); return true; } catch (error) { console.error('Failed to initialize install marker', error); return false; } }; function RootLayoutInner() { const { isDarkMode, colorPalette, signOut } = useApp(); const colors = useColors(isDarkMode, colorPalette); const [initialRoute, setInitialRoute] = useState(null); useEffect(() => { (async () => { const didResetSessionForFreshInstall = await ensureInstallConsistency(); if (didResetSessionForFreshInstall) { await signOut(); } const session = await AuthService.getSession(); if (!session) { // Kein Benutzer → immer zum Onboarding (Landing + Register/Login) setInitialRoute('auth/login'); return; } const validity = await AuthService.validateWithServer(); if (validity === 'invalid') { await AuthService.logout(); await signOut(); setInitialRoute('auth/login'); return; } // 'valid' or 'unreachable' (offline) → allow tab navigation setInitialRoute('(tabs)'); })(); }, [signOut]); if (initialRoute === null) return null; return ( <> {/* Coach Marks rendern über allem */} ); } export default function RootLayout() { initDatabase(); return ( ); }