From e9b78a14d5046429e47ad6fcf0f63b8b9722ec59 Mon Sep 17 00:00:00 2001 From: Henry-Hiles Date: Fri, 10 Apr 2026 16:31:55 -0400 Subject: [PATCH] Update reactions as they are modified --- lib/controllers/message_controller.dart | 3 +- lib/controllers/room_chat_controller.dart | 63 +++++++++++++++++++++-- 2 files changed, 60 insertions(+), 6 deletions(-) diff --git a/lib/controllers/message_controller.dart b/lib/controllers/message_controller.dart index 24356c24..79bc77ec 100644 --- a/lib/controllers/message_controller.dart +++ b/lib/controllers/message_controller.dart @@ -79,7 +79,8 @@ class MessageController extends AsyncNotifier { ); final reactions = reactionEvents - ?.fold>>(IMap(), (acc, event) { + ?.where((event) => event.redactedBy == null) + .fold>>(IMap(), (acc, event) { final key = event.content["m.relates_to"]?["key"]; if (key == null) return acc; diff --git a/lib/controllers/room_chat_controller.dart b/lib/controllers/room_chat_controller.dart index d3da7c74..1ecf0ea7 100644 --- a/lib/controllers/room_chat_controller.dart +++ b/lib/controllers/room_chat_controller.dart @@ -9,6 +9,7 @@ import "package:nexus/controllers/message_controller.dart"; import "package:nexus/controllers/messages_controller.dart"; import "package:nexus/controllers/new_events_controller.dart"; import "package:nexus/controllers/rooms_controller.dart"; +import "package:nexus/controllers/selected_room_controller.dart"; import "package:nexus/models/configs/messages_config.dart"; import "package:nexus/models/configs/message_config.dart"; import "package:nexus/models/requests/get_room_state_request.dart"; @@ -77,15 +78,67 @@ class RoomChatController extends AsyncNotifier { ref.onDispose( ref.listen(NewEventsController.provider(roomId), (_, next) async { for (final event in next) { - // TODO: Handle new reactions + if (event.type == "m.reaction") { + final message = controller.messages.firstWhereOrNull( + (message) => + message.id == event.content["m.relates_to"]?["event_id"], + ); + final key = event.content["m.relates_to"]?["key"]; + if (message == null || key == null || !ref.mounted) return; + + return await controller.updateMessage( + message, + message.copyWith( + reactions: IMap(message.reactions) + .update( + key, + (reactors) => [...reactors, event.authorId], + ifAbsent: () => [event.authorId], + ) + .unlock, + ), + ); + } + if (event.type == "m.room.redaction") { final controller = await future; - final message = controller.messages.firstWhereOrNull( - (message) => message.id == event.content["redacts"], + final redactsId = event.content["redacts"]; + final originalMessage = controller.messages.firstWhereOrNull( + (message) => message.id == redactsId, ); - if (message == null || !ref.mounted) return; + if (!ref.mounted) return; - await controller.removeMessage(message); + if (originalMessage != null) { + return await controller.removeMessage(originalMessage); + } + + final redacts = ref + .read(SelectedRoomController.provider) + ?.events + .firstWhere((event) => event.eventId == redactsId); + + if (redacts?.type == "m.reaction") { + final message = controller.messages.firstWhereOrNull( + (message) => + message.id == redacts!.content["m.relates_to"]?["event_id"], + ); + final key = redacts!.content["m.relates_to"]?["key"]; + if (message == null || key == null || !ref.mounted) return; + + return await controller.updateMessage( + message, + message.copyWith( + reactions: IMap(message.reactions) + .update( + key, + (reactors) => + IList(reactors).remove(redacts.authorId).unlock, + ) + .where((_, value) => value.isNotEmpty) + .unlock, + ), + ); + } } else { final message = await ref.watch( MessageController.provider(