Skip to content

Commit 975aa38

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 9539503 commit 975aa38

File tree

4 files changed

+41
-32
lines changed

4 files changed

+41
-32
lines changed

lib/model/message_list.dart

+3-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,7 @@ mixin _MessageSequence {
155155
}
156156
case MessageListRecipientHeaderItem(:var message):
157157
case MessageListDateSeparatorItem(:var message):
158-
return (message.id <= messageId) ? -1 : 1;
158+
return message.id != null && message.id! <= messageId ? -1 : 1;
159159
case MessageListMessageItem(:var message): return message.id.compareTo(messageId);
160160
}
161161
}

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<StreamRecipient> message) {
98+
return TopicNarrow(message.recipient.streamId, message.recipient.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<DmRecipient> message, {
198+
required int selfUserId,
199+
}) {
198200
return DmNarrow(
199-
allRecipientIds: List.unmodifiable(message.allRecipientIds),
201+
allRecipientIds: List.unmodifiable(message.recipient.allRecipientIds),
200202
selfUserId: selfUserId,
201203
);
202204
}

lib/widgets/message_list.dart

+30-23
Original file line numberDiff line numberDiff line change
@@ -901,23 +901,28 @@ 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;
910-
return switch (message) {
911-
StreamMessage() => StreamMessageRecipientHeader(message: message, narrow: narrow),
912-
DmMessage() => DmRecipientHeader(message: message, narrow: narrow),
913-
};
910+
switch (message) {
911+
case MessageBase<StreamRecipient>():
912+
return StreamMessageRecipientHeader(message: message, narrow: narrow);
913+
case MessageBase<DmRecipient>():
914+
return DmRecipientHeader(message: message, narrow: narrow);
915+
case MessageBase<Recipient>():
916+
assert(false, 'Unexpected concrete subclass of MessageBase<MessageDestination>');
917+
return SizedBox.shrink();
918+
}
914919
}
915920
}
916921

917922
class DateSeparator extends StatelessWidget {
918923
const DateSeparator({super.key, required this.message});
919924

920-
final Message message;
925+
final MessageBase message;
921926

922927
@override
923928
Widget build(BuildContext context) {
@@ -1027,7 +1032,7 @@ class StreamMessageRecipientHeader extends StatelessWidget {
10271032
required this.narrow,
10281033
});
10291034

1030-
final StreamMessage message;
1035+
final MessageBase<StreamRecipient> message;
10311036
final Narrow narrow;
10321037

10331038
static bool _containsDifferentChannels(Narrow narrow) {
@@ -1053,11 +1058,11 @@ class StreamMessageRecipientHeader extends StatelessWidget {
10531058
final designVariables = DesignVariables.of(context);
10541059
final zulipLocalizations = ZulipLocalizations.of(context);
10551060

1056-
final topic = message.topic;
1061+
final StreamRecipient(:streamId, :topic) = message.recipient;
10571062

10581063
final messageListTheme = MessageListTheme.of(context);
10591064

1060-
final subscription = store.subscriptions[message.streamId];
1065+
final subscription = store.subscriptions[streamId];
10611066
final Color backgroundColor;
10621067
final Color iconColor;
10631068
if (subscription != null) {
@@ -1073,16 +1078,17 @@ class StreamMessageRecipientHeader extends StatelessWidget {
10731078
if (!_containsDifferentChannels(narrow)) {
10741079
streamWidget = const SizedBox(width: 16);
10751080
} else {
1076-
final stream = store.streams[message.streamId];
1081+
final stream = store.streams[streamId];
1082+
final message = this.message;
10771083
final streamName = stream?.name
1078-
?? message.displayRecipient
1084+
?? (message is StreamMessage ? message.displayRecipient : null)
10791085
?? zulipLocalizations.unknownChannelName; // TODO(log)
10801086

10811087
streamWidget = GestureDetector(
10821088
onTap: () => Navigator.push(context,
10831089
MessageListPage.buildRoute(context: context,
1084-
narrow: ChannelNarrow(message.streamId))),
1085-
onLongPress: () => showChannelActionSheet(context, channelId: message.streamId),
1090+
narrow: ChannelNarrow(streamId))),
1091+
onLongPress: () => showChannelActionSheet(context, channelId: streamId),
10861092
child: Row(
10871093
crossAxisAlignment: CrossAxisAlignment.center,
10881094
children: [
@@ -1130,7 +1136,7 @@ class StreamMessageRecipientHeader extends StatelessWidget {
11301136
Icon(size: 14, color: designVariables.title.withFadedAlpha(0.5),
11311137
// A null [Icon.icon] makes a blank space.
11321138
iconDataForTopicVisibilityPolicy(
1133-
store.topicVisibilityPolicy(message.streamId, topic))),
1139+
store.topicVisibilityPolicy(streamId, topic))),
11341140
]));
11351141

11361142
return GestureDetector(
@@ -1143,7 +1149,7 @@ class StreamMessageRecipientHeader extends StatelessWidget {
11431149
MessageListPage.buildRoute(context: context,
11441150
narrow: TopicNarrow.ofMessage(message))),
11451151
onLongPress: () => showTopicActionSheet(context,
1146-
channelId: message.streamId,
1152+
channelId: streamId,
11471153
topic: topic,
11481154
someMessageIdInTopic: message.id),
11491155
child: ColoredBox(
@@ -1168,20 +1174,21 @@ class DmRecipientHeader extends StatelessWidget {
11681174
required this.narrow,
11691175
});
11701176

1171-
final DmMessage message;
1177+
final MessageBase<DmRecipient> message;
11721178
final Narrow narrow;
11731179

11741180
@override
11751181
Widget build(BuildContext context) {
11761182
final zulipLocalizations = ZulipLocalizations.of(context);
11771183
final store = PerAccountStoreWidget.of(context);
11781184
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(", "));
1185+
if (message.recipient.allRecipientIds.length > 1) {
1186+
title = zulipLocalizations.messageListGroupYouAndOthers(
1187+
message.recipient.allRecipientIds
1188+
.where((id) => id != store.selfUserId)
1189+
.map(store.userDisplayName)
1190+
.sorted()
1191+
.join(", "));
11851192
} else {
11861193
title = zulipLocalizations.messageListGroupYouWithYourself;
11871194
}
@@ -1233,7 +1240,7 @@ TextStyle recipientHeaderTextStyle(BuildContext context, {FontStyle? fontStyle})
12331240
class RecipientHeaderDate extends StatelessWidget {
12341241
const RecipientHeaderDate({super.key, required this.message});
12351242

1236-
final Message message;
1243+
final MessageBase message;
12371244

12381245
@override
12391246
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)