Skip to content

Commit 41104fa

Browse files
committed
msglist [nfc]: Migrate most MessageListItem subclasses to use MessageBase
except MessageListMessageItem. This keeps changes minimal, leaving most of the helpers in lib/model/message_list.dart untouched, to avoid unnecessary generalization. This hoists streamId in StreamMessageRecipientHeader.build, where we used to access streamId via message instead from the onLongPress callback. Because Message.streamId only changes on message moves, we expect the build method to be called again, so this should be fine.
1 parent 70eb57a commit 41104fa

File tree

4 files changed

+37
-29
lines changed

4 files changed

+37
-29
lines changed

lib/model/message_list.dart

+4-3
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,13 @@ sealed class MessageListItem {
2424
}
2525

2626
class MessageListRecipientHeaderItem extends MessageListItem {
27-
final Message message;
27+
final MessageBase message;
2828

2929
MessageListRecipientHeaderItem(this.message);
3030
}
3131

3232
class MessageListDateSeparatorItem extends MessageListItem {
33-
final Message message;
33+
final MessageBase message;
3434

3535
MessageListDateSeparatorItem(this.message);
3636
}
@@ -155,7 +155,8 @@ mixin _MessageSequence {
155155
}
156156
case MessageListRecipientHeaderItem(:var message):
157157
case MessageListDateSeparatorItem(:var message):
158-
return (message.id <= messageId) ? -1 : 1;
158+
if (message.id == null) return 1;
159+
return message.id! <= messageId ? -1 : 1;
159160
case MessageListMessageItem(:var message): return message.id.compareTo(messageId);
160161
}
161162
}

lib/model/narrow.dart

