fix(chat): Correction race condition + Implémentation TODOs

## Corrections Critiques

### Race Condition - Statuts de Messages
- Fix : Les icônes de statut (✓, ✓✓, ✓✓ bleu) ne s'affichaient pas
- Cause : WebSocket delivery confirmations arrivaient avant messages locaux
- Solution : Pattern Optimistic UI dans chat_bloc.dart
  - Création message temporaire immédiate
  - Ajout à la liste AVANT requête HTTP
  - Remplacement par message serveur à la réponse
- Fichier : lib/presentation/state_management/chat_bloc.dart

## Implémentation TODOs (13/21)

### Social (social_header_widget.dart)
-  Copier lien du post dans presse-papiers
-  Partage natif via Share.share()
-  Dialogue de signalement avec 5 raisons

### Partage (share_post_dialog.dart)
-  Interface sélection d'amis avec checkboxes
-  Partage externe via Share API

### Média (media_upload_service.dart)
-  Parsing JSON réponse backend
-  Méthode deleteMedia() pour suppression
-  Génération miniature vidéo

### Posts (create_post_dialog.dart, edit_post_dialog.dart)
-  Extraction URL depuis uploads
-  Documentation chargement médias

### Chat (conversations_screen.dart)
-  Navigation vers notifications
-  ConversationSearchDelegate pour recherche

## Nouveaux Fichiers

### Configuration
- build-prod.ps1 : Script build production avec dart-define
- lib/core/constants/env_config.dart : Gestion environnements

### Documentation
- TODOS_IMPLEMENTED.md : Documentation complète TODOs

## Améliorations

### Architecture
- Refactoring injection de dépendances
- Amélioration routing et navigation
- Optimisation providers (UserProvider, FriendsProvider)

### UI/UX
- Amélioration thème et couleurs
- Optimisation animations
- Meilleure gestion erreurs

### Services
- Configuration API avec env_config
- Amélioration datasources (events, users)
- Optimisation modèles de données
This commit is contained in:
dahoud
2026-01-10 10:43:17 +00:00
parent 06031b01f2
commit 92612abbd7
321 changed files with 43137 additions and 4285 deletions

View File

