From 65234201201c35a4d14900bd562f1195c6c125ab Mon Sep 17 00:00:00 2001 From: Henry-Hiles Date: Sun, 23 Nov 2025 16:56:42 -0500 Subject: [PATCH] add edits --- lib/controllers/room_chat_controller.dart | 25 ++++++++++++++++------- lib/helpers/extension_helper.dart | 14 ++++++++++++- lib/widgets/chat_page/room_chat.dart | 23 ++++++++++++++------- 3 files changed, 47 insertions(+), 15 deletions(-) diff --git a/lib/controllers/room_chat_controller.dart b/lib/controllers/room_chat_controller.dart index 312a6c9..b06c311 100644 --- a/lib/controllers/room_chat_controller.dart +++ b/lib/controllers/room_chat_controller.dart @@ -19,17 +19,28 @@ class RoomChatController extends AsyncNotifier { if (event.roomId != room.id) return; final message = await event.toMessage(); if (message != null) { - await insertMessage(message); + if (event.relationshipType == RelationshipTypes.edit) { + final controller = await future; + final oldMessage = controller.messages.firstWhereOrNull( + (element) => element.id == event.relationshipEventId, + ); + if (oldMessage == null) return; + await updateMessage(oldMessage, message); + } else { + await insertMessage(message); + } } }).cancel, ); - return InMemoryChatController( - messages: (await Future.wait( - response.chunk.map( - (event) => Event.fromMatrixEvent(event, room).toMessage(), - ), - )).nonNulls.toList().reversed.toList(), + messages: { + for (var msg in (await Future.wait( + response.chunk.map( + (event) => Event.fromMatrixEvent(event, room).toMessage(), + ), + )).nonNulls.toList().reversed.toList()) + msg.id: msg, + }.values.toList(), ); } diff --git a/lib/helpers/extension_helper.dart b/lib/helpers/extension_helper.dart index 8c5f9fa..af5d0e7 100644 --- a/lib/helpers/extension_helper.dart +++ b/lib/helpers/extension_helper.dart @@ -40,13 +40,24 @@ extension ToMessage on Event { ? relationshipEventId : null; final sender = (await fetchSenderUser()) ?? senderFromMemoryOrFallback; + + final newContent = content["m.new_content"] as Map?; final metadata = { - "formatted": formattedText.isEmpty ? body : formattedText, + "formatted": + newContent?["formatted_body"] ?? + newContent?["body"] ?? + (formattedText.isEmpty ? this.body : formattedText), "eventType": type, "displayName": sender.displayName ?? sender.id, "txnId": transactionId, }; + final editedAt = relationshipType == RelationshipTypes.edit + ? originServerTs + : null; + final body = newContent?["body"] as String? ?? this.body; + final eventId = relationshipEventId ?? this.eventId; + if (redacted) return null; final asText = @@ -57,6 +68,7 @@ extension ToMessage on Event { text: body, replyToMessageId: replyId, deliveredAt: originServerTs, + editedAt: editedAt, ) as TextMessage; diff --git a/lib/widgets/chat_page/room_chat.dart b/lib/widgets/chat_page/room_chat.dart index 05b1e89..4ab8442 100644 --- a/lib/widgets/chat_page/room_chat.dart +++ b/lib/widgets/chat_page/room_chat.dart @@ -136,13 +136,16 @@ class RoomChat extends HookConsumerWidget { }) => FlyerChatTextMessage( customWidget: HtmlWidget( message.metadata?["formatted"].replaceAllMapped( - RegExp( - r'(?)(https?:\/\/[^\s<]+)', - caseSensitive: false, - ), - (m) => - "${m.group(0)!}", - ), + RegExp( + r'(?)(https?:\/\/[^\s<]+)', + caseSensitive: false, + ), + (m) => + "${m.group(0)!}", + ) + + ((message.editedAt != null) + ? "(edited)" + : ""), customWidgetBuilder: (element) { if (element.localName == "mx-reply") { return SizedBox.shrink(); @@ -193,11 +196,17 @@ class RoomChat extends HookConsumerWidget { "color", value, ), + "data-mx-bg-color" => MapEntry( "background-color", value, ), + + "edited" => MapEntry( + "display", + "block", + ), _ => null, }, )