import React, { useState, useCallback } from 'react'; import { View, Text, StyleSheet, TouchableOpacity, Dimensions, ActivityIndicator, } from 'react-native'; import { useNavigation } from '@react-navigation/native'; import { MaterialIcons } from '@expo/vector-icons'; import { ONBOARDING_STEPS, CURRENT_ONBOARDING_VERSION, type OnboardingStep } from '../config/onboarding'; import { onboardingStorage } from '../services/onboardingStorage'; import { scanSubdirectories } from '../hooks/useDeviceFiles'; import { safDirectory } from '../services/safDirectory'; import * as FileSystem from 'expo-file-system/legacy'; const { width: SCREEN_WIDTH } = Dimensions.get('window'); type ScanState = 'idle' | 'scanning' | 'done'; function stepIcon(step: OnboardingStep): keyof typeof MaterialIcons.glyphMap { if (step.icon === 'waving-hand') return 'waving-hand'; if (step.icon === 'create-new-folder') return 'create-new-folder'; if (step.icon === 'check-circle') return 'check-circle'; if (step.icon === 'folder-off') return 'folder-off'; return 'info'; } function ScanProgressView() { return ( <> Scan en cours... Dot. explore les sous-dossiers de votre stockage. Cela peut prendre quelques secondes. ); } function ScanDoneView({ folderCount }: { folderCount: number }) { return ( <> Scan terminé ! {folderCount > 1 ? `${folderCount} dossiers découverts et ajoutés à votre espace Dot.` : '1 dossier ajouté à votre espace Dot.'} ); } export function OnboardingScreen() { const navigation = useNavigation(); const [currentIndex, setCurrentIndex] = useState(0); const [scanState, setScanState] = useState('idle'); const [folderCount, setFolderCount] = useState(0); const pendingSteps = onboardingStorage.getPendingSteps(); const step = pendingSteps[currentIndex]; const complete = useCallback(() => { onboardingStorage.setCompletedVersion(CURRENT_ONBOARDING_VERSION); navigation.reset({ index: 0, routes: [{ name: 'Home' as never }] }); }, [navigation]); const handleRecursiveScan = useCallback(async () => { try { const result = await FileSystem.StorageAccessFramework.requestDirectoryPermissionsAsync(); if (!result.granted) return; const dirUri = result.directoryUri; const parts = dirUri.split('/'); const dirName = decodeURIComponent(parts[parts.length - 1] ?? 'Stockage'); setScanState('scanning'); safDirectory.addFolder(dirUri, dirName); const subdirs = await scanSubdirectories(dirUri); if (subdirs.length > 0) { safDirectory.addBatchFolders( subdirs.map((d) => ({ uri: d.uri, name: d.name, source: 'recursive', parentUri: d.parentUri })) ); } setFolderCount(1 + subdirs.length); setScanState('done'); safDirectory.setDiscovered(); } catch (err) { console.error('[Onboarding] recursive scan error:', err); setScanState('idle'); } }, []); const handleNext = useCallback(async () => { if (!step) return; onboardingStorage.markStepSeen(step.id); if (currentIndex < pendingSteps.length - 1) { setCurrentIndex(currentIndex + 1); setScanState('idle'); setFolderCount(0); } else { complete(); } }, [step, currentIndex, pendingSteps.length, complete]); const handleSkip = useCallback(() => { complete(); }, [complete]); if (!step) { complete(); return null; } const isScanStep = step.action?.type === 'recursive_scan'; return ( Passer {scanState === 'scanning' && isScanStep ? ( ) : scanState === 'done' && isScanStep ? ( ) : ( <> {step.title} {step.description} {isScanStep && scanState === 'idle' && ( {step.action?.label ?? 'Choisir un dossier'} )} )} {pendingSteps.map((_, i) => ( ))} {(!isScanStep || scanState === 'done') && ( {currentIndex < pendingSteps.length - 1 ? 'Suivant' : 'Commencer'} )} {isScanStep && scanState === 'idle' && ( Passer cette étape )} ); } const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: '#fff', }, skipContainer: { alignItems: 'flex-end', paddingHorizontal: 20, paddingTop: 60, }, skipText: { fontSize: 16, color: '#999', }, content: { flex: 1, justifyContent: 'center', alignItems: 'center', paddingHorizontal: 40, }, iconContainer: { width: 120, height: 120, borderRadius: 60, backgroundColor: '#E3F2FD', justifyContent: 'center', alignItems: 'center', marginBottom: 40, }, title: { fontSize: 26, fontWeight: '700', color: '#333', textAlign: 'center', marginBottom: 16, }, description: { fontSize: 16, color: '#666', textAlign: 'center', lineHeight: 24, }, actionBtn: { flexDirection: 'row', alignItems: 'center', backgroundColor: '#F57C00', borderRadius: 12, paddingHorizontal: 24, paddingVertical: 14, gap: 10, marginTop: 32, }, actionBtnText: { fontSize: 16, color: '#fff', fontWeight: '600', }, footer: { paddingHorizontal: 40, paddingBottom: 60, alignItems: 'center', gap: 24, }, dots: { flexDirection: 'row', gap: 8, }, dot: { width: 8, height: 8, borderRadius: 4, backgroundColor: '#ddd', }, dotActive: { backgroundColor: '#1976D2', width: 24, }, nextBtn: { flexDirection: 'row', alignItems: 'center', backgroundColor: '#1976D2', borderRadius: 12, paddingHorizontal: 32, paddingVertical: 14, gap: 8, }, nextBtnText: { fontSize: 16, color: '#fff', fontWeight: '600', }, });