Skip to content

Commit 42d8b32

Browse files
committed
msglist: Show recipient headers on all messages, in Mentions / Starred
Fixes: #1637
1 parent 080a7e5 commit 42d8b32

File tree

2 files changed

+74
-1
lines changed

2 files changed

+74
-1
lines changed

lib/model/message_list.dart

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,18 @@ enum FetchingStatus {
105105
///
106106
/// This comprises much of the guts of [MessageListView].
107107
mixin _MessageSequence {
108+
/// Whether each message should have its own recipient header,
109+
/// even if it's in the same conversation as the previous message.
110+
///
111+
/// In some message-list views, notably "Mentions" and "Starred",
112+
/// it would be misleading to give the impression that consecutive messages
113+
/// in the same conversation were sent one after the other
114+
/// with no other messages in between.
115+
/// By giving each message its own recipient header (a `true` value for this),
116+
/// we intend to avoid giving that impression.
117+
@visibleForTesting
118+
bool get oneMessagePerBlock;
119+
108120
/// A sequence number for invalidating stale fetches.
109121
int generation = 0;
110122

@@ -435,7 +447,11 @@ mixin _MessageSequence {
435447
required MessageListMessageBaseItem Function(bool canShareSender) buildItem,
436448
}) {
437449
final bool canShareSender;
438-
if (prevMessage == null || !haveSameRecipient(prevMessage, message)) {
450+
if (
451+
prevMessage == null
452+
|| oneMessagePerBlock
453+
|| !haveSameRecipient(prevMessage, message)
454+
) {
439455
items.add(MessageListRecipientHeaderItem(message));
440456
canShareSender = false;
441457
} else {
@@ -623,6 +639,15 @@ class MessageListView with ChangeNotifier, _MessageSequence {
623639
super.dispose();
624640
}
625641

642+
@override bool get oneMessagePerBlock => switch (narrow) {
643+
CombinedFeedNarrow()
644+
|| ChannelNarrow()
645+
|| TopicNarrow()
646+
|| DmNarrow() => false,
647+
MentionsNarrow()
648+
|| StarredMessagesNarrow() => true,
649+
};
650+
626651
/// Whether [message] should actually appear in this message list,
627652
/// given that it does belong to the narrow.
628653
///

test/model/message_list_test.dart

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2742,6 +2742,53 @@ void main() {
27422742
checkNotifiedOnce();
27432743
}));
27442744

2745+
group('one message per block?', () {
2746+
final channelId = 1;
2747+
final topic = 'some topic';
2748+
void doTest({required Narrow narrow, required bool expected}) {
2749+
test('$narrow: ${expected ? 'yes' : 'no'}', () => awaitFakeAsync((async) async {
2750+
final sender = eg.user();
2751+
final channel = eg.stream(streamId: channelId);
2752+
final message1 = eg.streamMessage(
2753+
sender: sender,
2754+
stream: channel,
2755+
topic: topic,
2756+
flags: [MessageFlag.starred, MessageFlag.mentioned],
2757+
);
2758+
final message2 = eg.streamMessage(
2759+
sender: sender,
2760+
stream: channel,
2761+
topic: topic,
2762+
flags: [MessageFlag.starred, MessageFlag.mentioned],
2763+
);
2764+
2765+
await prepare(
2766+
narrow: narrow,
2767+
stream: channel,
2768+
);
2769+
connection.prepare(json: newestResult(
2770+
foundOldest: false,
2771+
messages: [message1, message2],
2772+
).toJson());
2773+
await model.fetchInitial();
2774+
checkNotifiedOnce();
2775+
2776+
check(model).items.deepEquals(<Condition<Object?>>[
2777+
(it) => it.isA<MessageListRecipientHeaderItem>(),
2778+
(it) => it.isA<MessageListMessageItem>(),
2779+
if (expected) (it) => it.isA<MessageListRecipientHeaderItem>(),
2780+
(it) => it.isA<MessageListMessageItem>(),
2781+
]);
2782+
}));
2783+
}
2784+
2785+
doTest(narrow: CombinedFeedNarrow(), expected: false);
2786+
doTest(narrow: ChannelNarrow(channelId), expected: false);
2787+
doTest(narrow: TopicNarrow(channelId, eg.t(topic)), expected: false);
2788+
doTest(narrow: StarredMessagesNarrow(), expected: true);
2789+
doTest(narrow: MentionsNarrow(), expected: true);
2790+
});
2791+
27452792
test('showSender is maintained correctly', () => awaitFakeAsync((async) async {
27462793
// TODO(#150): This will get more complicated with message moves.
27472794
// Until then, we always compute this sequentially from oldest to newest.
@@ -3011,6 +3058,7 @@ void checkInvariants(MessageListView model) {
30113058
for (int j = 0; j < allMessages.length; j++) {
30123059
bool forcedShowSender = false;
30133060
if (j == 0
3061+
|| model.oneMessagePerBlock
30143062
|| !haveSameRecipient(allMessages[j-1], allMessages[j])) {
30153063
check(model.items[i++]).isA<MessageListRecipientHeaderItem>()
30163064
.message.identicalTo(allMessages[j]);

0 commit comments

Comments
 (0)