Skip to content

Commit 0755784

Browse files
committed
message: Update all edit timestamps on UpdateMessageEvent
This is equivalent for a content edit (where there's just one message affected), but differs when multiple messages are affected, as can happen with a message move.
1 parent d52f60f commit 0755784

File tree

3 files changed

+50
-8
lines changed

3 files changed

+50
-8
lines changed

lib/model/message.dart

+18-7
Original file line numberDiff line numberDiff line change
@@ -93,32 +93,43 @@ class MessageStoreImpl with MessageStore {
9393
}
9494

9595
void handleUpdateMessageEvent(UpdateMessageEvent event) {
96+
assert(event.messageIds.contains(event.messageId), "See https://github.com/zulip/zulip-flutter/pull/753#discussion_r1649463633");
97+
_handleUpdateMessageEventTimestamp(event);
9698
_handleUpdateMessageEventContent(event);
9799
// TODO(#150): Handle message moves. The views' recipient headers
98100
// may need updating, and consequently showSender too.
101+
for (final view in _messageListViews) {
102+
view.notifyListenersIfAnyMessagePresent(event.messageIds);
103+
}
99104
}
100105

101-
void _handleUpdateMessageEventContent(UpdateMessageEvent event) {
102-
final message = messages[event.messageId];
103-
if (message == null) return;
104-
106+
void _handleUpdateMessageEventTimestamp(UpdateMessageEvent event) {
105107
// TODO(server-5): Cut this fallback; rely on renderingOnly from FL 114
106108
final isRenderingOnly = event.renderingOnly ?? (event.userId == null);
107-
if (event.editTimestamp != null && !isRenderingOnly) {
109+
if (event.editTimestamp == null || isRenderingOnly) {
108110
// A rendering-only update gets omitted from the message edit history,
109111
// and [Message.lastEditTimestamp] is the last timestamp of that history.
110112
// So on a rendering-only update, the timestamp doesn't get updated.
113+
return;
114+
}
115+
116+
for (final messageId in event.messageIds) {
117+
final message = messages[messageId];
118+
if (message == null) continue;
111119
message.lastEditTimestamp = event.editTimestamp;
112120
}
121+
}
113122

114-
message.flags = event.flags;
123+
void _handleUpdateMessageEventContent(UpdateMessageEvent event) {
124+
final message = messages[event.messageId];
125+
if (message == null) return;
115126

127+
message.flags = event.flags;
116128
if (event.renderedContent != null) {
117129
assert(message.contentType == 'text/html',
118130
"Message contentType was ${message.contentType}; expected text/html.");
119131
message.content = event.renderedContent!;
120132
}
121-
122133
if (event.isMeMessage != null) {
123134
message.isMeMessage = event.isMeMessage!;
124135
}

lib/model/message_list.dart

+4-1
Original file line numberDiff line numberDiff line change
@@ -467,11 +467,14 @@ class MessageListView with ChangeNotifier, _MessageSequence {
467467
}
468468
}
469469

470+
/// Update data derived from the content of the given message.
471+
///
472+
/// This does not notify listeners.
473+
/// The caller should ensure that happens later.
470474
void messageContentChanged(int messageId) {
471475
final index = _findMessageWithId(messageId);
472476
if (index != -1) {
473477
_reparseContent(index);
474-
notifyListeners();
475478
}
476479
}
477480

test/model/message_test.dart

+28
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,34 @@ void main() {
162162
});
163163

164164
group('handleUpdateMessageEvent', () {
165+
test('update timestamps on all messages', () async {
166+
const t1 = 1718748879;
167+
const t2 = t1 + 60;
168+
final message1 = eg.streamMessage(lastEditTimestamp: null);
169+
final message2 = eg.streamMessage(lastEditTimestamp: t1);
170+
// This event is a bit artificial, but convenient.
171+
// TODO use a realistic move-messages event here
172+
final updateEvent = Event.fromJson({
173+
...eg.updateMessageEditEvent(message1).toJson(),
174+
'message_ids': [message1.id, message2.id],
175+
'edit_timestamp': t2,
176+
}) as UpdateMessageEvent;
177+
await prepare();
178+
await prepareMessages([message1, message2]);
179+
180+
check(store).messages.values.unorderedMatches(<Condition<Message>>[
181+
(it) => it.lastEditTimestamp.isNull,
182+
(it) => it.lastEditTimestamp.equals(t1),
183+
]);
184+
185+
await store.handleEvent(updateEvent);
186+
checkNotifiedOnce();
187+
check(store).messages.values.unorderedMatches(<Condition<Message>>[
188+
(it) => it.lastEditTimestamp.equals(t2),
189+
(it) => it.lastEditTimestamp.equals(t2),
190+
]);
191+
});
192+
165193
test('update a message', () async {
166194
final originalMessage = eg.streamMessage(
167195
content: "<p>Hello, world</p>");

0 commit comments

Comments
 (0)