You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

160 lines
5.5KB

  1. // lib/presentation/screens/media_picker/media_picker_screen.dart
  2. import 'dart:convert';
  3. import 'dart:io';
  4. import 'package:flutter/material.dart';
  5. import 'package:image_picker/image_picker.dart';
  6. // --- IMPORTS NÉCESSAIRES ---
  7. import '../../../routes/app_routes.dart';
  8. import '../../../repositories/ai_repository.dart';
  9. import '../../../services/image_analysis_service.dart';
  10. import '../ai_enhancement/ai_enhancement_screen.dart';
  11. class MediaPickerScreen extends StatefulWidget {
  12. const MediaPickerScreen({super.key});
  13. @override
  14. State<MediaPickerScreen> createState() => _MediaPickerScreenState();
  15. }
  16. class _MediaPickerScreenState extends State<MediaPickerScreen> {
  17. final _picker = ImagePicker();
  18. XFile? _selectedMedia;
  19. bool _isAnalyzing = false;
  20. // --- DÉCLARATION CORRECTE DES DÉPENDANCES ---
  21. // On instancie les dépendances. AiRepository n'a pas besoin d'arguments.
  22. final AiRepository _aiRepository = AiRepository();
  23. // --- FIN DE LA CORRECTION ---
  24. /// Déclenche la sélection d'image depuis la source choisie (galerie ou caméra).
  25. Future<void> _pickImage(ImageSource source) async {
  26. if (_isAnalyzing) return;
  27. try {
  28. final file = await _picker.pickImage(source: source, imageQuality: 85, maxWidth: 1280);
  29. if (file != null) {
  30. setState(() => _selectedMedia = file);
  31. _analyzeAndNavigate();
  32. }
  33. } catch (e) {
  34. if (!mounted) return;
  35. ScaffoldMessenger.of(context).showSnackBar(
  36. SnackBar(content: Text("Erreur lors de la sélection de l'image: $e")),
  37. );
  38. }
  39. }
  40. /// Fonction qui analyse l'image et navigue vers l'écran d'amélioration.
  41. Future<void> _analyzeAndNavigate() async {
  42. if (_selectedMedia == null) return;
  43. setState(() => _isAnalyzing = true);
  44. try {
  45. final imageFile = File(_selectedMedia!.path);
  46. final imageBytes = await imageFile.readAsBytes();
  47. final imageBase64 = base64Encode(imageBytes);
  48. // On utilise la méthode d'analyse directement depuis le repository.
  49. final ImageAnalysisResult analysisResult = await _aiRepository.analyzeImage(imageBase64);
  50. final String prompt = analysisResult.prompt;
  51. final List<String> filterIds = analysisResult.filterIds;
  52. if (!mounted) return;
  53. final screenArguments = AiEnhancementScreenArguments(
  54. image: imageFile,
  55. initialPrompt: prompt,
  56. suggestedFilterIds: filterIds,
  57. aiRepository: _aiRepository,
  58. );
  59. Navigator.pushNamed(
  60. context,
  61. AppRoutes.aiEnhancement,
  62. arguments: screenArguments,
  63. );
  64. } catch (e) {
  65. if (!mounted) return;
  66. ScaffoldMessenger.of(context).showSnackBar(
  67. SnackBar(content: Text("Erreur lors de l'analyse de l'image : $e")),
  68. );
  69. } finally {
  70. if (mounted) {
  71. setState(() => _isAnalyzing = false);
  72. }
  73. }
  74. }
  75. @override
  76. Widget build(BuildContext context) {
  77. // Le code du Widget build reste inchangé
  78. return Scaffold(
  79. appBar: AppBar(title: const Text('1. Choisir une Image')),
  80. body: Stack(
  81. children: [
  82. SafeArea(
  83. child: Column(
  84. crossAxisAlignment: CrossAxisAlignment.stretch,
  85. children: [
  86. Expanded(
  87. child: Center(
  88. child: Padding(
  89. padding: const EdgeInsets.all(24),
  90. child: Column(
  91. mainAxisSize: MainAxisSize.min,
  92. crossAxisAlignment: CrossAxisAlignment.stretch,
  93. children: [
  94. const Icon(Icons.camera_enhance, size: 80, color: Colors.grey),
  95. const SizedBox(height: 24),
  96. Text(
  97. 'Choisissez une image pour commencer',
  98. style: Theme.of(context).textTheme.headlineSmall,
  99. textAlign: TextAlign.center,
  100. ),
  101. const SizedBox(height: 48),
  102. FilledButton.icon(
  103. onPressed: _isAnalyzing ? null : () => _pickImage(ImageSource.gallery),
  104. icon: const Icon(Icons.photo_library_outlined),
  105. label: const Text('Importer depuis la galerie'),
  106. style: FilledButton.styleFrom(padding: const EdgeInsets.symmetric(vertical: 12)),
  107. ),
  108. const SizedBox(height: 12),
  109. OutlinedButton.icon(
  110. onPressed: _isAnalyzing ? null : () => _pickImage(ImageSource.camera),
  111. icon: const Icon(Icons.camera_alt_outlined),
  112. label: const Text('Prendre une photo'),
  113. style: OutlinedButton.styleFrom(padding: const EdgeInsets.symmetric(vertical: 12)),
  114. ),
  115. ],
  116. ),
  117. ),
  118. ),
  119. ),
  120. ],
  121. ),
  122. ),
  123. if (_isAnalyzing)
  124. Container(
  125. color: Colors.black.withOpacity(0.5),
  126. child: const Center(
  127. child: Column(
  128. mainAxisSize: MainAxisSize.min,
  129. children: [
  130. CircularProgressIndicator(),
  131. SizedBox(height: 16),
  132. Text("Analyse de l'image...", style: TextStyle(color: Colors.white, fontSize: 16)),
  133. ],
  134. ),
  135. ),
  136. ),
  137. ],
  138. ),
  139. );
  140. }
  141. }