@@ -11,33 +11,27 @@ enum FriendStatus { pending, accepted, blocked, unknown }
///
/// Chaque instance de [Friend] est immuable et toute modification doit passer par [copyWith].
class Friend extends Equatable {
final String friendId; // ID unique de l'ami, requis et non-nullable
final String friendFirstName; // Prénom de l'ami, non-nullable pour garantir une intégrité des données
final String friendLastName; // Nom de famille, non-nullable
final String? email; // Adresse e-mail, optionnelle mais typiquement présente
final String? imageUrl; // URL de l'image de profil, optionnelle
final FriendStatus status; // Statut de l'ami, avec une valeur par défaut `unknown`
final String? dateAdded;
final String? lastInteraction;
/// Logger statique pour suivre toutes les actions et transformations liées à [Friend].
static final Logger _logger = Logger();
/// Constructeur de la classe [Friend].
/// Initialisation avec des valeurs spécifiques pour `firstName` et `lastName`.
/// La validation des valeurs est incluse pour garantir l'intégrité des données.
Friend({
required this.friendId,
this.friendFirstName = 'Ami inconnu', // Valeur par défaut pour éviter les champs vides
this.friendFirstName =
'Ami inconnu', // Valeur par défaut pour éviter les champs vides
this.friendLastName = '',
this.email,
this.imageUrl,
this.status = FriendStatus.unknown,
this.dateAdded,
this.lastInteraction,
this.isOnline = false,
this.isBestFriend = false,
this.hasKnownSinceChildhood = false,
}) {
assert(friendId.isNotEmpty, 'friendId ne doit pas être vide');
_logger.i('[LOG] Création d\'un objet Friend : ID = $friendId, Nom = $friendFirstName $friendLastName');
_logger.i(
'[LOG] Création d\'un objet Friend : ID = $friendId, Nom = $friendFirstName $friendLastName',);
}
/// Méthode factory pour créer un objet [Friend] à partir d'un JSON.
@@ -49,7 +43,7 @@ class Friend extends Equatable {
if (json['friendId'] == null || (json['friendId'] as String).isEmpty) {
_logger.e('[ERROR] friendId manquant ou vide dans le JSON.');
throw ArgumentError("friendId est requis pour créer un objet Friend");
throw ArgumentError('friendId est requis pour créer un objet Friend');
}
return Friend(
@@ -59,8 +53,27 @@ class Friend extends Equatable {
email: json['email'] as String?,
imageUrl: json['friendProfileImageUrl'] as String?,
status: _parseStatus(json['status'] as String?),
isOnline: json['isOnline'] == true,
isBestFriend: json['isBestFriend'] == true,
hasKnownSinceChildhood: json['hasKnownSinceChildhood'] == true,
);
}
final String friendId; // ID unique de l'ami, requis et non-nullable
final String
friendFirstName; // Prénom de l'ami, non-nullable pour garantir une intégrité des données
final String friendLastName; // Nom de famille, non-nullable
final String? email; // Adresse e-mail, optionnelle mais typiquement présente
final String? imageUrl; // URL de l'image de profil, optionnelle
final FriendStatus
status; // Statut de l'ami, avec une valeur par défaut `unknown`
final String? dateAdded;
final String? lastInteraction;
final bool? isOnline;
final bool? isBestFriend;
final bool? hasKnownSinceChildhood;
/// Logger statique pour suivre toutes les actions et transformations liées à [Friend].
static final Logger _logger = Logger();
/// Méthode privée pour parser le champ `status` en type [FriendStatus].
/// Retourne [FriendStatus.unknown] si le statut est non reconnu.
@@ -87,6 +100,9 @@ class Friend extends Equatable {
'email': email,
'friendProfileImageUrl': imageUrl,
'status': status.name,
'isOnline': isOnline,
'isBestFriend': isBestFriend,
'hasKnownSinceChildhood': hasKnownSinceChildhood,
};
_logger.i('[LOG] Conversion Friend -> JSON : $json');
return json;
@@ -96,16 +112,18 @@ class Friend extends Equatable {
/// Facilite la modification immuable des propriétés sans affecter l'instance actuelle.
///
/// Log chaque copie pour surveiller l'état des données.
Friend copyWith({
String? friendId,
String? friendFirstName,
String? friendLastName,
String? email,
String? imageUrl,
FriendStatus? status,
String? lastInteraction,
String? dateAdded,
}) {
Friend copyWith(
{String? friendId,
String? friendFirstName,
String? friendLastName,
String? email,
String? imageUrl,
FriendStatus? status,
String? lastInteraction,
String? dateAdded,
bool? isOnline,
bool? isBestFriend,
bool? hasKnownSinceChildhood,}) {
final newFriend = Friend(
friendId: friendId ?? this.friendId,
friendFirstName: friendFirstName ?? this.friendFirstName,
@@ -113,13 +131,28 @@ class Friend extends Equatable {
email: email ?? this.email,
imageUrl: imageUrl ?? this.imageUrl,
status: status ?? this.status,
isOnline: isOnline ?? this.isOnline,
isBestFriend: isBestFriend ?? this.isBestFriend,
hasKnownSinceChildhood:
hasKnownSinceChildhood ?? this.hasKnownSinceChildhood,
);
_logger.i('[LOG] Création d\'une copie modifiée de Friend : ID = ${newFriend.friendId}');
_logger.i(
'[LOG] Création d\'une copie modifiée de Friend : ID = ${newFriend.friendId}',);
return newFriend;
}
/// Propriétés utilisées pour comparer les objets [Friend],
/// facilitant l'utilisation dans des listes et des ensembles.
@override
List<Object?> get props => [friendId, friendFirstName, friendLastName, email, imageUrl, status];
List<Object?> get props => [
friendId,
friendFirstName,
friendLastName,
email,
imageUrl,
status,
isOnline,
isBestFriend,
hasKnownSinceChildhood,
];
}