diff --git a/lib/api/model/model.dart b/lib/api/model/model.dart index 6dbdec8d13f..e7e81495016 100644 --- a/lib/api/model/model.dart +++ b/lib/api/model/model.dart @@ -250,13 +250,13 @@ class Subscription { sealed class Message { final String? avatarUrl; final String client; - final String content; + String content; final String contentType; // final List editHistory; // TODO handle final int id; - final bool isMeMessage; - final int? lastEditTimestamp; + bool isMeMessage; + int? lastEditTimestamp; // final List reactions; // TODO handle final int recipientId; @@ -271,7 +271,7 @@ sealed class Message { // final List topicLinks; // TODO handle // final string type; // handled by runtime type of object - final List flags; // TODO enum + List flags; // TODO enum final String? matchContent; final String? matchSubject; diff --git a/lib/model/message_list.dart b/lib/model/message_list.dart index 952b00ebbd4..09b1a0ab169 100644 --- a/lib/model/message_list.dart +++ b/lib/model/message_list.dart @@ -1,5 +1,7 @@ +import 'package:collection/collection.dart'; import 'package:flutter/foundation.dart'; +import '../api/model/events.dart'; import '../api/model/model.dart'; import '../api/route/messages.dart'; import 'content.dart'; @@ -86,6 +88,67 @@ class MessageListView extends ChangeNotifier { notifyListeners(); } + applyChangesToMessage(UpdateMessageEvent event, Message message) { + if (event.renderingOnly != null && event.renderingOnly == true) { + //TODO update inline preview + return; + } + + if (!event.flags.equals(message.flags)) { + //TODO Possibly a new @alert on this message. Update alerts. + message.flags = event.flags; + } + + if (event.renderedContent != null) { + message.content = event.renderedContent as String; + } + + if (event.editTimestamp != null) { + message.lastEditTimestamp = event.editTimestamp; + } + + if (event.isMeMessage != null) { + message.isMeMessage = event.isMeMessage as bool; + } + + } + + ///This is almost directly copied from package:collection/algorithms.dart. + ///The way that package was set up doesn't allow us to search + ///for a message ID among a bunch of message objects - this is a quick + ///modification of that method to work here for us. + int findMessageWithId(int messageId) { + var min = 0; + var max = messages.length; + + while (min < max) { + var mid = min + ((max - min) >> 1); + Message message = messages[mid]; + var comp = message.id.compareTo(messageId); + if (comp == 0) return mid; + if (comp < 0) { + min = mid + 1; + } else { + max = mid; + } + } + return -1; +} + + void maybeUpdateMessage(UpdateMessageEvent event) { + int idx = findMessageWithId(event.messageId); + + if (idx == -1) { + return; + } + + Message message = messages[idx]; + applyChangesToMessage(event, message); + + contents[idx] = parseContent(message.content); + notifyListeners(); + } + /// Called when the app is reassembled during debugging, e.g. for hot reload. /// /// This will redo from scratch any computations we can, such as parsing diff --git a/lib/model/store.dart b/lib/model/store.dart index d9de7200207..f5121f3da82 100644 --- a/lib/model/store.dart +++ b/lib/model/store.dart @@ -272,7 +272,9 @@ class PerAccountStore extends ChangeNotifier { } } else if (event is UpdateMessageEvent) { assert(debugLog("server event: update_message ${event.messageId}")); - // TODO handle + for (final view in _messageListViews) { + view.maybeUpdateMessage(event); + } } else if (event is DeleteMessageEvent) { assert(debugLog("server event: delete_message ${event.messageIds}")); // TODO handle