Skip to content

Commit 9a77682

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 d4a1100 commit 9a77682

File tree

4 files changed

+43
-32
lines changed

4 files changed

+43
-32
lines changed

lib/model/message_list.dart

Lines changed: 3 additions & 3 deletions
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

Lines changed: 6 additions & 4 deletions
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

Lines changed: 32 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import 'dart:math';
22

33
import 'package:collection/collection.dart';
4+
import 'package:flutter/foundation.dart';
45
// ignore: undefined_hidden_name // anticipates https://github.com/flutter/flutter/pull/164818
56
import 'package:flutter/material.dart' hide SliverPaintOrder;
67
import 'package:flutter_color_models/flutter_color_models.dart';
@@ -901,23 +902,29 @@ class _MarkAsReadAnimationState extends State<MarkAsReadAnimation> {
901902
class RecipientHeader extends StatelessWidget {
902903
const RecipientHeader({super.key, required this.message, required this.narrow});
903904

904-
final Message message;
905+
final MessageBase message;
905906
final Narrow narrow;
906907

907908
@override
908909
Widget build(BuildContext context) {
909910
final message = this.message;
910-
return switch (message) {
911-
StreamMessage() => StreamMessageRecipientHeader(message: message, narrow: narrow),
912-
DmMessage() => DmRecipientHeader(message: message, narrow: narrow),
913-
};
911+
switch (message) {
912+
case MessageBase<StreamConversation>():
913+
return StreamMessageRecipientHeader(message: message, narrow: narrow);
914+
case MessageBase<DmConversation>():
915+
return DmRecipientHeader(message: message, narrow: narrow);
916+
case MessageBase<Conversation>():
917+
assert(false, 'Unexpected concrete subclass of MessageBase<Conversation>:'
918+
' ${objectRuntimeType(message, 'MessageBase<Conversation>')}');
919+
return SizedBox.shrink();
920+
}
914921
}
915922
}
916923

917924
class DateSeparator extends StatelessWidget {
918925
const DateSeparator({super.key, required this.message});
919926

920-
final Message message;
927+
final MessageBase message;
921928

922929
@override
923930
Widget build(BuildContext context) {
@@ -1027,7 +1034,7 @@ class StreamMessageRecipientHeader extends StatelessWidget {
10271034
required this.narrow,
10281035
});
10291036

1030-
final StreamMessage message;
1037+
final MessageBase<StreamConversation> message;
10311038
final Narrow narrow;
10321039

10331040
static bool _containsDifferentChannels(Narrow narrow) {
@@ -1053,11 +1060,11 @@ class StreamMessageRecipientHeader extends StatelessWidget {
10531060
final designVariables = DesignVariables.of(context);
10541061
final zulipLocalizations = ZulipLocalizations.of(context);
10551062

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

10581065
final messageListTheme = MessageListTheme.of(context);
10591066

1060-
final subscription = store.subscriptions[message.streamId];
1067+
final subscription = store.subscriptions[streamId];
10611068
final Color backgroundColor;
10621069
final Color iconColor;
10631070
if (subscription != null) {
@@ -1073,16 +1080,17 @@ class StreamMessageRecipientHeader extends StatelessWidget {
10731080
if (!_containsDifferentChannels(narrow)) {
10741081
streamWidget = const SizedBox(width: 16);
10751082
} else {
1076-
final stream = store.streams[message.streamId];
1083+
final stream = store.streams[streamId];
1084+
final message = this.message;
10771085
final streamName = stream?.name
1078-
?? message.displayRecipient
1086+
?? (message is StreamMessage ? message.displayRecipient : null)
10791087
?? zulipLocalizations.unknownChannelName; // TODO(log)
10801088

10811089
streamWidget = GestureDetector(
10821090
onTap: () => Navigator.push(context,
10831091
MessageListPage.buildRoute(context: context,
1084-
narrow: ChannelNarrow(message.streamId))),
1085-
onLongPress: () => showChannelActionSheet(context, channelId: message.streamId),
1092+
narrow: ChannelNarrow(streamId))),
1093+
onLongPress: () => showChannelActionSheet(context, channelId: streamId),
10861094
child: Row(
10871095
crossAxisAlignment: CrossAxisAlignment.center,
10881096
children: [
@@ -1130,7 +1138,7 @@ class StreamMessageRecipientHeader extends StatelessWidget {
11301138
Icon(size: 14, color: designVariables.title.withFadedAlpha(0.5),
11311139
// A null [Icon.icon] makes a blank space.
11321140
iconDataForTopicVisibilityPolicy(
1133-
store.topicVisibilityPolicy(message.streamId, topic))),
1141+
store.topicVisibilityPolicy(streamId, topic))),
11341142
]));
11351143

11361144
return GestureDetector(
@@ -1143,7 +1151,7 @@ class StreamMessageRecipientHeader extends StatelessWidget {
11431151
MessageListPage.buildRoute(context: context,
11441152
narrow: TopicNarrow.ofMessage(message))),
11451153
onLongPress: () => showTopicActionSheet(context,
1146-
channelId: message.streamId,
1154+
channelId: streamId,
11471155
topic: topic,
11481156
someMessageIdInTopic: message.id),
11491157
child: ColoredBox(
@@ -1168,20 +1176,21 @@ class DmRecipientHeader extends StatelessWidget {
11681176
required this.narrow,
11691177
});
11701178

1171-
final DmMessage message;
1179+
final MessageBase<DmConversation> message;
11721180
final Narrow narrow;
11731181

11741182
@override
11751183
Widget build(BuildContext context) {
11761184
final zulipLocalizations = ZulipLocalizations.of(context);
11771185
final store = PerAccountStoreWidget.of(context);
11781186
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(", "));
1187+
if (message.conversation.allRecipientIds.length > 1) {
1188+
title = zulipLocalizations.messageListGroupYouAndOthers(
1189+
message.conversation.allRecipientIds
1190+
.where((id) => id != store.selfUserId)
1191+
.map(store.userDisplayName)
1192+
.sorted()
1193+
.join(", "));
11851194
} else {
11861195
title = zulipLocalizations.messageListGroupYouWithYourself;
11871196
}
@@ -1233,7 +1242,7 @@ TextStyle recipientHeaderTextStyle(BuildContext context, {FontStyle? fontStyle})
12331242
class RecipientHeaderDate extends StatelessWidget {
12341243
const RecipientHeaderDate({super.key, required this.message});
12351244

1236-
final Message message;
1245+
final MessageBase message;
12371246

12381247
@override
12391248
Widget build(BuildContext context) {

test/model/message_list_test.dart

Lines changed: 2 additions & 2 deletions
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)