Initialisation du projet geosector complet (web + flutter)
This commit is contained in:
364
flutt/lib/chat/repositories/chat_repository.dart
Normal file
364
flutt/lib/chat/repositories/chat_repository.dart
Normal file
@@ -0,0 +1,364 @@
|
||||
import 'package:hive/hive.dart';
|
||||
import 'package:uuid/uuid.dart';
|
||||
import '../../core/constants/app_keys.dart';
|
||||
import '../models/conversation_model.dart';
|
||||
import '../models/message_model.dart';
|
||||
import '../models/participant_model.dart';
|
||||
import '../services/chat_api_service.dart';
|
||||
import '../services/notifications/mqtt_notification_service.dart';
|
||||
|
||||
/// Repository pour la gestion des fonctionnalités de chat
|
||||
///
|
||||
/// Ce repository centralise toutes les opérations liées au chat,
|
||||
/// y compris la gestion des conversations, des messages et des participants
|
||||
|
||||
class ChatRepository {
|
||||
final ChatApiService _apiService;
|
||||
final MqttNotificationService _mqttService;
|
||||
|
||||
ChatRepository(this._apiService, this._mqttService);
|
||||
|
||||
/// Liste des conversations de l'utilisateur
|
||||
Future<List<ConversationModel>> getConversations({bool forceRefresh = false}) async {
|
||||
try {
|
||||
// Récupérer depuis Hive
|
||||
var box = await Hive.openBox<ConversationModel>(AppKeys.chatConversationsBoxName);
|
||||
var localConversations = box.values.toList();
|
||||
|
||||
// Si on force le rafraîchissement ou qu'on n'a pas de données locales
|
||||
if (forceRefresh || localConversations.isEmpty) {
|
||||
try {
|
||||
// Récupérer depuis l'API
|
||||
var apiConversations = await _apiService.getConversations();
|
||||
|
||||
// Mettre à jour Hive
|
||||
await box.clear();
|
||||
for (var conversation in apiConversations) {
|
||||
await box.put(conversation.id, conversation);
|
||||
}
|
||||
|
||||
return apiConversations;
|
||||
} catch (e) {
|
||||
// Si l'API échoue, utiliser les données locales
|
||||
if (localConversations.isNotEmpty) {
|
||||
return localConversations;
|
||||
}
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
||||
return localConversations;
|
||||
} catch (e) {
|
||||
throw Exception('Erreur lors de la récupération des conversations: $e');
|
||||
}
|
||||
}
|
||||
|
||||
/// Récupère une conversation spécifique
|
||||
Future<ConversationModel> getConversation(String id) async {
|
||||
try {
|
||||
// Vérifier d'abord dans Hive
|
||||
var box = await Hive.openBox<ConversationModel>(AppKeys.chatConversationsBoxName);
|
||||
var localConversation = box.get(id);
|
||||
|
||||
if (localConversation != null) {
|
||||
return localConversation;
|
||||
}
|
||||
|
||||
// Sinon récupérer depuis l'API
|
||||
var apiConversation = await _apiService.getConversation(id);
|
||||
await box.put(id, apiConversation);
|
||||
|
||||
return apiConversation;
|
||||
} catch (e) {
|
||||
throw Exception('Erreur lors de la récupération de la conversation: $e');
|
||||
}
|
||||
}
|
||||
|
||||
/// Crée une nouvelle conversation
|
||||
Future<ConversationModel> createConversation(Map<String, dynamic> data) async {
|
||||
try {
|
||||
// Créer via l'API
|
||||
var conversation = await _apiService.createConversation(data);
|
||||
|
||||
// Sauvegarder dans Hive
|
||||
var box = await Hive.openBox<ConversationModel>(AppKeys.chatConversationsBoxName);
|
||||
await box.put(conversation.id, conversation);
|
||||
|
||||
// S'abonner aux notifications de la conversation
|
||||
await _mqttService.subscribeToConversation(conversation.id);
|
||||
|
||||
return conversation;
|
||||
} catch (e) {
|
||||
throw Exception('Erreur lors de la création de la conversation: $e');
|
||||
}
|
||||
}
|
||||
|
||||
/// Supprime une conversation
|
||||
Future<void> deleteConversation(String id) async {
|
||||
try {
|
||||
// Supprimer via l'API
|
||||
await _apiService.deleteConversation(id);
|
||||
|
||||
// Supprimer de Hive
|
||||
var box = await Hive.openBox<ConversationModel>(AppKeys.chatConversationsBoxName);
|
||||
await box.delete(id);
|
||||
|
||||
// Se désabonner des notifications
|
||||
await _mqttService.unsubscribeFromConversation(id);
|
||||
} catch (e) {
|
||||
throw Exception('Erreur lors de la suppression de la conversation: $e');
|
||||
}
|
||||
}
|
||||
|
||||
/// Épingle/désépingle une conversation
|
||||
Future<void> pinConversation(String id, bool isPinned) async {
|
||||
try {
|
||||
await _apiService.pinConversation(id, isPinned);
|
||||
|
||||
// Mettre à jour dans Hive
|
||||
var box = await Hive.openBox<ConversationModel>(AppKeys.chatConversationsBoxName);
|
||||
var conversation = box.get(id);
|
||||
if (conversation != null) {
|
||||
await box.put(id, conversation.copyWith(isPinned: isPinned));
|
||||
}
|
||||
} catch (e) {
|
||||
throw Exception('Erreur lors de l\'épinglage de la conversation: $e');
|
||||
}
|
||||
}
|
||||
|
||||
/// Met à jour les permissions de réponse
|
||||
Future<void> updateReplyPermission(String id, String replyPermission) async {
|
||||
try {
|
||||
await _apiService.updateReplyPermission(id, replyPermission);
|
||||
|
||||
// Mettre à jour dans Hive
|
||||
var box = await Hive.openBox<ConversationModel>(AppKeys.chatConversationsBoxName);
|
||||
var conversation = box.get(id);
|
||||
if (conversation != null) {
|
||||
await box.put(id, conversation.copyWith(replyPermission: replyPermission));
|
||||
}
|
||||
} catch (e) {
|
||||
throw Exception('Erreur lors de la mise à jour des permissions: $e');
|
||||
}
|
||||
}
|
||||
|
||||
/// Récupère les messages d'une conversation
|
||||
Future<List<MessageModel>> getMessages(String conversationId, {int page = 1, int limit = 50}) async {
|
||||
try {
|
||||
// Récupérer depuis Hive
|
||||
var box = await Hive.openBox<MessageModel>(AppKeys.chatMessagesBoxName);
|
||||
var localMessages = box.values
|
||||
.where((m) => m.conversationId == conversationId)
|
||||
.toList()
|
||||
..sort((a, b) => b.createdAt.compareTo(a.createdAt));
|
||||
|
||||
// Si on a assez de messages localement
|
||||
if (localMessages.length >= page * limit) {
|
||||
return localMessages.skip((page - 1) * limit).take(limit).toList();
|
||||
}
|
||||
|
||||
try {
|
||||
// Récupérer depuis l'API
|
||||
var apiMessages = await _apiService.getMessages(conversationId, page: page, limit: limit);
|
||||
|
||||
// Mettre à jour Hive
|
||||
for (var message in apiMessages) {
|
||||
await box.put(message.id, message);
|
||||
}
|
||||
|
||||
return apiMessages;
|
||||
} catch (e) {
|
||||
// Si l'API échoue, utiliser les données locales
|
||||
if (localMessages.isNotEmpty) {
|
||||
return localMessages.skip((page - 1) * limit).take(limit).toList();
|
||||
}
|
||||
rethrow;
|
||||
}
|
||||
} catch (e) {
|
||||
throw Exception('Erreur lors de la récupération des messages: $e');
|
||||
}
|
||||
}
|
||||
|
||||
/// Envoie un message via MQTT
|
||||
Future<void> sendMessage(String conversationId, Map<String, dynamic> messageData) async {
|
||||
try {
|
||||
// Générer un ID unique pour le message
|
||||
var messageId = const Uuid().v4();
|
||||
var userId = messageData['senderId'] as String?;
|
||||
|
||||
// Créer le message
|
||||
var message = MessageModel(
|
||||
id: messageId,
|
||||
conversationId: conversationId,
|
||||
senderId: userId,
|
||||
senderType: 'user',
|
||||
content: messageData['content'] as String,
|
||||
contentType: messageData['contentType'] as String? ?? 'text',
|
||||
createdAt: DateTime.now(),
|
||||
status: 'sent',
|
||||
isAnnouncement: messageData['isAnnouncement'] as bool? ?? false,
|
||||
);
|
||||
|
||||
// Sauvegarder temporairement dans Hive
|
||||
var box = await Hive.openBox<MessageModel>(AppKeys.chatMessagesBoxName);
|
||||
await box.put(messageId, message);
|
||||
|
||||
// Publier via MQTT
|
||||
await _mqttService.publishMessage('chat/message/send', {
|
||||
'messageId': messageId,
|
||||
'conversationId': conversationId,
|
||||
'senderId': userId,
|
||||
'content': message.content,
|
||||
'contentType': message.contentType,
|
||||
'timestamp': message.createdAt.toIso8601String(),
|
||||
'isAnnouncement': message.isAnnouncement,
|
||||
});
|
||||
} catch (e) {
|
||||
throw Exception('Erreur lors de l\'envoi du message: $e');
|
||||
}
|
||||
}
|
||||
|
||||
/// Marque un message comme lu
|
||||
Future<void> markMessageAsRead(String messageId) async {
|
||||
try {
|
||||
// Mettre à jour via l'API
|
||||
await _apiService.markMessageAsRead(messageId);
|
||||
|
||||
// Mettre à jour dans Hive
|
||||
var box = await Hive.openBox<MessageModel>(AppKeys.chatMessagesBoxName);
|
||||
var message = box.get(messageId);
|
||||
if (message != null) {
|
||||
await box.put(messageId, message.copyWith(
|
||||
status: 'read',
|
||||
readAt: DateTime.now(),
|
||||
));
|
||||
}
|
||||
} catch (e) {
|
||||
throw Exception('Erreur lors du marquage comme lu: $e');
|
||||
}
|
||||
}
|
||||
|
||||
/// Ajoute un participant à une conversation
|
||||
Future<void> addParticipant(String conversationId, Map<String, dynamic> participantData) async {
|
||||
try {
|
||||
await _apiService.addParticipant(conversationId, participantData);
|
||||
|
||||
// Mettre à jour la conversation dans Hive
|
||||
var conversationBox = await Hive.openBox<ConversationModel>(AppKeys.chatConversationsBoxName);
|
||||
var conversation = conversationBox.get(conversationId);
|
||||
if (conversation != null) {
|
||||
var updatedParticipants = List<ParticipantModel>.from(conversation.participants);
|
||||
updatedParticipants.add(ParticipantModel.fromJson(participantData));
|
||||
await conversationBox.put(conversationId, conversation.copyWith(participants: updatedParticipants));
|
||||
}
|
||||
} catch (e) {
|
||||
throw Exception('Erreur lors de l\'ajout du participant: $e');
|
||||
}
|
||||
}
|
||||
|
||||
/// Retire un participant d'une conversation
|
||||
Future<void> removeParticipant(String conversationId, String participantId) async {
|
||||
try {
|
||||
await _apiService.removeParticipant(conversationId, participantId);
|
||||
|
||||
// Mettre à jour la conversation dans Hive
|
||||
var conversationBox = await Hive.openBox<ConversationModel>(AppKeys.chatConversationsBoxName);
|
||||
var conversation = conversationBox.get(conversationId);
|
||||
if (conversation != null) {
|
||||
var updatedParticipants = List<ParticipantModel>.from(conversation.participants);
|
||||
updatedParticipants.removeWhere((p) => p.id == participantId);
|
||||
await conversationBox.put(conversationId, conversation.copyWith(participants: updatedParticipants));
|
||||
}
|
||||
} catch (e) {
|
||||
throw Exception('Erreur lors du retrait du participant: $e');
|
||||
}
|
||||
}
|
||||
|
||||
/// Crée un utilisateur anonyme (pour Resalice)
|
||||
Future<String> createAnonymousUser({String? name, String? email}) async {
|
||||
try {
|
||||
return await _apiService.createAnonymousUser(name: name, email: email);
|
||||
} catch (e) {
|
||||
throw Exception('Erreur lors de la création de l\'utilisateur anonyme: $e');
|
||||
}
|
||||
}
|
||||
|
||||
/// Convertit un utilisateur anonyme en utilisateur authentifié
|
||||
Future<void> convertAnonymousToUser(String anonymousId, String userId) async {
|
||||
try {
|
||||
// Mettre à jour tous les messages de l'utilisateur anonyme
|
||||
var messageBox = await Hive.openBox<MessageModel>(AppKeys.chatMessagesBoxName);
|
||||
var messages = messageBox.values.where((m) => m.senderId == anonymousId).toList();
|
||||
|
||||
for (var message in messages) {
|
||||
await messageBox.put(message.id, message.copyWith(
|
||||
senderId: userId,
|
||||
senderType: 'user',
|
||||
));
|
||||
}
|
||||
} catch (e) {
|
||||
throw Exception('Erreur lors de la conversion de l\'utilisateur: $e');
|
||||
}
|
||||
}
|
||||
|
||||
/// Récupère les annonces
|
||||
Future<List<ConversationModel>> getAnnouncements({bool forceRefresh = false}) async {
|
||||
try {
|
||||
// Filtrer les conversations pour n'avoir que les annonces
|
||||
var conversations = await getConversations(forceRefresh: forceRefresh);
|
||||
return conversations.where((c) => c.type == 'announcement').toList();
|
||||
} catch (e) {
|
||||
throw Exception('Erreur lors de la récupération des annonces: $e');
|
||||
}
|
||||
}
|
||||
|
||||
/// Crée une nouvelle annonce
|
||||
Future<ConversationModel> createAnnouncement(Map<String, dynamic> data) async {
|
||||
try {
|
||||
// Créer la conversation comme une annonce
|
||||
data['type'] = 'announcement';
|
||||
return await createConversation(data);
|
||||
} catch (e) {
|
||||
throw Exception('Erreur lors de la création de l\'annonce: $e');
|
||||
}
|
||||
}
|
||||
|
||||
/// Récupère les statistiques d'une annonce
|
||||
Future<Map<String, dynamic>> getAnnouncementStats(String conversationId) async {
|
||||
try {
|
||||
return await _apiService.getAnnouncementStats(conversationId);
|
||||
} catch (e) {
|
||||
throw Exception('Erreur lors de la récupération des statistiques: $e');
|
||||
}
|
||||
}
|
||||
|
||||
/// Récupère les cibles d'audience disponibles
|
||||
Future<List<Map<String, dynamic>>> getAvailableAudienceTargets() async {
|
||||
try {
|
||||
return await _apiService.getAvailableAudienceTargets();
|
||||
} catch (e) {
|
||||
throw Exception('Erreur lors de la récupération des cibles: $e');
|
||||
}
|
||||
}
|
||||
|
||||
/// Ajoute une cible d'audience
|
||||
Future<void> addAudienceTarget(String conversationId, Map<String, dynamic> targetData) async {
|
||||
try {
|
||||
// L'ajout des cibles d'audience est géré lors de la création de l'annonce
|
||||
// Mais on pourrait avoir besoin de modifier les cibles plus tard
|
||||
throw UnimplementedError('Ajout de cible non encore implémenté');
|
||||
} catch (e) {
|
||||
throw Exception('Erreur lors de l\'ajout de cible: $e');
|
||||
}
|
||||
}
|
||||
|
||||
/// Retire une cible d'audience
|
||||
Future<void> removeAudienceTarget(String conversationId, String targetId) async {
|
||||
try {
|
||||
// Le retrait des cibles d'audience est géré lors de la création de l'annonce
|
||||
throw UnimplementedError('Retrait de cible non encore implémenté');
|
||||
} catch (e) {
|
||||
throw Exception('Erreur lors du retrait de cible: $e');
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user