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:
dahoud
2026-04-15 20:26:35 +00:00
parent 07b8488714
commit 45dcd2171e
23 changed files with 2096 additions and 1588 deletions

View File

@@ -1,9 +1,8 @@
/// Use case: Récupérer les conversations
/// Use case: Récupérer les conversations v4
library get_conversations;
import 'package:dartz/dartz.dart';
import 'package:injectable/injectable.dart';
import '../../../../core/error/failures.dart';
import '../entities/conversation.dart';
import '../repositories/messaging_repository.dart';
@@ -13,13 +12,7 @@ class GetConversations {
GetConversations(this.repository);
Future<Either<Failure, List<Conversation>>> call({
String? organizationId,
bool includeArchived = false,
}) async {
return await repository.getConversations(
organizationId: organizationId,
includeArchived: includeArchived,
);
Future<List<ConversationSummary>> call() async {
return await repository.getMesConversations();
}
}

View File

@@ -1,9 +1,8 @@
/// Use case: Récupérer les messages d'une conversation
/// Use case: Récupérer les messages d'une conversation v4
library get_messages;
import 'package:dartz/dartz.dart';
import 'package:injectable/injectable.dart';
import '../../../../core/error/failures.dart';
import '../entities/message.dart';
import '../repositories/messaging_repository.dart';
@@ -13,19 +12,10 @@ class GetMessages {
GetMessages(this.repository);
Future<Either<Failure, List<Message>>> call({
Future<List<Message>> call({
required String conversationId,
int? limit,
String? beforeMessageId,
int page = 0,
}) async {
if (conversationId.isEmpty) {
return Left(ValidationFailure('ID conversation requis'));
}
return await repository.getMessages(
conversationId: conversationId,
limit: limit,
beforeMessageId: beforeMessageId,
);
return await repository.getMessages(conversationId, page: page);
}
}

View File

@@ -1,10 +1,10 @@
/// Use case: Envoyer un broadcast organisation
/// Use case: Broadcast — non utilisé en v4 (remplacé par canal rôle)
///
/// Conservé pour la compatibilité du graphe de dépendances.
library send_broadcast;
import 'package:dartz/dartz.dart';
import 'package:injectable/injectable.dart';
import '../../../../core/error/failures.dart';
import '../entities/message.dart';
import '../repositories/messaging_repository.dart';
@lazySingleton
@@ -13,32 +13,13 @@ class SendBroadcast {
SendBroadcast(this.repository);
Future<Either<Failure, Message>> call({
required String organizationId,
required String subject,
required String content,
MessagePriority priority = MessagePriority.normal,
List<String>? attachments,
/// Démarre un canal de communication avec le rôle BUREAU
Future<void> call({
required String organisationId,
}) async {
// Validation
if (subject.trim().isEmpty) {
return Left(ValidationFailure('Le sujet ne peut pas être vide'));
}
if (content.trim().isEmpty) {
return Left(ValidationFailure('Le message ne peut pas être vide'));
}
if (organizationId.isEmpty) {
return Left(ValidationFailure('ID organisation requis'));
}
return await repository.sendBroadcast(
organizationId: organizationId,
subject: subject,
content: content,
priority: priority,
attachments: attachments,
await repository.demarrerConversationRole(
roleCible: 'PRESIDENT',
organisationId: organisationId,
);
}
}

View File

@@ -1,9 +1,8 @@
/// Use case: Envoyer un message
/// Use case: Envoyer un message v4
library send_message;
import 'package:dartz/dartz.dart';
import 'package:injectable/injectable.dart';
import '../../../../core/error/failures.dart';
import '../entities/message.dart';
import '../repositories/messaging_repository.dart';
@@ -13,22 +12,15 @@ class SendMessage {
SendMessage(this.repository);
Future<Either<Failure, Message>> call({
Future<Message> call({
required String conversationId,
required String content,
List<String>? attachments,
MessagePriority priority = MessagePriority.normal,
required String contenu,
String typeMessage = 'TEXTE',
}) async {
// Validation
if (content.trim().isEmpty) {
return Left(ValidationFailure('Le message ne peut pas être vide'));
}
return await repository.sendMessage(
conversationId: conversationId,
content: content,
attachments: attachments,
priority: priority,
return await repository.envoyerMessage(
conversationId,
typeMessage: typeMessage,
contenu: contenu,
);
}
}