+6-4
Original file line numberDiff line numberDiff line change
@@ -94,8 +94,8 @@ class ChannelNarrow extends Narrow {
9494
class TopicNarrow extends Narrow implements SendableNarrow {
9595
const TopicNarrow(this.streamId, this.topic, {this.with_});
9696

97-
factory TopicNarrow.ofMessage(StreamMessage message) {
98-
return TopicNarrow(message.streamId, message.topic);
97+
factory TopicNarrow.ofMessage(MessageBase<StreamConversation> message) {
98+
return TopicNarrow(message.conversation.streamId, message.conversation.topic);
9999
}
100100

101101
final int streamId;
@@ -194,9 +194,11 @@ class DmNarrow extends Narrow implements SendableNarrow {
194194
);
195195
}
196196

197-
factory DmNarrow.ofMessage(DmMessage message, {required int selfUserId}) {
197+
factory DmNarrow.ofMessage(MessageBase<DmConversation> message, {
198+
required int selfUserId,
199+
}) {
198200
return DmNarrow(
199-
allRecipientIds: List.unmodifiable(message.allRecipientIds),
201+
allRecipientIds: List.unmodifiable(message.conversation.allRecipientIds),
200202
selfUserId: selfUserId,
201203
);
202204
}

lib/widgets/message_list.dart

+25-20
Original file line numberDiff line numberDiff line change
@@ -901,23 +901,27 @@ class _MarkAsReadAnimationState extends State<MarkAsReadAnimation> {
901901
class RecipientHeader extends StatelessWidget {
902902
const RecipientHeader({super.key, required this.message, required this.narrow});
903903

904-
final Message message;
904+
final MessageBase message;
905905
final Narrow narrow;
906906

907907
@override
908908
Widget build(BuildContext context) {
909909
final message = this.message;
910910
return switch (message) {
911-
StreamMessage() => StreamMessageRecipientHeader(message: message, narrow: narrow),
912-
DmMessage() => DmRecipientHeader(message: message, narrow: narrow),
911+
MessageBase<StreamConversation>() =>
912+
StreamMessageRecipientHeader(message: message, narrow: narrow),
913+
MessageBase<DmConversation>() =>
914+
DmRecipientHeader(message: message, narrow: narrow),
915+
MessageBase<Conversation>() =>
916+
throw StateError('Bad concrete subclass of MessageBase'),
913917
};
914918
}
915919
}
916920

917921
class DateSeparator extends StatelessWidget {
918922
const DateSeparator({super.key, required this.message});
919923

920-
final Message message;
924+
final MessageBase message;
921925

922926
@override
923927
Widget build(BuildContext context) {
@@ -1027,7 +1031,7 @@ class StreamMessageRecipientHeader extends StatelessWidget {
10271031
required this.narrow,
10281032
});
10291033

1030-
final StreamMessage message;
1034+
final MessageBase<StreamConversation> message;
10311035
final Narrow narrow;
10321036

10331037
static bool _containsDifferentChannels(Narrow narrow) {
@@ -1053,11 +1057,11 @@ class StreamMessageRecipientHeader extends StatelessWidget {
10531057
final designVariables = DesignVariables.of(context);
10541058
final zulipLocalizations = ZulipLocalizations.of(context);
10551059

1056-
final topic = message.topic;
1060+
final StreamConversation(:streamId, :topic) = message.conversation;
10571061

10581062
final messageListTheme = MessageListTheme.of(context);
10591063

1060-
final subscription = store.subscriptions[message.streamId];
1064+
final subscription = store.subscriptions[streamId];
10611065
final Color backgroundColor;
10621066
final Color iconColor;
10631067
if (subscription != null) {
@@ -1073,16 +1077,16 @@ class StreamMessageRecipientHeader extends StatelessWidget {
10731077
if (!_containsDifferentChannels(narrow)) {
10741078
streamWidget = const SizedBox(width: 16);
10751079
} else {
1076-
final stream = store.streams[message.streamId];
1080+
final stream = store.streams[streamId];
10771081
final streamName = stream?.name
10781082
?? message.conversation.displayRecipient
10791083
?? zulipLocalizations.unknownChannelName; // TODO(log)
10801084

10811085
streamWidget = GestureDetector(
10821086
onTap: () => Navigator.push(context,
10831087
MessageListPage.buildRoute(context: context,
1084-
narrow: ChannelNarrow(message.streamId))),
1085-
onLongPress: () => showChannelActionSheet(context, channelId: message.streamId),
1088+
narrow: ChannelNarrow(streamId))),
1089+
onLongPress: () => showChannelActionSheet(context, channelId: streamId),
10861090
child: Row(
10871091
crossAxisAlignment: CrossAxisAlignment.center,
10881092
children: [
@@ -1130,7 +1134,7 @@ class StreamMessageRecipientHeader extends StatelessWidget {
11301134
Icon(size: 14, color: designVariables.title.withFadedAlpha(0.5),
11311135
// A null [Icon.icon] makes a blank space.
11321136
iconDataForTopicVisibilityPolicy(
1133-
store.topicVisibilityPolicy(message.streamId, topic))),
1137+
store.topicVisibilityPolicy(streamId, topic))),
11341138
]));
11351139

11361140
return GestureDetector(
@@ -1143,7 +1147,7 @@ class StreamMessageRecipientHeader extends StatelessWidget {
11431147
MessageListPage.buildRoute(context: context,
11441148
narrow: TopicNarrow.ofMessage(message))),
11451149
onLongPress: () => showTopicActionSheet(context,
1146-
channelId: message.streamId,
1150+
channelId: streamId,
11471151
topic: topic,
11481152
someMessageIdInTopic: message.id),
11491153
child: ColoredBox(
@@ -1168,20 +1172,21 @@ class DmRecipientHeader extends StatelessWidget {
11681172
required this.narrow,
11691173
});
11701174

1171-
final DmMessage message;
1175+
final MessageBase<DmConversation> message;
11721176
final Narrow narrow;
11731177

11741178
@override
11751179
Widget build(BuildContext context) {
11761180
final zulipLocalizations = ZulipLocalizations.of(context);
11771181
final store = PerAccountStoreWidget.of(context);
11781182
final String title;
1179-
if (message.allRecipientIds.length > 1) {
1180-
title = zulipLocalizations.messageListGroupYouAndOthers(message.allRecipientIds
1181-
.where((id) => id != store.selfUserId)
1182-
.map(store.userDisplayName)
1183-
.sorted()
1184-
.join(", "));
1183+
if (message.conversation.allRecipientIds.length > 1) {
1184+
title = zulipLocalizations.messageListGroupYouAndOthers(
1185+
message.conversation.allRecipientIds
1186+
.where((id) => id != store.selfUserId)
1187+
.map(store.userDisplayName)
1188+
.sorted()
1189+
.join(", "));
11851190
} else {
11861191
title = zulipLocalizations.messageListGroupYouWithYourself;
11871192
}
@@ -1233,7 +1238,7 @@ TextStyle recipientHeaderTextStyle(BuildContext context, {FontStyle? fontStyle})
12331238
class RecipientHeaderDate extends StatelessWidget {
12341239
const RecipientHeaderDate({super.key, required this.message});
12351240

1236-
final Message message;
1241+
final MessageBase message;
12371242

12381243
@override
12391244
Widget build(BuildContext context) {

test/model/message_list_test.dart

+2-2
Original file line numberDiff line numberDiff line change
@@ -1994,11 +1994,11 @@ void checkInvariants(MessageListView model) {
19941994
}
19951995

19961996
extension MessageListRecipientHeaderItemChecks on Subject<MessageListRecipientHeaderItem> {
1997-
Subject<Message> get message => has((x) => x.message, 'message');
1997+
Subject<MessageBase> get message => has((x) => x.message, 'message');
19981998
}
19991999

20002000
extension MessageListDateSeparatorItemChecks on Subject<MessageListDateSeparatorItem> {
2001-
Subject<Message> get message => has((x) => x.message, 'message');
2001+
Subject<MessageBase> get message => has((x) => x.message, 'message');
20022002
}
20032003

20042004
extension MessageListMessageItemChecks on Subject<MessageListMessageItem> {

0 commit comments

Comments
 (0)