Files
unionflow-mobile-apps/lib/features/communication/data/datasources/messaging_remote_datasource.dart
dahoud d094d6db9c Initial commit: unionflow-mobile-apps
Application Flutter complète (sans build artifacts).

Signed-off-by: lions dev Team
2026-03-15 16:30:08 +00:00

231 lines
7.3 KiB
Dart

/// Datasource distant pour la communication (API)
library messaging_remote_datasource;
import 'dart:convert';
import 'package:http/http.dart' as http;
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
import 'package:injectable/injectable.dart';
import '../../../../core/config/environment.dart';
import '../../../../core/error/exceptions.dart';
import '../models/message_model.dart';
import '../models/conversation_model.dart';
import '../../domain/entities/message.dart';
@lazySingleton
class MessagingRemoteDatasource {
final http.Client client;
final FlutterSecureStorage secureStorage;
MessagingRemoteDatasource({
required this.client,
required this.secureStorage,
});
/// Headers HTTP avec authentification
Future<Map<String, String>> _getHeaders() async {
final token = await secureStorage.read(key: 'access_token');
return {
'Content-Type': 'application/json',
'Accept': 'application/json',
if (token != null) 'Authorization': 'Bearer $token',
};
}
// === CONVERSATIONS ===
Future<List<ConversationModel>> getConversations({
String? organizationId,
bool includeArchived = false,
}) async {
final uri = Uri.parse('${AppConfig.apiBaseUrl}/api/messaging/conversations')
.replace(queryParameters: {
if (organizationId != null) 'organizationId': organizationId,
'includeArchived': includeArchived.toString(),
});
final response = await client.get(uri, headers: await _getHeaders());
if (response.statusCode == 200) {
final List<dynamic> jsonList = json.decode(response.body);
return jsonList
.map((json) => ConversationModel.fromJson(json))
.toList();
} else if (response.statusCode == 401) {
throw UnauthorizedException();
} else {
throw ServerException('Erreur lors de la récupération des conversations');
}
}
Future<ConversationModel> getConversationById(String conversationId) async {
final uri = Uri.parse(
'${AppConfig.apiBaseUrl}/api/messaging/conversations/$conversationId');
final response = await client.get(uri, headers: await _getHeaders());
if (response.statusCode == 200) {
return ConversationModel.fromJson(json.decode(response.body));
} else if (response.statusCode == 404) {
throw NotFoundException('Conversation non trouvée');
} else if (response.statusCode == 401) {
throw UnauthorizedException();
} else {
throw ServerException('Erreur lors de la récupération de la conversation');
}
}
Future<ConversationModel> createConversation({
required String name,
required List<String> participantIds,
String? organizationId,
String? description,
}) async {
final uri =
Uri.parse('${AppConfig.apiBaseUrl}/api/messaging/conversations');
final body = json.encode({
'name': name,
'participantIds': participantIds,
if (organizationId != null) 'organizationId': organizationId,
if (description != null) 'description': description,
});
final response = await client.post(
uri,
headers: await _getHeaders(),
body: body,
);
if (response.statusCode == 201 || response.statusCode == 200) {
return ConversationModel.fromJson(json.decode(response.body));
} else if (response.statusCode == 401) {
throw UnauthorizedException();
} else {
throw ServerException('Erreur lors de la création de la conversation');
}
}
// === MESSAGES ===
Future<List<MessageModel>> getMessages({
required String conversationId,
int? limit,
String? beforeMessageId,
}) async {
final uri = Uri.parse(
'${AppConfig.apiBaseUrl}/api/messaging/conversations/$conversationId/messages')
.replace(queryParameters: {
if (limit != null) 'limit': limit.toString(),
if (beforeMessageId != null) 'beforeMessageId': beforeMessageId,
});
final response = await client.get(uri, headers: await _getHeaders());
if (response.statusCode == 200) {
final List<dynamic> jsonList = json.decode(response.body);
return jsonList.map((json) => MessageModel.fromJson(json)).toList();
} else if (response.statusCode == 401) {
throw UnauthorizedException();
} else {
throw ServerException('Erreur lors de la récupération des messages');
}
}
Future<MessageModel> sendMessage({
required String conversationId,
required String content,
List<String>? attachments,
MessagePriority priority = MessagePriority.normal,
}) async {
final uri = Uri.parse(
'${AppConfig.apiBaseUrl}/api/messaging/conversations/$conversationId/messages');
final body = json.encode({
'content': content,
if (attachments != null) 'attachments': attachments,
'priority': priority.name,
});
final response = await client.post(
uri,
headers: await _getHeaders(),
body: body,
);
if (response.statusCode == 201 || response.statusCode == 200) {
return MessageModel.fromJson(json.decode(response.body));
} else if (response.statusCode == 401) {
throw UnauthorizedException();
} else {
throw ServerException('Erreur lors de l\'envoi du message');
}
}
Future<MessageModel> sendBroadcast({
required String organizationId,
required String subject,
required String content,
MessagePriority priority = MessagePriority.normal,
List<String>? attachments,
}) async {
final uri = Uri.parse('${AppConfig.apiBaseUrl}/api/messaging/broadcast');
final body = json.encode({
'organizationId': organizationId,
'subject': subject,
'content': content,
'priority': priority.name,
if (attachments != null) 'attachments': attachments,
});
final response = await client.post(
uri,
headers: await _getHeaders(),
body: body,
);
if (response.statusCode == 201 || response.statusCode == 200) {
return MessageModel.fromJson(json.decode(response.body));
} else if (response.statusCode == 401) {
throw UnauthorizedException();
} else if (response.statusCode == 403) {
throw ForbiddenException('Permission insuffisante pour envoyer un broadcast');
} else {
throw ServerException('Erreur lors de l\'envoi du broadcast');
}
}
Future<void> markMessageAsRead(String messageId) async {
final uri =
Uri.parse('${AppConfig.apiBaseUrl}/api/messaging/messages/$messageId/read');
final response = await client.put(uri, headers: await _getHeaders());
if (response.statusCode != 200 && response.statusCode != 204) {
if (response.statusCode == 401) {
throw UnauthorizedException();
} else {
throw ServerException('Erreur lors du marquage du message comme lu');
}
}
}
Future<int> getUnreadCount({String? organizationId}) async {
final uri = Uri.parse('${AppConfig.apiBaseUrl}/api/messaging/unread/count')
.replace(queryParameters: {
if (organizationId != null) 'organizationId': organizationId,
});
final response = await client.get(uri, headers: await _getHeaders());
if (response.statusCode == 200) {
final data = json.decode(response.body);
return data['count'] as int;
} else if (response.statusCode == 401) {
throw UnauthorizedException();
} else {
throw ServerException('Erreur lors de la récupération du compte non lu');
}
}
}