feat(communication): module messagerie unifié + contact policies + blocages
Aligné avec le backend MessagingResource : - Nouveau module communication (conversations, messages, participants) - Respect des ContactPolicy (qui peut parler à qui par rôle) - Gestion MemberBlock (blocages individuels) - UI : conversations list, conversation detail, broadcast, tiles - BLoC : MessagingBloc avec events (envoyer, démarrer conversation rôle, etc.)
This commit is contained in:
@@ -1,173 +1,68 @@
|
||||
/// Entité métier Message
|
||||
/// Entité métier Message v4
|
||||
///
|
||||
/// Représente un message dans le système de communication UnionFlow
|
||||
/// Correspond au DTO backend : MessageResponse
|
||||
library message;
|
||||
|
||||
import 'package:equatable/equatable.dart';
|
||||
|
||||
/// Type de message
|
||||
enum MessageType {
|
||||
/// Message individuel (membre à membre)
|
||||
individual,
|
||||
|
||||
/// Broadcast organisation (OrgAdmin → tous)
|
||||
broadcast,
|
||||
|
||||
/// Message ciblé par rôle (Moderator → groupe)
|
||||
targeted,
|
||||
|
||||
/// Notification système
|
||||
system,
|
||||
}
|
||||
|
||||
/// Statut de lecture du message
|
||||
enum MessageStatus {
|
||||
/// Envoyé mais non lu
|
||||
sent,
|
||||
|
||||
/// Livré (reçu par le serveur)
|
||||
delivered,
|
||||
|
||||
/// Lu par le destinataire
|
||||
read,
|
||||
|
||||
/// Échec d'envoi
|
||||
failed,
|
||||
}
|
||||
|
||||
/// Priorité du message
|
||||
enum MessagePriority {
|
||||
/// Priorité normale
|
||||
normal,
|
||||
|
||||
/// Priorité élevée (important)
|
||||
high,
|
||||
|
||||
/// Priorité urgente (critique)
|
||||
urgent,
|
||||
}
|
||||
|
||||
/// Entité Message
|
||||
/// Message dans une conversation
|
||||
class Message extends Equatable {
|
||||
final String id;
|
||||
final String conversationId;
|
||||
final String senderId;
|
||||
final String senderName;
|
||||
final String? senderAvatar;
|
||||
final String content;
|
||||
final MessageType type;
|
||||
final MessageStatus status;
|
||||
final MessagePriority priority;
|
||||
final List<String> recipientIds;
|
||||
final List<String>? recipientRoles;
|
||||
final String? organizationId;
|
||||
final DateTime createdAt;
|
||||
final DateTime? readAt;
|
||||
final Map<String, dynamic>? metadata;
|
||||
final List<String>? attachments;
|
||||
final bool isEdited;
|
||||
final DateTime? editedAt;
|
||||
final bool isDeleted;
|
||||
final String typeMessage; // TEXTE | VOCAL | IMAGE | SYSTEME
|
||||
final String? contenu;
|
||||
final String? urlFichier;
|
||||
final int? dureeAudio;
|
||||
final bool supprime;
|
||||
final String? expediteurId;
|
||||
final String? expediteurNom;
|
||||
final String? expediteurPrenom;
|
||||
final String? messageParentId;
|
||||
final String? messageParentApercu;
|
||||
final DateTime? dateEnvoi;
|
||||
|
||||
const Message({
|
||||
required this.id,
|
||||
required this.conversationId,
|
||||
required this.senderId,
|
||||
required this.senderName,
|
||||
this.senderAvatar,
|
||||
required this.content,
|
||||
required this.type,
|
||||
required this.status,
|
||||
this.priority = MessagePriority.normal,
|
||||
required this.recipientIds,
|
||||
this.recipientRoles,
|
||||
this.organizationId,
|
||||
required this.createdAt,
|
||||
this.readAt,
|
||||
this.metadata,
|
||||
this.attachments,
|
||||
this.isEdited = false,
|
||||
this.editedAt,
|
||||
this.isDeleted = false,
|
||||
required this.typeMessage,
|
||||
this.contenu,
|
||||
this.urlFichier,
|
||||
this.dureeAudio,
|
||||
this.supprime = false,
|
||||
this.expediteurId,
|
||||
this.expediteurNom,
|
||||
this.expediteurPrenom,
|
||||
this.messageParentId,
|
||||
this.messageParentApercu,
|
||||
this.dateEnvoi,
|
||||
});
|
||||
|
||||
/// Vérifie si le message a été lu
|
||||
bool get isRead => status == MessageStatus.read;
|
||||
String get expediteurNomComplet {
|
||||
if (expediteurPrenom != null && expediteurNom != null) {
|
||||
return '$expediteurPrenom $expediteurNom';
|
||||
}
|
||||
if (expediteurPrenom != null) return expediteurPrenom!;
|
||||
if (expediteurNom != null) return expediteurNom!;
|
||||
return '';
|
||||
}
|
||||
|
||||
/// Vérifie si le message est urgent
|
||||
bool get isUrgent => priority == MessagePriority.urgent;
|
||||
bool get isTexte => typeMessage == 'TEXTE';
|
||||
bool get isVocal => typeMessage == 'VOCAL';
|
||||
bool get isImage => typeMessage == 'IMAGE';
|
||||
bool get isSysteme => typeMessage == 'SYSTEME';
|
||||
bool get hasParent => messageParentId != null;
|
||||
|
||||
/// Vérifie si le message est un broadcast
|
||||
bool get isBroadcast => type == MessageType.broadcast;
|
||||
|
||||
/// Vérifie si le message a des pièces jointes
|
||||
bool get hasAttachments => attachments != null && attachments!.isNotEmpty;
|
||||
|
||||
/// Copie avec modifications
|
||||
Message copyWith({
|
||||
String? id,
|
||||
String? conversationId,
|
||||
String? senderId,
|
||||
String? senderName,
|
||||
String? senderAvatar,
|
||||
String? content,
|
||||
MessageType? type,
|
||||
MessageStatus? status,
|
||||
MessagePriority? priority,
|
||||
List<String>? recipientIds,
|
||||
List<String>? recipientRoles,
|
||||
String? organizationId,
|
||||
DateTime? createdAt,
|
||||
DateTime? readAt,
|
||||
Map<String, dynamic>? metadata,
|
||||
List<String>? attachments,
|
||||
bool? isEdited,
|
||||
DateTime? editedAt,
|
||||
bool? isDeleted,
|
||||
}) {
|
||||
return Message(
|
||||
id: id ?? this.id,
|
||||
conversationId: conversationId ?? this.conversationId,
|
||||
senderId: senderId ?? this.senderId,
|
||||
senderName: senderName ?? this.senderName,
|
||||
senderAvatar: senderAvatar ?? this.senderAvatar,
|
||||
content: content ?? this.content,
|
||||
type: type ?? this.type,
|
||||
status: status ?? this.status,
|
||||
priority: priority ?? this.priority,
|
||||
recipientIds: recipientIds ?? this.recipientIds,
|
||||
recipientRoles: recipientRoles ?? this.recipientRoles,
|
||||
organizationId: organizationId ?? this.organizationId,
|
||||
createdAt: createdAt ?? this.createdAt,
|
||||
readAt: readAt ?? this.readAt,
|
||||
metadata: metadata ?? this.metadata,
|
||||
attachments: attachments ?? this.attachments,
|
||||
isEdited: isEdited ?? this.isEdited,
|
||||
editedAt: editedAt ?? this.editedAt,
|
||||
isDeleted: isDeleted ?? this.isDeleted,
|
||||
);
|
||||
/// Texte à afficher dans la liste (aperçu)
|
||||
String get apercu {
|
||||
if (supprime) return '🚫 Message supprimé';
|
||||
if (isVocal) return '🎙️ Note vocale${dureeAudio != null ? ' (${dureeAudio}s)' : ''}';
|
||||
if (isImage) return '📷 Image';
|
||||
if (isSysteme) return contenu ?? '🔔 Notification système';
|
||||
return contenu ?? '';
|
||||
}
|
||||
|
||||
@override
|
||||
List<Object?> get props => [
|
||||
id,
|
||||
conversationId,
|
||||
senderId,
|
||||
senderName,
|
||||
senderAvatar,
|
||||
content,
|
||||
type,
|
||||
status,
|
||||
priority,
|
||||
recipientIds,
|
||||
recipientRoles,
|
||||
organizationId,
|
||||
createdAt,
|
||||
readAt,
|
||||
metadata,
|
||||
attachments,
|
||||
isEdited,
|
||||
editedAt,
|
||||
isDeleted,
|
||||
id, typeMessage, contenu, urlFichier, dureeAudio, supprime,
|
||||
expediteurId, expediteurNom, expediteurPrenom,
|
||||
messageParentId, messageParentApercu, dateEnvoi,
|
||||
];
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user