128 lines
		
	
	
		
			4.1 KiB
		
	
	
	
		
			Dart
		
	
	
	
	
	
			
		
		
	
	
			128 lines
		
	
	
		
			4.1 KiB
		
	
	
	
		
			Dart
		
	
	
	
	
	
| import 'package:flutter/material.dart';
 | |
| import 'package:cloud_firestore/cloud_firestore.dart';
 | |
| 
 | |
| class ProfilePictureWidget extends StatefulWidget {
 | |
|   final String? userId;
 | |
|   final double radius;
 | |
|   final String? defaultImageUrl;
 | |
| 
 | |
|   const ProfilePictureWidget({
 | |
|     super.key,
 | |
|     required this.userId,
 | |
|     this.radius = 25,
 | |
|     this.defaultImageUrl,
 | |
|   });
 | |
| 
 | |
|   @override
 | |
|   State<ProfilePictureWidget> createState() => _ProfilePictureWidgetState();
 | |
| }
 | |
| 
 | |
| class _ProfilePictureWidgetState extends State<ProfilePictureWidget> {
 | |
|   late Future<DocumentSnapshot?> _userFuture;
 | |
| 
 | |
|   @override
 | |
|   void initState() {
 | |
|     super.initState();
 | |
|     _userFuture = _getUserFuture();
 | |
|   }
 | |
| 
 | |
|   @override
 | |
|   void didUpdateWidget(ProfilePictureWidget oldWidget) {
 | |
|     super.didUpdateWidget(oldWidget);
 | |
|     if (oldWidget.userId != widget.userId) {
 | |
|       _userFuture = _getUserFuture();
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   Future<DocumentSnapshot?> _getUserFuture() {
 | |
|     if (widget.userId == null || widget.userId!.isEmpty) {
 | |
|       return Future.value(null);
 | |
|     }
 | |
|     return FirebaseFirestore.instance
 | |
|         .collection('users')
 | |
|         .doc(widget.userId)
 | |
|         .get();
 | |
|   }
 | |
| 
 | |
|   @override
 | |
|   Widget build(BuildContext context) {
 | |
|     if (widget.userId == null || widget.userId!.isEmpty) {
 | |
|       return _buildDefaultAvatar(widget.radius, widget.defaultImageUrl);
 | |
|     }
 | |
| 
 | |
|     return FutureBuilder<DocumentSnapshot?>(
 | |
|       future: _userFuture,
 | |
|       builder: (context, snapshot) {
 | |
|         if (snapshot.connectionState == ConnectionState.waiting) {
 | |
|           return _buildLoadingAvatar(widget.radius);
 | |
|         } else if (snapshot.hasError) {
 | |
|           print("Error loading profile: ${snapshot.error}");
 | |
|           return _buildDefaultAvatar(widget.radius, widget.defaultImageUrl);
 | |
|         } else if (snapshot.data != null && snapshot.data!.exists) {
 | |
|           final userData = snapshot.data!.data() as Map<String, dynamic>?;
 | |
|           final profilePhotoUrl = userData?['profilePhotoUrl'] as String?;
 | |
| 
 | |
|           if (profilePhotoUrl != null && profilePhotoUrl.isNotEmpty) {
 | |
|             return CircleAvatar(
 | |
|               radius: widget.radius,
 | |
|               backgroundImage: NetworkImage(profilePhotoUrl),
 | |
|               onBackgroundImageError: (e, stack) {
 | |
|                 print("Error loading profile image: $e");
 | |
|               },
 | |
|             );
 | |
|           }
 | |
|         }
 | |
|         return _buildDefaultAvatar(widget.radius, widget.defaultImageUrl);
 | |
|       },
 | |
|     );
 | |
|   }
 | |
| 
 | |
|   // Widget utilitaire pour construire un CircleAvatar de chargement
 | |
|   Widget _buildLoadingAvatar(double radius) {
 | |
|     return CircleAvatar(
 | |
|       radius: radius,
 | |
|       backgroundColor:
 | |
|           Colors.grey[300], // Couleur de fond pendant le chargement
 | |
|       child: SizedBox(
 | |
|         width: radius * 0.8, // Ajuster la taille du loader
 | |
|         height: radius * 0.8,
 | |
|         child: const CircularProgressIndicator(
 | |
|             strokeWidth: 2), // Indicateur de chargement
 | |
|       ),
 | |
|     );
 | |
|   }
 | |
| 
 | |
|   // Widget utilitaire pour construire un CircleAvatar par défaut (avec icône ou image par défaut)
 | |
|   Widget _buildDefaultAvatar(double radius, String? defaultImageUrl) {
 | |
|     if (defaultImageUrl != null && defaultImageUrl.isNotEmpty) {
 | |
|       return CircleAvatar(
 | |
|         radius: radius,
 | |
|         // Utilisation de Image.network pour l'image par défaut, avec gestion d'erreur similaire
 | |
|         backgroundImage: Image.network(
 | |
|           defaultImageUrl,
 | |
|           errorBuilder: (context, error, stackTrace) {
 | |
|             print(
 | |
|                 "Erreur de chargement Image.network pour l'URL par défaut: $defaultImageUrl, Erreur: $error");
 | |
|             return _buildIconAvatar(
 | |
|                 radius); // Si l'image par défaut ne charge pas, afficher l'icône
 | |
|           },
 | |
|         ).image, // .image pour ImageProvider
 | |
|       );
 | |
|     } else {
 | |
|       return _buildIconAvatar(
 | |
|           radius); // Si pas d'URL par défaut fournie, afficher l'icône
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   // Widget utilitaire pour construire un CircleAvatar avec une icône par défaut
 | |
|   Widget _buildIconAvatar(double radius) {
 | |
|     return CircleAvatar(
 | |
|       radius: radius,
 | |
|       child: FittedBox(
 | |
|         fit: BoxFit.scaleDown,
 | |
|         child: Icon(Icons.account_circle, size: radius * 1.5),
 | |
|       ),
 | |
|     );
 | |
|   }
 | |
| }
 |