import React, { useEffect, useState } from 'react'; import { View } from 'react-native'; import { Stack, useRouter, useSegments } from 'expo-router'; import { PaperProvider, MD3DarkTheme, ActivityIndicator, Snackbar } from 'react-native-paper'; import { SafeAreaProvider } from 'react-native-safe-area-context'; import { GestureHandlerRootView } from 'react-native-gesture-handler'; import { useAppStore } from '../src/store/appStore'; import { registerToastCallback } from '../src/utils/errorHandler'; /** * Thème Material Design 3 sombre personnalisé pour n8n Pilot. * L'orange (#FF6D3E) est la couleur d'accent principale — cohérente avec l'identité n8n. */ const APP_THEME = { ...MD3DarkTheme, colors: { ...MD3DarkTheme.colors, primary: '#FF6D3E', primaryContainer: '#5C1C00', secondary: '#FF9E7D', background: '#121212', surface: '#1E1E1E', surfaceVariant: '#2C2C2C', }, }; /** * Layout racine de l'application. * Responsabilités : * 1. Fournit les providers globaux (GestureHandler, SafeArea, Paper) * 2. Charge la configuration au démarrage depuis le secure store * 3. Redirige vers /setup si aucune configuration n'existe * 4. Enregistre le callback de toast pour l'errorHandler global * 5. Affiche le toast d'erreur global en overlay */ export default function RootLayout() { const router = useRouter(); const segments = useSegments(); const { config, loadConfig } = useAppStore(); const [isReady, setIsReady] = useState(false); const [toastMessage, setToastMessage] = useState(''); const [toastVisible, setToastVisible] = useState(false); /** * Enregistre le callback de toast dans l'errorHandler au premier montage. * Permet à toute la couche API de remonter des erreurs vers l'UI sans couplage direct. */ useEffect(() => { registerToastCallback((message) => { setToastMessage(message); setToastVisible(true); }); }, []); /** Charge la configuration depuis le secure store puis marque l'app comme prête */ useEffect(() => { loadConfig().finally(() => setIsReady(true)); }, []); /** * Gère la redirection initiale selon l'état de configuration. * - Pas configuré et hors /setup → redirige vers /setup * - Configuré et dans /setup → redirige vers les tabs */ useEffect(() => { if (!isReady) return; const inSetup = segments[0] === 'setup'; if (!config.isConfigured && !inSetup) { router.replace('/setup'); } else if (config.isConfigured && inSetup) { router.replace('/(tabs)'); } }, [isReady, config.isConfigured, segments]); if (!isReady) { return ( ); } return ( {/* Toast global pour toutes les erreurs remontées par l'errorHandler */} setToastVisible(false)} duration={4000} style={{ backgroundColor: '#4A0000' }} > {toastMessage} ); }