Files
afterwork/lib/core/errors/exceptions.dart
dahoud 92612abbd7 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
2026-01-10 10:43:17 +00:00

300 lines
7.8 KiB
Dart

/// Exception de base pour toutes les exceptions serveur.
///
/// Cette exception est levée lorsque le serveur retourne une erreur
/// ou lorsqu'une communication avec le serveur échoue.
///
/// **Usage:**
/// ```dart
/// if (response.statusCode >= 400) {
/// throw ServerException(
/// 'Erreur serveur: ${response.statusCode}',
/// statusCode: response.statusCode,
/// );
/// }
/// ```
class ServerException implements Exception {
/// Crée une nouvelle [ServerException].
///
/// [message] Message décrivant l'erreur
/// [statusCode] Code de statut HTTP optionnel
/// [originalError] L'erreur originale si disponible
const ServerException(
this.message, {
this.statusCode,
this.originalError,
});
/// Message décrivant l'erreur
final String message;
/// Code de statut HTTP (404, 500, etc.)
final int? statusCode;
/// L'erreur originale qui a causé cette exception
final Object? originalError;
@override
String toString() {
final buffer = StringBuffer('ServerException: $message');
if (statusCode != null) {
buffer.write(' (Status: $statusCode)');
}
if (originalError != null) {
buffer.write(' (Original: $originalError)');
}
return buffer.toString();
}
}
/// Exception liée au cache local.
///
/// Cette exception 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
///
/// **Usage:**
/// ```dart
/// try {
/// await cache.write(key, value);
/// } catch (e) {
/// throw CacheException('Impossible d\'écrire dans le cache', e);
/// }
/// ```
class CacheException implements Exception {
/// Crée une nouvelle [CacheException].
///
/// [message] Message décrivant l'erreur
/// [originalError] L'erreur originale si disponible
const CacheException([
this.message = 'Erreur de cache',
this.originalError,
]);
/// Message décrivant l'erreur
final String message;
/// L'erreur originale qui a causé cette exception
final Object? originalError;
@override
String toString() {
if (originalError != null) {
return 'CacheException: $message (Original: $originalError)';
}
return 'CacheException: $message';
}
}
/// Exception liée à l'authentification.
///
/// Cette exception est levée lorsque :
/// - Les identifiants sont incorrects
/// - Le token d'authentification est expiré
/// - L'utilisateur n'est pas autorisé
///
/// **Usage:**
/// ```dart
/// if (!isValidCredentials(email, password)) {
/// throw AuthenticationException('Identifiants incorrects');
/// }
/// ```
class AuthenticationException implements Exception {
/// Crée une nouvelle [AuthenticationException].
///
/// [message] Message décrivant l'erreur d'authentification
/// [code] Code d'erreur optionnel
const AuthenticationException(
this.message, {
this.code,
});
/// Message décrivant l'erreur
final String message;
/// Code d'erreur optionnel
final String? code;
@override
String toString() {
if (code != null) {
return 'AuthenticationException: $message (Code: $code)';
}
return 'AuthenticationException: $message';
}
}
/// Exception serveur avec message personnalisé.
///
/// **Note:** Cette classe est dépréciée. Utilisez [ServerException] à la place.
///
/// **Usage déprécié:**
/// ```dart
/// throw ServerExceptionWithMessage('Erreur personnalisée');
/// ```
@Deprecated('Utilisez ServerException à la place')
class ServerExceptionWithMessage implements Exception {
/// Crée une nouvelle [ServerExceptionWithMessage].
///
/// [message] Message décrivant l'erreur
const ServerExceptionWithMessage(this.message);
/// Message décrivant l'erreur
final String message;
@override
String toString() => 'ServerException: $message';
}
/// Exception levée lorsque l'utilisateur n'est pas trouvé.
///
/// Cette exception est levée lorsque :
/// - L'utilisateur avec l'ID donné n'existe pas
/// - L'utilisateur a été supprimé
/// - L'ID utilisateur est invalide
///
/// **Usage:**
/// ```dart
/// final user = await repository.getUserById(userId);
/// if (user == null) {
/// throw UserNotFoundException('Utilisateur avec ID $userId non trouvé');
/// }
/// ```
class UserNotFoundException implements Exception {
/// Crée une nouvelle [UserNotFoundException].
///
/// [message] Message décrivant l'erreur
/// [userId] L'ID de l'utilisateur non trouvé
const UserNotFoundException([
this.message = 'Utilisateur non trouvé',
this.userId,
]);
/// Message décrivant l'erreur
final String message;
/// L'ID de l'utilisateur non trouvé
final String? userId;
@override
String toString() {
if (userId != null) {
return 'UserNotFoundException: $message (UserId: $userId)';
}
return 'UserNotFoundException: $message';
}
}
/// Exception levée en cas de conflit de données.
///
/// Cette exception est levée lorsque :
/// - Une ressource existe déjà (ex: email déjà utilisé)
/// - Une opération entre en conflit avec l'état actuel
/// - Une contrainte d'unicité est violée
///
/// **Usage:**
/// ```dart
/// if (await userExists(email)) {
/// throw ConflictException('Un utilisateur avec cet email existe déjà');
/// }
/// ```
class ConflictException implements Exception {
/// Crée une nouvelle [ConflictException].
///
/// [message] Message décrivant le conflit
/// [resource] La ressource en conflit
const ConflictException([
this.message = 'Conflit détecté',
this.resource,
]);
/// Message décrivant le conflit
final String message;
/// La ressource en conflit
final String? resource;
@override
String toString() {
if (resource != null) {
return 'ConflictException: $message (Resource: $resource)';
}
return 'ConflictException: $message';
}
}
/// Exception levée lorsque l'utilisateur n'est pas autorisé.
///
/// Cette exception est levée lorsque :
/// - Le token d'authentification est invalide ou expiré
/// - L'utilisateur n'a pas les permissions nécessaires
/// - La session a expiré
///
/// **Usage:**
/// ```dart
/// if (!hasPermission(user, Permission.admin)) {
/// throw UnauthorizedException('Accès non autorisé');
/// }
/// ```
class UnauthorizedException implements Exception {
/// Crée une nouvelle [UnauthorizedException].
///
/// [message] Message décrivant l'erreur
/// [reason] Raison de la non-autorisation
const UnauthorizedException([
this.message = 'Non autorisé',
this.reason,
]);
/// Message décrivant l'erreur
final String message;
/// Raison de la non-autorisation
final String? reason;
@override
String toString() {
if (reason != null) {
return 'UnauthorizedException: $message (Reason: $reason)';
}
return 'UnauthorizedException: $message';
}
}
/// Exception levée lorsque la validation échoue.
///
/// Cette exception est levée lorsque :
/// - Les données ne respectent pas les contraintes
/// - Les données sont manquantes ou invalides
/// - Les données ne passent pas la validation métier
///
/// **Usage:**
/// ```dart
/// if (email.isEmpty || !isValidEmail(email)) {
/// throw ValidationException('Email invalide', field: 'email');
/// }
/// ```
class ValidationException implements Exception {
/// Crée une nouvelle [ValidationException].
///
/// [message] Message décrivant l'erreur de validation
/// [field] Le champ qui a échoué la validation
const ValidationException(
this.message, {
this.field,
});
/// Message décrivant l'erreur
final String message;
/// Le champ qui a échoué la validation
final String? field;
@override
String toString() {
if (field != null) {
return 'ValidationException: $message (Field: $field)';
}
return 'ValidationException: $message';
}
}