Skip to content

Commit

Permalink
unreads: Handle updates when there are moved messages
Browse files Browse the repository at this point in the history
Signed-off-by: Zixuan James Li <[email protected]>
  • Loading branch information
PIG208 committed Feb 24, 2025
1 parent b74c89e commit ca94f61
Show file tree
Hide file tree
Showing 2 changed files with 166 additions and 1 deletion.
20 changes: 19 additions & 1 deletion lib/model/unreads.dart
Original file line number Diff line number Diff line change
Expand Up @@ -296,13 +296,31 @@ class Unreads extends ChangeNotifier {
madeAnyUpdate |= mentions.add(messageId);
}

// TODO(#901) handle moved messages
madeAnyUpdate |= _handleMessageMove(event);

if (madeAnyUpdate) {
notifyListeners();
}
}

bool _handleMessageMove(UpdateMessageEvent event) {
if (event.moveData == null) {
// No moved messages.
return false;
}
final UpdateMessageMoveData(
:origStreamId, :newStreamId, :origTopic, :newTopic) = event.moveData!;

final messageToMoveIds = _removeAllInStreamTopic(
event.messageIds.toSet(), origStreamId, origTopic);
if (messageToMoveIds == null || messageToMoveIds.isEmpty) {
// No known unreads affected by move; nothing to do.
return false;
}
_addAllInStreamTopic(messageToMoveIds..sort(), newStreamId, newTopic);
return true;
}

void handleDeleteMessageEvent(DeleteMessageEvent event) {
mentions.removeAll(event.messageIds);
final messageIdsSet = Set.of(event.messageIds);
Expand Down
147 changes: 147 additions & 0 deletions test/model/unreads_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -469,6 +469,153 @@ void main() {
}
}
});

group('moves', () {
final origChannel = eg.stream();
const origTopic = 'origTopic';
const newTopic = 'newTopic';

group('move read messages', () {
final readMessages = List<StreamMessage>.generate(10,
(_) => eg.streamMessage(
stream: origChannel, topic: origTopic, flags: [MessageFlag.read]));

test('to new topic', () {
prepare();
fillWithMessages(readMessages);

model.handleUpdateMessageEvent(eg.updateMessageEventMoveFrom(
origMessages: readMessages,
newTopicStr: newTopic));
checkNotNotified();
checkMatchesMessages([]);
});

test('from topic with unreads', () {
prepare();
final unreadMessage = eg.streamMessage(
stream: origChannel, topic: origTopic);
fillWithMessages([...readMessages, unreadMessage]);

model.handleUpdateMessageEvent(eg.updateMessageEventMoveFrom(
origMessages: readMessages,
newTopicStr: newTopic));
checkNotNotified();
checkMatchesMessages([unreadMessage]);
});

test('to topic with unreads', () {
prepare();
final unreadMessage = eg.streamMessage(
stream: origChannel, topic: newTopic);
fillWithMessages([...readMessages, unreadMessage]);

model.handleUpdateMessageEvent(eg.updateMessageEventMoveFrom(
origMessages: readMessages,
newTopicStr: newTopic,
));
checkNotNotified();
checkMatchesMessages([unreadMessage]);
});
});

group('move unread messages', () {
final unreadMessages = List<StreamMessage>.generate(10,
(_) => eg.streamMessage(stream: origChannel, topic: origTopic));

test('to new topic', () {
prepare();
fillWithMessages(unreadMessages);

model.handleUpdateMessageEvent(eg.updateMessageEventMoveFrom(
origMessages: unreadMessages,
newTopicStr: newTopic));
checkNotifiedOnce();
checkMatchesMessages([
for (final message in unreadMessages)
Message.fromJson(message.toJson()..['subject'] = newTopic),
]);
});

test('to new channel', () {
prepare();
final newChannel = eg.stream();
fillWithMessages(unreadMessages);

model.handleUpdateMessageEvent(eg.updateMessageEventMoveFrom(
origMessages: unreadMessages,
newStreamId: newChannel.streamId));
checkNotifiedOnce();
checkMatchesMessages([
for (final message in unreadMessages)
Message.fromJson(
message.toJson()..['stream_id'] = newChannel.streamId),
]);
});

test('from topic containing other unreads', () {
prepare();
final unreadMessage = eg.streamMessage(
stream: origChannel, topic: origTopic);
fillWithMessages([...unreadMessages, unreadMessage]);

model.handleUpdateMessageEvent(eg.updateMessageEventMoveFrom(
origMessages: unreadMessages,
newTopicStr: newTopic));
checkNotifiedOnce();
checkMatchesMessages([
for (final message in unreadMessages)
Message.fromJson(message.toJson()..['subject'] = newTopic),
unreadMessage,
]);
});

test('to topic containing other unreads', () {
prepare();
final unreadMessage = eg.streamMessage(
stream: origChannel, topic: newTopic);
fillWithMessages([...unreadMessages, unreadMessage]);

model.handleUpdateMessageEvent(eg.updateMessageEventMoveFrom(
origMessages: unreadMessages,
newTopicStr: newTopic));
checkNotifiedOnce();
checkMatchesMessages([
for (final message in unreadMessages)
Message.fromJson(message.toJson()..['subject'] = newTopic),
unreadMessage,
]);
});

test('tolerate unsorted messages', () {
prepare();
final unreadMessages = List.generate(10,
(i) => eg.streamMessage(id: 1000-i, stream: origChannel, topic: origTopic));

model.handleUpdateMessageEvent(eg.updateMessageEventMoveFrom(
origMessages: unreadMessages,
newTopicStr: newTopic));
checkNotifiedOnce();
checkMatchesMessages([
for (final message in unreadMessages)
Message.fromJson(message.toJson()..['subject'] = newTopic)
]);
});

test('tolerate unreads unknown to the model', () {
prepare();
final unknownUnreadMessage = eg.streamMessage(
stream: eg.stream(), topic: origTopic);
fillWithMessages(unreadMessages);

model.handleUpdateMessageEvent(eg.updateMessageEventMoveFrom(
origMessages: [unknownUnreadMessage],
newTopicStr: newTopic));
checkNotNotified();
checkMatchesMessages(unreadMessages);
});
});
});
});


Expand Down

0 comments on commit ca94f61

Please sign in to comment.