import 'dart:io'; import 'package:flutter/material.dart'; import 'package:image_picker/image_picker.dart'; import 'package:permission_handler/permission_handler.dart'; import 'package:device_info_plus/device_info_plus.dart'; import 'package:provider/provider.dart'; import '../../core/constants/app_constants.dart'; import '../../core/theme/app_theme.dart'; import '../../data/models/target_type.dart'; import '../crop/crop_screen.dart'; import '../session/session_provider.dart'; import 'widgets/image_source_button.dart'; class CaptureScreen extends StatefulWidget { const CaptureScreen({super.key}); @override State createState() => _CaptureScreenState(); } class _CaptureScreenState extends State { final ImagePicker _picker = ImagePicker(); final TargetType _selectedType = TargetType.concentric; String? _selectedImagePath; bool _isLoading = false; Future _handleGallerySelection() async { PermissionStatus status; if (Platform.isAndroid) { final deviceInfo = DeviceInfoPlugin(); final androidInfo = await deviceInfo.androidInfo; if (androidInfo.version.sdkInt >= 33) { status = await Permission.photos.request(); } else { status = await Permission.storage.request(); } } else { status = await Permission.photos.request(); } if (status.isGranted) { _captureImage(ImageSource.gallery); } else if (status.isPermanentlyDenied) { _showSettingsDialog(); } else { if (mounted) { ScaffoldMessenger.of(context).showSnackBar( const SnackBar( content: Text('Accès à la galerie requis pour continuer'), ), ); } } } void _showSettingsDialog() { showDialog( context: context, builder: (context) => AlertDialog( title: const Text('Permission requise'), content: const Text( 'L\'accès aux photos est nécessaire. Veuillez l\'activer dans les paramètres.', ), actions: [ TextButton( onPressed: () => Navigator.pop(context), child: const Text('Annuler'), ), TextButton( onPressed: () => openAppSettings(), child: const Text('Paramètres'), ), ], ), ); } @override Widget build(BuildContext context) { final sessionProvider = context.watch(); final title = sessionProvider.isSessionActive ? 'Cible ${sessionProvider.targetCount + 1}' : 'Source'; return Scaffold( appBar: AppBar(title: Text(title)), body: SingleChildScrollView( padding: const EdgeInsets.all(AppConstants.defaultPadding), child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ const SizedBox(height: AppConstants.largePadding), _buildSectionTitle('Source de l\'Image'), const SizedBox(height: 12), Row( children: [ Expanded( child: ImageSourceButton( icon: Icons.camera_alt, label: 'Scanner', // Appelle maintenant l'appareil photo classique onPressed: _isLoading ? null : _openStandardCamera, ), ), const SizedBox(width: 12), Expanded( child: ImageSourceButton( icon: Icons.photo_library, label: 'Galerie', onPressed: _isLoading ? null : _handleGallerySelection, ), ), ], ), const SizedBox(height: AppConstants.largePadding), if (_isLoading) const Center( child: Padding( padding: EdgeInsets.all(32), child: CircularProgressIndicator(), ), ) else _buildGuide(), ], ), ), ); } Widget _buildSectionTitle(String title) { return Text( title, style: Theme.of( context, ).textTheme.titleMedium?.copyWith(fontWeight: FontWeight.bold), ); } Widget _buildGuide() { return Card( child: Padding( padding: const EdgeInsets.all(AppConstants.defaultPadding), child: Column( children: [ Icon(Icons.help_outline, size: 48, color: Colors.grey[400]), const SizedBox(height: 12), Text( 'Conseils pour une bonne analyse', style: Theme.of( context, ).textTheme.titleSmall?.copyWith(fontWeight: FontWeight.bold), ), const SizedBox(height: 12), _buildGuideItem( Icons.crop_free, 'Cadrez la cible entière dans l\'image', ), _buildGuideItem(Icons.wb_sunny, 'Utilisez un bon éclairage'), _buildGuideItem(Icons.straighten, 'Prenez la photo de face'), _buildGuideItem(Icons.blur_off, 'Évitez les images floues'), _buildGuideItem( Icons.cleaning_services, 'Nettoyer votre objectif avec une chiffonnette', ), ], ), ), ); } Widget _buildGuideItem(IconData icon, String text) { return Padding( padding: const EdgeInsets.symmetric(vertical: 4), child: Row( children: [ Icon(icon, size: 20, color: AppTheme.primaryColor), const SizedBox(width: 12), Expanded(child: Text(text)), ], ), ); } // NOUVELLE FONCTION : Ouvre l'appareil photo classique 100% Manuel Future _openStandardCamera() async { final status = await Permission.camera.request(); if (status.isGranted) { _captureImage(ImageSource.camera); } else { if (mounted) { ScaffoldMessenger.of(context).showSnackBar( const SnackBar(content: Text('Accès à l\'appareil photo requis')), ); } } } Future _captureImage(ImageSource source) async { setState(() => _isLoading = true); try { final XFile? image = await _picker.pickImage( source: source, maxWidth: 2048, maxHeight: 2048, imageQuality: 90, ); if (image != null) { setState(() { _selectedImagePath = image.path; }); // On appelle directement l'analyse avec le bon chemin de fichier _analyzeImage(); } } catch (e) { debugPrint('Erreur capture: $e'); } finally { if (mounted) setState(() => _isLoading = false); } } void _analyzeImage() { if (_selectedImagePath == null) return; // Correction de la redirection pour ouvrir proprement le CropScreen Navigator.push( context, MaterialPageRoute( builder: (_) => CropScreen( imagePath: _selectedImagePath!, targetType: _selectedType, ), ), ); } }