## 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
125 lines
3.3 KiB
Dart
125 lines
3.3 KiB
Dart
import 'package:equatable/equatable.dart';
|
|
|
|
/// Entité de domaine représentant un message de chat.
|
|
///
|
|
/// Un message est échangé entre deux utilisateurs dans une conversation.
|
|
class ChatMessage extends Equatable {
|
|
const ChatMessage({
|
|
required this.id,
|
|
required this.conversationId,
|
|
required this.senderId,
|
|
required this.senderFirstName,
|
|
required this.senderLastName,
|
|
required this.senderProfileImageUrl,
|
|
required this.content,
|
|
required this.timestamp,
|
|
required this.isRead,
|
|
this.isDelivered = false,
|
|
this.attachmentUrl,
|
|
this.attachmentType,
|
|
});
|
|
|
|
final String id;
|
|
final String conversationId;
|
|
final String senderId;
|
|
final String senderFirstName;
|
|
final String senderLastName;
|
|
final String? senderProfileImageUrl;
|
|
final String content;
|
|
final DateTime timestamp;
|
|
final bool isRead;
|
|
final bool isDelivered;
|
|
final String? attachmentUrl; // URL d'une image/fichier joint
|
|
final AttachmentType? attachmentType;
|
|
|
|
/// Nom complet de l'expéditeur.
|
|
String get senderFullName => '$senderFirstName $senderLastName';
|
|
|
|
/// Indique si le message a une pièce jointe.
|
|
bool get hasAttachment => attachmentUrl != null && attachmentType != null;
|
|
|
|
@override
|
|
List<Object?> get props => [
|
|
id,
|
|
conversationId,
|
|
senderId,
|
|
senderFirstName,
|
|
senderLastName,
|
|
senderProfileImageUrl,
|
|
content,
|
|
timestamp,
|
|
isRead,
|
|
isDelivered,
|
|
attachmentUrl,
|
|
attachmentType,
|
|
];
|
|
|
|
/// Crée une copie de ce message avec des valeurs modifiées.
|
|
ChatMessage copyWith({
|
|
String? id,
|
|
String? conversationId,
|
|
String? senderId,
|
|
String? senderFirstName,
|
|
String? senderLastName,
|
|
String? senderProfileImageUrl,
|
|
String? content,
|
|
DateTime? timestamp,
|
|
bool? isRead,
|
|
bool? isDelivered,
|
|
String? attachmentUrl,
|
|
AttachmentType? attachmentType,
|
|
}) {
|
|
return ChatMessage(
|
|
id: id ?? this.id,
|
|
conversationId: conversationId ?? this.conversationId,
|
|
senderId: senderId ?? this.senderId,
|
|
senderFirstName: senderFirstName ?? this.senderFirstName,
|
|
senderLastName: senderLastName ?? this.senderLastName,
|
|
senderProfileImageUrl: senderProfileImageUrl ?? this.senderProfileImageUrl,
|
|
content: content ?? this.content,
|
|
timestamp: timestamp ?? this.timestamp,
|
|
isRead: isRead ?? this.isRead,
|
|
isDelivered: isDelivered ?? this.isDelivered,
|
|
attachmentUrl: attachmentUrl ?? this.attachmentUrl,
|
|
attachmentType: attachmentType ?? this.attachmentType,
|
|
);
|
|
}
|
|
}
|
|
|
|
/// Type de pièce jointe.
|
|
enum AttachmentType {
|
|
image,
|
|
video,
|
|
audio,
|
|
file,
|
|
}
|
|
|
|
/// Extensions pour faciliter l'utilisation.
|
|
extension AttachmentTypeExtension on AttachmentType {
|
|
String get displayName {
|
|
switch (this) {
|
|
case AttachmentType.image:
|
|
return 'Image';
|
|
case AttachmentType.video:
|
|
return 'Vidéo';
|
|
case AttachmentType.audio:
|
|
return 'Audio';
|
|
case AttachmentType.file:
|
|
return 'Fichier';
|
|
}
|
|
}
|
|
|
|
String get icon {
|
|
switch (this) {
|
|
case AttachmentType.image:
|
|
return '🖼️';
|
|
case AttachmentType.video:
|
|
return '🎥';
|
|
case AttachmentType.audio:
|
|
return '🎵';
|
|
case AttachmentType.file:
|
|
return '📄';
|
|
}
|
|
}
|
|
}
|