Skip to content

Commit d6b001c

Browse files
committed
message: Mutate messages for flags events here, instead of in msglists
Like a recent commit did for message edits, and one before that did for reactions, this fixes the part of #455 that's concerned with update-message-flags events. Like in the commit that dealt with message edits, this fixes the symptom of a dropped update when there are zero message lists open. In this case I'm *pretty* sure there wasn't a user-facing symptom with the double-processing situation when the message is in two or more open message lists. That's because I believe we don't give different behavior for a flag that's present multiple times in the `flags` list, vs. just once.
1 parent 574fd85 commit d6b001c

File tree

3 files changed

+84
-32
lines changed

3 files changed

+84
-32
lines changed

lib/model/message.dart

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -133,8 +133,36 @@ class MessageStoreImpl with MessageStore {
133133
}
134134

135135
void handleUpdateMessageFlagsEvent(UpdateMessageFlagsEvent event) {
136-
for (final view in _messageListViews) {
137-
view.handleUpdateMessageFlagsEvent(event); // TODO update mainly in [messages] instead
136+
final isAdd = switch (event) {
137+
UpdateMessageFlagsAddEvent() => true,
138+
UpdateMessageFlagsRemoveEvent() => false,
139+
};
140+
141+
if (isAdd && (event as UpdateMessageFlagsAddEvent).all) {
142+
for (final message in messages.values) {
143+
message.flags.add(event.flag);
144+
}
145+
146+
for (final view in _messageListViews) {
147+
if (view.messages.isEmpty) continue;
148+
view.notifyListeners();
149+
}
150+
} else {
151+
bool anyMessageFound = false;
152+
for (final messageId in event.messages) {
153+
final message = messages[messageId];
154+
if (message == null) continue; // a message we don't know about yet
155+
anyMessageFound = true;
156+
157+
isAdd
158+
? message.flags.add(event.flag)
159+
: message.flags.remove(event.flag);
160+
}
161+
if (anyMessageFound) {
162+
for (final view in _messageListViews) {
163+
view.notifyListenersIfAnyMessagePresent(event.messages);
164+
}
165+
}
138166
}
139167
}
140168

lib/model/message_list.dart

Lines changed: 15 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -444,6 +444,13 @@ class MessageListView with ChangeNotifier, _MessageSequence {
444444
notifyListeners();
445445
}
446446

447+
// Repeal the `@protected` annotation that applies on the base implementation,
448+
// so we can call this method from [MessageStoreImpl].
449+
@override
450+
void notifyListeners() {
451+
super.notifyListeners();
452+
}
453+
447454
/// Notify listeners if the given message is present in this view.
448455
void notifyListenersIfMessagePresent(int messageId) {
449456
final index = _findMessageWithId(messageId);
@@ -452,6 +459,14 @@ class MessageListView with ChangeNotifier, _MessageSequence {
452459
}
453460
}
454461

462+
/// Notify listeners if any of the given messages is present in this view.
463+
void notifyListenersIfAnyMessagePresent(Iterable<int> messageIds) {
464+
final isAnyPresent = messageIds.any((id) => _findMessageWithId(id) != -1);
465+
if (isAnyPresent) {
466+
notifyListeners();
467+
}
468+
}
469+
455470
void messageContentChanged(int messageId) {
456471
final index = _findMessageWithId(messageId);
457472
if (index != -1) {
@@ -460,35 +475,6 @@ class MessageListView with ChangeNotifier, _MessageSequence {
460475
}
461476
}
462477

463-
void handleUpdateMessageFlagsEvent(UpdateMessageFlagsEvent event) {
464-
final isAdd = switch (event) {
465-
UpdateMessageFlagsAddEvent() => true,
466-
UpdateMessageFlagsRemoveEvent() => false,
467-
};
468-
469-
bool didUpdateAny = false;
470-
if (isAdd && (event as UpdateMessageFlagsAddEvent).all) {
471-
for (final message in messages) {
472-
message.flags.add(event.flag);
473-
didUpdateAny = true;
474-
}
475-
} else {
476-
for (final messageId in event.messages) {
477-
final index = _findMessageWithId(messageId);
478-
if (index != -1) {
479-
final message = messages[index];
480-
isAdd ? message.flags.add(event.flag) : message.flags.remove(event.flag);
481-
didUpdateAny = true;
482-
}
483-
}
484-
}
485-
if (!didUpdateAny) {
486-
return;
487-
}
488-
489-
notifyListeners();
490-
}
491-
492478
/// Called when the app is reassembled during debugging, e.g. for hot reload.
493479
///
494480
/// This will redo from scratch any computations we can, such as parsing

test/model/message_list_test.dart

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -306,6 +306,33 @@ void main() {
306306
});
307307
});
308308

309+
group('notifyListenersIfAnyMessagePresent', () {
310+
final messages = List.generate(100, (i) => eg.streamMessage(id: 100 + i));
311+
312+
test('all messages present', () async {
313+
await prepare(narrow: const CombinedFeedNarrow());
314+
await prepareMessages(foundOldest: false, messages: messages);
315+
model.notifyListenersIfAnyMessagePresent([150, 151, 152]);
316+
checkNotifiedOnce();
317+
});
318+
319+
test('some messages present', () async {
320+
await prepare(narrow: const CombinedFeedNarrow());
321+
await prepareMessages(foundOldest: false,
322+
messages: messages.where((m) => m.id != 151).toList());
323+
model.notifyListenersIfAnyMessagePresent([150, 151, 152]);
324+
checkNotifiedOnce();
325+
});
326+
327+
test('no messages present', () async {
328+
await prepare(narrow: const CombinedFeedNarrow());
329+
await prepareMessages(foundOldest: false, messages:
330+
messages.where((m) => ![150, 151, 152].contains(m.id)).toList());
331+
model.notifyListenersIfAnyMessagePresent([150, 151, 152]);
332+
checkNotNotified();
333+
});
334+
});
335+
309336
group('messageContentChanged', () {
310337
test('message present', () async {
311338
await prepare(narrow: const CombinedFeedNarrow());
@@ -428,7 +455,18 @@ void main() {
428455
);
429456
});
430457

431-
// TODO(#455) message flags
458+
test('UpdateMessageFlagsEvent is applied even when message not in any msglists', () async {
459+
await checkApplied(
460+
mkEvent: (message) => UpdateMessageFlagsAddEvent(
461+
id: 1,
462+
flag: MessageFlag.starred,
463+
messages: [message.id],
464+
all: false,
465+
),
466+
doCheckMessageAfterFetch:
467+
(messageSubject) => messageSubject.flags.contains(MessageFlag.starred),
468+
);
469+
});
432470
});
433471

434472
test('reassemble', () async {

0 commit comments

Comments
 (0)