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

@@ -1,9 +1,218 @@
import 'package:equatable/equatable.dart';
/// Classe de base abstraite pour toutes les erreurs de l'application.
///
/// Les [Failure] représentent des erreurs métier qui peuvent être gérées
/// de manière élégante par l'application, contrairement aux [Exception]
/// qui sont des erreurs techniques.
///
/// **Usage:**
/// ```dart
/// try {
/// final result = await repository.getData();
/// return Right(result);
/// } catch (e) {
/// return Left(ServerFailure(message: e.toString()));
/// }
/// ```
abstract class Failure extends Equatable {
/// Crée une nouvelle [Failure].
///
/// [message] Un message optionnel décrivant l'erreur
/// [code] Un code d'erreur optionnel
const Failure({
this.message = 'Une erreur est survenue',
this.code,
});
/// Message décrivant l'erreur
final String message;
/// Code d'erreur optionnel
final String? code;
@override
List<Object> get props => [];
List<Object?> get props => [message, code];
@override
String toString() => 'Failure(message: $message, code: $code)';
}
class ServerFailure extends Failure {}
class CacheFailure extends Failure {}
/// Erreur liée au serveur ou à la communication réseau.
///
/// Cette erreur est levée lorsque :
/// - Une requête HTTP échoue
/// - Le serveur retourne une erreur
/// - La connexion réseau est perdue
/// - Un timeout se produit
///
/// **Exemple:**
/// ```dart
/// try {
/// final response = await http.get(url);
/// if (response.statusCode != 200) {
/// throw ServerFailure(
/// message: 'Erreur serveur: ${response.statusCode}',
/// code: response.statusCode.toString(),
/// );
/// }
/// } catch (e) {
/// throw ServerFailure(message: e.toString());
/// }
/// ```
class ServerFailure extends Failure {
/// Crée une nouvelle [ServerFailure].
///
/// [message] Message décrivant l'erreur serveur
/// [code] Code d'erreur HTTP optionnel
/// [statusCode] Code de statut HTTP optionnel
const ServerFailure({
super.message = 'Erreur serveur',
super.code,
this.statusCode,
});
/// Code de statut HTTP (404, 500, etc.)
final int? statusCode;
@override
List<Object?> get props => [...super.props, statusCode];
@override
String toString() =>
'ServerFailure(message: $message, code: $code, statusCode: $statusCode)';
}
/// Erreur liée au cache local.
///
/// Cette erreur est levée lorsque :
/// - Les données ne peuvent pas être lues depuis le cache
/// - Les données ne peuvent pas être écrites dans le cache
/// - Le cache est corrompu ou inaccessible
///
/// **Exemple:**
/// ```dart
/// try {
/// final cachedData = await cache.get(key);
/// if (cachedData == null) {
/// throw CacheFailure(message: 'Données non trouvées dans le cache');
/// }
/// } catch (e) {
/// throw CacheFailure(message: e.toString());
/// }
/// ```
class CacheFailure extends Failure {
/// Crée une nouvelle [CacheFailure].
///
/// [message] Message décrivant l'erreur de cache
/// [code] Code d'erreur optionnel
const CacheFailure({
super.message = 'Erreur de cache',
super.code,
});
@override
String toString() => 'CacheFailure(message: $message, code: $code)';
}
/// Erreur liée à l'authentification.
///
/// Cette erreur est levée lorsque :
/// - Les identifiants sont incorrects
/// - Le token d'authentification est expiré
/// - L'utilisateur n'est pas autorisé
///
/// **Exemple:**
/// ```dart
/// if (!isAuthenticated) {
/// throw AuthenticationFailure(
/// message: 'Authentification requise',
/// );
/// }
/// ```
class AuthenticationFailure extends Failure {
/// Crée une nouvelle [AuthenticationFailure].
///
/// [message] Message décrivant l'erreur d'authentification
/// [code] Code d'erreur optionnel
const AuthenticationFailure({
super.message = 'Erreur d\'authentification',
super.code,
});
@override
String toString() =>
'AuthenticationFailure(message: $message, code: $code)';
}
/// Erreur liée à la validation des données.
///
/// Cette erreur est levée lorsque :
/// - Les données saisies sont invalides
/// - Les données ne respectent pas les contraintes
/// - Les données sont manquantes
///
/// **Exemple:**
/// ```dart
/// if (email.isEmpty || !isValidEmail(email)) {
/// throw ValidationFailure(
/// message: 'Email invalide',
/// field: 'email',
/// );
/// }
/// ```
class ValidationFailure extends Failure {
/// Crée une nouvelle [ValidationFailure].
///
/// [message] Message décrivant l'erreur de validation
/// [field] Le champ qui a échoué la validation
/// [code] Code d'erreur optionnel
const ValidationFailure({
super.message = 'Erreur de validation',
this.field,
super.code,
});
/// Le champ qui a échoué la validation
final String? field;
@override
List<Object?> get props => [super.props, field];
@override
String toString() =>
'ValidationFailure(message: $message, field: $field, code: $code)';
}
/// Erreur liée à une opération réseau.
///
/// Cette erreur est levée lorsque :
/// - La connexion Internet est perdue
/// - Le timeout est dépassé
/// - La connexion est refusée
///
/// **Exemple:**
/// ```dart
/// try {
/// final response = await http.get(url).timeout(
/// const Duration(seconds: 5),
/// );
/// } on TimeoutException {
/// throw NetworkFailure(message: 'Timeout de connexion');
/// } on SocketException {
/// throw NetworkFailure(message: 'Pas de connexion Internet');
/// }
/// ```
class NetworkFailure extends Failure {
/// Crée une nouvelle [NetworkFailure].
///
/// [message] Message décrivant l'erreur réseau
/// [code] Code d'erreur optionnel
const NetworkFailure({
super.message = 'Erreur réseau',
super.code,
});
@override
String toString() => 'NetworkFailure(message: $message, code: $code)';
}