Refactoring + Checkpoint
This commit is contained in:
@@ -1,42 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import '../../widgets/friend_card.dart';
|
||||
import '../../widgets/friend_detail_screen.dart';
|
||||
|
||||
class FriendsContent extends StatelessWidget {
|
||||
final List<Map<String, String>> friends = [
|
||||
{'name': 'Alice', 'imageUrl': 'https://example.com/image1.jpg'},
|
||||
{'name': 'Bob', 'imageUrl': 'https://example.com/image2.jpg'},
|
||||
{'name': 'Charlie', 'imageUrl': 'https://example.com/image3.jpg'},
|
||||
// Autres amis...
|
||||
];
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return ListView.builder(
|
||||
padding: const EdgeInsets.symmetric(vertical: 10.0, horizontal: 16.0),
|
||||
itemCount: friends.length,
|
||||
itemBuilder: (context, index) {
|
||||
final friend = friends[index];
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 10.0),
|
||||
child: FriendCard(
|
||||
name: friend['name']!,
|
||||
imageUrl: friend['imageUrl']!,
|
||||
onTap: () => _navigateToFriendDetail(context, friend),
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
void _navigateToFriendDetail(BuildContext context, Map<String, String> friend) {
|
||||
Navigator.of(context).push(MaterialPageRoute(
|
||||
builder: (context) => FriendDetailScreen(
|
||||
name: friend['name']!,
|
||||
imageUrl: friend['imageUrl']!,
|
||||
friendId: friend['friendId']!,
|
||||
),
|
||||
));
|
||||
}
|
||||
}
|
||||
@@ -1,12 +1,13 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import '../../../data/providers/friends_provider.dart';
|
||||
import '../../../domain/entities/friend.dart';
|
||||
import '../../widgets/friend_detail_screen.dart';
|
||||
import '../../widgets/friends_circle.dart';
|
||||
import '../../widgets/search_friends.dart';
|
||||
|
||||
/// [FriendsScreen] est l'écran principal permettant d'afficher et de gérer la liste des amis.
|
||||
/// Il inclut des fonctionnalités de pagination, de recherche, et de rafraîchissement manuel de la liste.
|
||||
/// Ce widget est un [StatefulWidget] afin de pouvoir mettre à jour dynamiquement la liste des amis.
|
||||
class FriendsScreen extends StatefulWidget {
|
||||
final String userId; // Identifiant de l'utilisateur pour récupérer ses amis
|
||||
|
||||
@@ -28,7 +29,7 @@ class _FriendsScreenState extends State<FriendsScreen> {
|
||||
|
||||
// Log pour indiquer le début du chargement des amis
|
||||
debugPrint("[LOG] Initialisation de la page : chargement des amis pour l'utilisateur ${widget.userId}");
|
||||
// Chargement initial de la liste d'amis
|
||||
// Chargement initial de la liste d'amis via le fournisseur (Provider)
|
||||
Provider.of<FriendsProvider>(context, listen: false).fetchFriends(widget.userId);
|
||||
}
|
||||
|
||||
@@ -46,12 +47,12 @@ class _FriendsScreenState extends State<FriendsScreen> {
|
||||
void _onScroll() {
|
||||
final provider = Provider.of<FriendsProvider>(context, listen: false);
|
||||
|
||||
// Ajout d'une marge de 200 pixels pour détecter le bas de la liste plus tôt
|
||||
// Ajout d'une marge de 200 pixels pour détecter le bas de la liste plus tôt.
|
||||
if (_scrollController.position.pixels >=
|
||||
_scrollController.position.maxScrollExtent - 200 &&
|
||||
!provider.isLoading && provider.hasMore) {
|
||||
debugPrint("[LOG] Scroll : Fin de liste atteinte, chargement de la page suivante.");
|
||||
provider.fetchFriends(widget.userId, loadMore: true);
|
||||
provider.fetchFriends(widget.userId, loadMore: true); // Chargement de plus d'amis
|
||||
}
|
||||
}
|
||||
|
||||
@@ -64,9 +65,11 @@ class _FriendsScreenState extends State<FriendsScreen> {
|
||||
appBar: AppBar(
|
||||
title: const Text('Mes Amis'),
|
||||
actions: [
|
||||
// Bouton pour rafraîchir la liste des amis
|
||||
IconButton(
|
||||
icon: const Icon(Icons.refresh),
|
||||
onPressed: () {
|
||||
// Vérifie si la liste n'est pas en cours de chargement avant d'envoyer une nouvelle requête.
|
||||
if (!friendsProvider.isLoading) {
|
||||
debugPrint("[LOG] Bouton Refresh : demande de rafraîchissement de la liste des amis");
|
||||
friendsProvider.fetchFriends(widget.userId);
|
||||
@@ -80,13 +83,13 @@ class _FriendsScreenState extends State<FriendsScreen> {
|
||||
body: SafeArea(
|
||||
child: Column(
|
||||
children: [
|
||||
// Widget de recherche d'amis en haut de l'écran
|
||||
const Padding(
|
||||
padding: EdgeInsets.all(8.0),
|
||||
// Widget pour la recherche d'amis
|
||||
child: SearchFriends(),
|
||||
),
|
||||
Expanded(
|
||||
// Construction de la liste d'amis basée sur l'état du FriendsProvider
|
||||
// Construction de la liste d'amis avec un affichage en grille
|
||||
child: Consumer<FriendsProvider>(
|
||||
builder: (context, friendsProvider, child) {
|
||||
// Si le chargement est en cours et qu'il n'y a aucun ami, afficher un indicateur de chargement.
|
||||
@@ -103,40 +106,69 @@ class _FriendsScreenState extends State<FriendsScreen> {
|
||||
);
|
||||
}
|
||||
|
||||
// Affichage de la grille des amis
|
||||
debugPrint("[LOG] Affichage de la grille des amis (nombre d'amis : ${friendsProvider.friendsList.length})");
|
||||
|
||||
return GridView.builder(
|
||||
controller: _scrollController,
|
||||
padding: const EdgeInsets.all(16),
|
||||
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
|
||||
crossAxisCount: 3,
|
||||
mainAxisSpacing: 10,
|
||||
controller: _scrollController, // Utilisation du contrôleur pour la pagination
|
||||
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
|
||||
crossAxisCount: 2, // Deux amis par ligne
|
||||
crossAxisSpacing: 10,
|
||||
mainAxisSpacing: 10,
|
||||
childAspectRatio: 0.8, // Ajuste la taille des cartes
|
||||
),
|
||||
itemCount: friendsProvider.friendsList.length + (friendsProvider.isLoading && friendsProvider.hasMore ? 1 : 0),
|
||||
itemCount: friendsProvider.friendsList.length,
|
||||
itemBuilder: (context, index) {
|
||||
if (index >= friendsProvider.friendsList.length) {
|
||||
return const Center(child: CircularProgressIndicator());
|
||||
}
|
||||
final friend = friendsProvider.friendsList[index];
|
||||
debugPrint("[LOG] Affichage de l'ami à l'index $index avec ID : ${friend.friendId}");
|
||||
|
||||
return FriendsCircle(
|
||||
friend: friend,
|
||||
onTap: () {
|
||||
debugPrint("[LOG] Détail : Affichage des détails de l'ami ID : ${friend.friendId}");
|
||||
FriendDetailScreen.open(
|
||||
context,
|
||||
friend.friendId,
|
||||
friend.friendFirstName,
|
||||
friend.imageUrl ?? '',
|
||||
);
|
||||
},
|
||||
// Affichage de chaque ami dans une carte avec une animation
|
||||
return GestureDetector(
|
||||
onTap: () => _navigateToFriendDetail(context, friend), // Action au clic sur l'avatar
|
||||
child: AnimatedContainer(
|
||||
duration: const Duration(milliseconds: 300),
|
||||
curve: Curves.easeInOut,
|
||||
transform: Matrix4.identity()
|
||||
..scale(1.05), // Effet de zoom lors du survol
|
||||
child: Card(
|
||||
elevation: 6,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
CircleAvatar(
|
||||
radius: 50,
|
||||
backgroundImage: friend.imageUrl != null && friend.imageUrl!.isNotEmpty
|
||||
? (friend.imageUrl!.startsWith('https') // Vérifie si l'image est une URL réseau.
|
||||
? NetworkImage(friend.imageUrl!) // Charge l'image depuis une URL réseau.
|
||||
: AssetImage(friend.imageUrl!) as ImageProvider) // Sinon, charge depuis les ressources locales.
|
||||
: const AssetImage('lib/assets/images/default_avatar.png'), // Si aucune image, utilise l'image par défaut.
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
Text(
|
||||
"${friend.friendFirstName} ${friend.friendLastName}",
|
||||
style: const TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: 16,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 5),
|
||||
Text(
|
||||
friend.status.name,
|
||||
style: const TextStyle(fontSize: 14),
|
||||
),
|
||||
const SizedBox(height: 5),
|
||||
Text(
|
||||
friend.lastInteraction ?? 'Aucune interaction récente',
|
||||
style: const TextStyle(
|
||||
fontStyle: FontStyle.italic,
|
||||
fontSize: 12,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
},
|
||||
),
|
||||
),
|
||||
@@ -145,4 +177,24 @@ class _FriendsScreenState extends State<FriendsScreen> {
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/// Navigation vers l'écran de détails de l'ami
|
||||
/// Permet de voir les informations complètes d'un ami lorsque l'utilisateur clique sur son avatar.
|
||||
void _navigateToFriendDetail(BuildContext context, Friend friend) {
|
||||
debugPrint("[LOG] Navigation : Détails de l'ami ${friend.friendFirstName} ${friend.friendLastName}");
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) => FriendDetailScreen(
|
||||
friendFirstName: friend.friendFirstName, // Prénom de l'ami
|
||||
friendLastName: friend.friendLastName, // Nom de l'ami
|
||||
imageUrl: friend.imageUrl ?? '', // URL de l'image de l'ami (ou valeur par défaut)
|
||||
friendId: friend.friendId, // Identifiant unique de l'ami
|
||||
status: friend.status, // Statut de l'ami
|
||||
lastInteraction: friend.lastInteraction ?? 'Aucune', // Dernière interaction (si disponible)
|
||||
dateAdded: friend.dateAdded ?? 'Inconnu', // Date d'ajout de l'ami (si disponible)
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,20 +8,21 @@ import '../../widgets/friend_detail_screen.dart';
|
||||
import '../../widgets/friends_appbar.dart';
|
||||
import '../../widgets/search_friends.dart';
|
||||
|
||||
/// Écran d'affichage des amis avec gestion des amis via un provider.
|
||||
class FriendsScreenWithProvider extends StatelessWidget {
|
||||
final Logger _logger = Logger(); // Logger pour une meilleure traçabilité
|
||||
final Logger _logger = Logger(); // Logger pour la traçabilité détaillée.
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
backgroundColor: Colors.black,
|
||||
appBar: FriendsAppBar(),
|
||||
backgroundColor: Colors.black, // Fond noir pour une ambiance immersive.
|
||||
appBar: FriendsAppBar(), // AppBar personnalisé pour l'écran.
|
||||
body: SafeArea(
|
||||
child: Column(
|
||||
children: [
|
||||
const Padding(
|
||||
padding: EdgeInsets.all(8.0),
|
||||
child: SearchFriends(),
|
||||
child: SearchFriends(), // Barre de recherche pour trouver des amis.
|
||||
),
|
||||
Expanded(
|
||||
child: Consumer<FriendsProvider>(
|
||||
@@ -29,10 +30,10 @@ class FriendsScreenWithProvider extends StatelessWidget {
|
||||
final friends = friendsProvider.friendsList;
|
||||
|
||||
if (friends.isEmpty) {
|
||||
_logger.i("[LOG] Aucun ami trouvé");
|
||||
_logger.i("[LOG] Aucun ami trouvé."); // Log pour la recherche sans résultat.
|
||||
return const Center(
|
||||
child: Text(
|
||||
'Aucun ami trouvé',
|
||||
'Aucun ami trouvé', // Message affiché si aucun ami n'est trouvé.
|
||||
style: TextStyle(color: Colors.white70),
|
||||
),
|
||||
);
|
||||
@@ -43,6 +44,10 @@ class FriendsScreenWithProvider extends StatelessWidget {
|
||||
itemCount: friends.length,
|
||||
itemBuilder: (context, index) {
|
||||
final friend = friends[index];
|
||||
|
||||
// Log lorsque chaque ami est affiché
|
||||
_logger.i("[LOG] Affichage de l'ami : ${friend.friendFirstName ?? 'Ami inconnu'}");
|
||||
|
||||
return Dismissible(
|
||||
key: Key(friend.friendId),
|
||||
background: Container(
|
||||
@@ -53,7 +58,7 @@ class FriendsScreenWithProvider extends StatelessWidget {
|
||||
),
|
||||
onDismissed: (direction) {
|
||||
_logger.i("[LOG] Suppression de l'ami avec l'ID : ${friend.friendId}");
|
||||
friendsProvider.removeFriend(friend.friendId);
|
||||
friendsProvider.removeFriend(friend.friendId); // Suppression de l'ami via le provider.
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(content: Text("Ami supprimé : ${friend.friendFirstName}")),
|
||||
);
|
||||
@@ -61,14 +66,16 @@ class FriendsScreenWithProvider extends StatelessWidget {
|
||||
child: FriendExpandingCard(
|
||||
name: friend.friendFirstName ?? 'Ami inconnu',
|
||||
imageUrl: friend.imageUrl ?? '',
|
||||
description: "Amis depuis ${friend.friendId}",
|
||||
onTap: () => _navigateToFriendDetail(context, friend),
|
||||
description: "Amis depuis ${friend.dateAdded ?? 'Inconnu'}\nStatut : ${friend.status ?? 'Inconnu'}",
|
||||
onTap: () {
|
||||
_navigateToFriendDetail(context, friend); // Navigation vers les détails de l'ami.
|
||||
},
|
||||
onMessageTap: () {
|
||||
_logger.i("[LOG] Envoi d'un message à l'ami : ${friend.friendFirstName ?? 'Ami inconnu'}");
|
||||
},
|
||||
onRemoveTap: () {
|
||||
_logger.i("[LOG] Tentative de suppression de l'ami : ${friend.friendFirstName ?? 'Ami inconnu'}");
|
||||
friendsProvider.removeFriend(friend.friendId);
|
||||
friendsProvider.removeFriend(friend.friendId); // Suppression via le provider.
|
||||
},
|
||||
),
|
||||
);
|
||||
@@ -83,13 +90,19 @@ class FriendsScreenWithProvider extends StatelessWidget {
|
||||
);
|
||||
}
|
||||
|
||||
/// Navigue vers l'écran de détails de l'ami.
|
||||
void _navigateToFriendDetail(BuildContext context, Friend friend) {
|
||||
_logger.i("[LOG] Navigation vers les détails de l'ami : ${friend.friendFirstName}");
|
||||
|
||||
Navigator.of(context).push(MaterialPageRoute(
|
||||
builder: (context) => FriendDetailScreen(
|
||||
name: friend.friendFirstName,
|
||||
imageUrl: friend.imageUrl ?? '',
|
||||
friendId: friend.friendId,
|
||||
friendFirstName: friend.friendFirstName,
|
||||
friendLastName: friend.friendLastName,
|
||||
imageUrl: friend.imageUrl ?? '',
|
||||
status: friend.status,
|
||||
lastInteraction: friend.lastInteraction ?? 'Aucune',
|
||||
dateAdded: friend.dateAdded ?? 'Inconnu',
|
||||
),
|
||||
));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user