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.

148 line
5.2KB

  1. // lib/presentation/screens/media_picker/media_picker_screen.dart
  2. import 'dart:convert'; // <<< NÉCESSAIRE POUR BASE64
  3. import 'dart:io';
  4. import 'package:flutter/material.dart';
  5. import 'package:image_picker/image_picker.dart';
  6. import 'package:social_content_creator/routes/app_routes.dart';
  7. import 'package:social_content_creator/services/image_analysis_service.dart'; // <<< IMPORT CORRECT
  8. class MediaPickerScreen extends StatefulWidget {
  9. const MediaPickerScreen({super.key});
  10. @override
  11. State<MediaPickerScreen> createState() => _MediaPickerScreenState();
  12. }
  13. class _MediaPickerScreenState extends State<MediaPickerScreen> {
  14. final _picker = ImagePicker();
  15. XFile? _selectedMedia;
  16. // On instancie la classe CONCRÈTE
  17. final ImageAnalysisService _analysisService = OllamaImageAnalysisService();
  18. bool _isAnalyzing = false;
  19. Future<void> _pickImage(ImageSource source) async {
  20. try {
  21. final file = await _picker.pickImage(source: source, imageQuality: 85, maxWidth: 1280);
  22. if (file != null) {
  23. setState(() => _selectedMedia = file);
  24. _analyzeAndNavigate();
  25. }
  26. } catch (e) {
  27. if (!mounted) return;
  28. ScaffoldMessenger.of(context).showSnackBar(
  29. SnackBar(content: Text("Erreur lors de la sélection de l'image: $e")),
  30. );
  31. }
  32. }
  33. /// Fonction qui analyse l'image et navigue vers l'écran suivant.
  34. Future<void> _analyzeAndNavigate() async {
  35. if (_selectedMedia == null) return;
  36. setState(() => _isAnalyzing = true);
  37. try {
  38. final imageFile = File(_selectedMedia!.path);
  39. // --- CORRECTION APPLIQUÉE ICI ---
  40. // 1. Convertir l'image en base64, comme attendu par le service.
  41. final imageBytes = await imageFile.readAsBytes();
  42. final String imageBase64 = base64Encode(imageBytes);
  43. // 2. Appeler la bonne méthode (`analyzeImage`) avec le bon argument (`base64Image`).
  44. final String imagePrompt = await _analysisService.analyzeImage(imageBase64);
  45. // --- FIN DE LA CORRECTION ---
  46. if (!mounted) return;
  47. // 3. Navigation avec l'image et le prompt
  48. Navigator.pushNamed(
  49. context,
  50. AppRoutes.aiEnhancement,
  51. arguments: <String, dynamic>{
  52. 'image': imageFile,
  53. 'prompt': imagePrompt,
  54. },
  55. );
  56. } catch (e) {
  57. if (!mounted) return;
  58. ScaffoldMessenger.of(context).showSnackBar(
  59. SnackBar(content: Text("Erreur lors de l'analyse de l'image : $e")),
  60. );
  61. } finally {
  62. if (mounted) {
  63. setState(() => _isAnalyzing = false);
  64. }
  65. }
  66. }
  67. @override
  68. Widget build(BuildContext context) {
  69. return Scaffold(
  70. appBar: AppBar(title: const Text('1. Choisir une Image')),
  71. body: Stack(
  72. children: [
  73. SafeArea(
  74. child: Column(
  75. crossAxisAlignment: CrossAxisAlignment.stretch,
  76. children: [
  77. Expanded(
  78. child: Center(
  79. child: Padding(
  80. padding: const EdgeInsets.all(24.0),
  81. child: Column(
  82. mainAxisSize: MainAxisSize.min,
  83. crossAxisAlignment: CrossAxisAlignment.stretch,
  84. children: [
  85. const Icon(Icons.camera_enhance, size: 80, color: Colors.grey),
  86. const SizedBox(height: 24),
  87. Text(
  88. "Choisissez une image pour commencer",
  89. style: Theme.of(context).textTheme.headlineSmall,
  90. textAlign: TextAlign.center,
  91. ),
  92. const SizedBox(height: 48),
  93. FilledButton.icon(
  94. onPressed: _isAnalyzing ? null : () => _pickImage(ImageSource.gallery),
  95. icon: const Icon(Icons.photo_library_outlined),
  96. label: const Text('Importer depuis la galerie'),
  97. style: FilledButton.styleFrom(padding: const EdgeInsets.symmetric(vertical: 12)),
  98. ),
  99. const SizedBox(height: 12),
  100. OutlinedButton.icon(
  101. onPressed: _isAnalyzing ? null : () => _pickImage(ImageSource.camera),
  102. icon: const Icon(Icons.camera_alt_outlined),
  103. label: const Text('Prendre une photo'),
  104. style: OutlinedButton.styleFrom(padding: const EdgeInsets.symmetric(vertical: 12)),
  105. ),
  106. ],
  107. ),
  108. ),
  109. ),
  110. ),
  111. ],
  112. ),
  113. ),
  114. if (_isAnalyzing)
  115. Container(
  116. color: Colors.black.withOpacity(0.5),
  117. child: const Center(
  118. child: Column(
  119. mainAxisSize: MainAxisSize.min,
  120. children: [
  121. CircularProgressIndicator(),
  122. SizedBox(height: 16),
  123. Text("Analyse de l'image...", style: TextStyle(color: Colors.white, fontSize: 16)),
  124. ],
  125. ),
  126. ),
  127. ),
  128. ],
  129. ),
  130. );
  131. }
  132. }