- Implemented TripImageService to load missing images for trips, reload images, and clean up unused images. - Added functionality to get image statistics and clean up duplicate images. - Created utility scripts for manual image cleanup and diagnostics in Firebase Storage. - Introduced tests for image loading optimization and photo quality algorithms. - Updated dependencies in pubspec.yaml and pubspec.lock for image handling.
150 lines
5.2 KiB
Dart
150 lines
5.2 KiB
Dart
import 'package:travel_mate/models/trip.dart';
|
|
import 'package:travel_mate/services/place_image_service.dart';
|
|
import 'package:travel_mate/repositories/trip_repository.dart';
|
|
import 'package:travel_mate/services/error_service.dart';
|
|
|
|
/// Service pour gérer le chargement automatique des images des voyages
|
|
class TripImageService {
|
|
final PlaceImageService _placeImageService = PlaceImageService();
|
|
final TripRepository _tripRepository = TripRepository();
|
|
final ErrorService _errorService = ErrorService();
|
|
|
|
/// Charge les images manquantes pour une liste de voyages
|
|
Future<void> loadMissingImages(List<Trip> trips) async {
|
|
final tripsWithoutImage = trips.where(
|
|
(trip) => trip.imageUrl == null || trip.imageUrl!.isEmpty
|
|
).toList();
|
|
|
|
if (tripsWithoutImage.isEmpty) {
|
|
return;
|
|
}
|
|
for (final trip in tripsWithoutImage) {
|
|
try {
|
|
await _loadImageForTrip(trip);
|
|
|
|
// Petite pause entre les requêtes pour éviter de surcharger l'API
|
|
await Future.delayed(const Duration(milliseconds: 500));
|
|
} catch (e) {
|
|
_errorService.logError(
|
|
'TripImageService',
|
|
'Erreur lors du chargement d\'image pour ${trip.title}: $e',
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Charge l'image pour un voyage spécifique
|
|
Future<void> _loadImageForTrip(Trip trip) async {
|
|
print('TripImageService: Recherche d\'image pour ${trip.title} (${trip.location})');
|
|
|
|
// D'abord vérifier si une image existe déjà dans le Storage
|
|
String? imageUrl = await _placeImageService.getExistingImageUrl(trip.location);
|
|
|
|
// Si aucune image n'existe, en télécharger une nouvelle
|
|
if (imageUrl == null) {
|
|
print('TripImageService: Aucune image existante, téléchargement via Google Places...');
|
|
imageUrl = await _placeImageService.getPlaceImageUrl(trip.location);
|
|
}
|
|
|
|
if (imageUrl != null && trip.id != null) {
|
|
// Mettre à jour le voyage avec l'image (existante ou nouvelle)
|
|
final updatedTrip = trip.copyWith(
|
|
imageUrl: imageUrl,
|
|
updatedAt: DateTime.now(),
|
|
);
|
|
|
|
await _tripRepository.updateTrip(trip.id!, updatedTrip);
|
|
print('TripImageService: Image mise à jour pour ${trip.title}: $imageUrl');
|
|
} else {
|
|
print('TripImageService: Aucune image trouvée pour ${trip.title}');
|
|
}
|
|
}
|
|
|
|
/// Recharge l'image d'un voyage spécifique (force le rechargement)
|
|
Future<String?> reloadImageForTrip(Trip trip) async {
|
|
try {
|
|
final imageUrl = await _placeImageService.getPlaceImageUrl(trip.location);
|
|
|
|
if (imageUrl != null && trip.id != null) {
|
|
final updatedTrip = trip.copyWith(
|
|
imageUrl: imageUrl,
|
|
updatedAt: DateTime.now(),
|
|
);
|
|
|
|
await _tripRepository.updateTrip(trip.id!, updatedTrip);
|
|
return imageUrl;
|
|
}
|
|
|
|
return null;
|
|
} catch (e) {
|
|
_errorService.logError(
|
|
'TripImageService',
|
|
'Erreur lors du rechargement d\'image pour ${trip.title}: $e',
|
|
);
|
|
return null;
|
|
}
|
|
}
|
|
|
|
/// Nettoie les images inutilisées du stockage
|
|
Future<void> cleanupUnusedImages(String userId) async {
|
|
try {
|
|
// Récupérer tous les voyages de l'utilisateur
|
|
final tripsStream = _tripRepository.getTripsByUserId(userId);
|
|
final trips = await tripsStream.first;
|
|
|
|
// Extraire toutes les URLs d'images utilisées
|
|
final usedImageUrls = trips
|
|
.where((trip) => trip.imageUrl != null && trip.imageUrl!.isNotEmpty)
|
|
.map((trip) => trip.imageUrl!)
|
|
.toList();
|
|
|
|
// Nettoyer les images inutilisées
|
|
await _placeImageService.cleanupUnusedImages(usedImageUrls);
|
|
|
|
} catch (e) {
|
|
_errorService.logError(
|
|
'TripImageService',
|
|
'Erreur lors du nettoyage des images: $e',
|
|
);
|
|
}
|
|
}
|
|
|
|
/// Obtient des statistiques sur les images stockées
|
|
Future<Map<String, dynamic>> getImageStatistics(String userId) async {
|
|
try {
|
|
final tripsStream = _tripRepository.getTripsByUserId(userId);
|
|
final trips = await tripsStream.first;
|
|
|
|
final tripsWithImages = trips.where((trip) => trip.imageUrl != null && trip.imageUrl!.isNotEmpty).length;
|
|
final tripsWithoutImages = trips.length - tripsWithImages;
|
|
|
|
return {
|
|
'totalTrips': trips.length,
|
|
'tripsWithImages': tripsWithImages,
|
|
'tripsWithoutImages': tripsWithoutImages,
|
|
'timestamp': DateTime.now().toIso8601String(),
|
|
};
|
|
} catch (e) {
|
|
_errorService.logError('TripImageService', 'Erreur lors de l\'obtention des statistiques: $e');
|
|
return {
|
|
'error': e.toString(),
|
|
'timestamp': DateTime.now().toIso8601String(),
|
|
};
|
|
}
|
|
}
|
|
|
|
/// Nettoie spécifiquement les doublons d'images
|
|
Future<void> cleanupDuplicateImages() async {
|
|
try {
|
|
print('TripImageService: Début du nettoyage des doublons...');
|
|
await _placeImageService.cleanupDuplicateImages();
|
|
print('TripImageService: Nettoyage des doublons terminé');
|
|
} catch (e) {
|
|
print('TripImageService: Erreur lors du nettoyage des doublons: $e');
|
|
_errorService.logError(
|
|
'TripImageService',
|
|
'Erreur lors du nettoyage des doublons: $e',
|
|
);
|
|
}
|
|
}
|
|
} |