-
Notifications
You must be signed in to change notification settings - Fork 306
local echo (6/n): Prepare message list for outbox message support #1475
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, this looks good! Small comments below.
|
||
final MessageListMessageItem item; | ||
class _SenderRow extends StatelessWidget { | ||
const _SenderRow({required this.message, required this.showTimestamp}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
msglist [nfc]: Extract _SenderRow widget
How about splitting this commit into two:
- one for minimally extracting the new helper widget
- one that adds
showTimestamp
, noting in the commit message that it's for the upcoming local-echo feature, and that thefalse
case doesn't have a Figma design
@@ -36,17 +36,29 @@ class MessageListDateSeparatorItem extends MessageListItem { | |||
} | |||
|
|||
/// A message to show in the message list. | |||
class MessageListMessageItem extends MessageListItem { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
msglist [nfc]: Extract MessageListMessageBaseItem
This is an NFC because MessageListMessageItem is still the only
subclass of it.
Commit-message nit: "NFC" or "an NFC change"
lib/model/message_list.dart
Outdated
final conversation = message.conversation; | ||
if (prevConversation is StreamConversation && conversation is StreamConversation) { | ||
if (prevConversation.streamId != conversation.streamId) return false; | ||
if (prevConversation.topic.canonicalize() != conversation.topic.canonicalize()) return false; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It looks like the existing code could have been using TopicName.isSameAs
; switching to that method could be a small independent improvement.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In fact, I wonder if Conversation
could declare an isSameAs
method, for its subclasses to implement.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good idea! I think we can go further and also pull out MessageBase.inSameConversationAs
to get rid of haveSameRecipient
altogether, moving its tests to test/api/model/model_test.dart
.
One worry though, is that haveSameRecipient
's meaning is quite local to the message list. We wouldn't use Conversation.isSameAs
or MessageBase.inSameConversationAs
elsewhere in the app, at least right now.
Thanks for the review! Updated the PR. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks! LGTM; marking for Greg's review.
@@ -596,7 +596,10 @@ extension type const TopicName(String _value) { | |||
/// Different from [MessageDestination], this information comes from | |||
/// [getMessages] or [getEvents], identifying the conversation that contains a | |||
/// message. | |||
sealed class Conversation {} | |||
sealed class Conversation { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
api [nfc]: Extract Conversation.isSameAs
This will make it easier to support comparing the conversations
between subclasses of MessageBase.
The message list tests on displayRecipient are now mostly exercising the
logic on Conversation.isSameAs, which makes it reasonable to move the
tests. Keep them here for now since this logic is more relevant to
message lists then it is to the rest of the app.
Commit-message nit: 'than it is'
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks both!
Generally these refactors look fine. A couple of them I'm not totally convinced of, so the motivation may become clearer with the PR that uses them. Otherwise, just small comments below.
lib/model/message_list.dart
Outdated
/// Returns whether an item has been appended or not. | ||
/// | ||
/// The caller must append a [MessageListMessageBaseItem] after this. | ||
bool _maybeAppendAuxillaryItem(MessageBase message, { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: spelling, "auxiliary"
bool _maybeAppendAuxillaryItem(MessageBase message, { | |
bool _maybeAppendAuxiliaryItem(MessageBase message, { |
lib/widgets/message_list.dart
Outdated
if (senderRow != null) | ||
Padding(padding: const EdgeInsets.fromLTRB(16, 2, 16, 0), | ||
child: senderRow), | ||
if (item.showSender) _SenderRow(message: message, showTimestamp: true), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: this is a major subcomponent, so good to give it a bit more visual prominence:
if (item.showSender) _SenderRow(message: message, showTimestamp: true), | |
if (item.showSender) | |
_SenderRow(message: message, showTimestamp: true), |
lib/widgets/message_list.dart
Outdated
height: (18 / 16), | ||
fontFeatures: const [FontFeature.enable('c2sc'), FontFeature.enable('smcp')], | ||
).merge(weightVariableTextStyle(context))), | ||
] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: comma
if (xs.length != ys.length) return false; | ||
final xs_ = xs.iterator; final ys_ = ys.iterator; | ||
while (xs_.moveNext() && ys_.moveNext()) { | ||
if (xs_.current != ys_.current) return false; | ||
} | ||
return true; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is best kept as its own method with its own name. It's written to a low-level API, but has a meaning that can be described very crisply and abstractly.
lib/api/model/model.dart
Outdated
/// Whether [this] and [other] have the same canonical form. | ||
bool isSameAs(Conversation other); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
/// Whether [this] and [other] have the same canonical form. | |
bool isSameAs(Conversation other); | |
/// Whether [this] and [other] refer to the same Zulip conversation. | |
bool isSameAs(Conversation other); |
I'd think of a "canonical form" as a strategy for implementing this sort of method, and the intended semantics as something a bit more abstract.
lib/model/message_list.dart
Outdated
@@ -36,17 +36,29 @@ class MessageListDateSeparatorItem extends MessageListItem { | |||
} | |||
|
|||
/// A message to show in the message list. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
doc should get updated
final MessageListMessageItem item; | ||
final MessageListMessageBaseItem item; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit:
msglist [nfc]: Handle MessageListMessageBaseItem with MessageItem
Can expand slightly to clarify:
msglist [nfc]: Handle MessageListMessageBaseItem with MessageItem widget
Otherwise, when looking at the commit message before rereading the code, these two classes sound like the same kind of thing, and then their relationship is confusing.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Or I think better yet:
msglist [nfc]: Let MessageItem widget take a MessageListMessageBaseItem
That basically specifies that we're talking about a field on the widget, vs. the wide range of other things that "handle" could mean.
This is for the upcoming local-echo feature, to hide the timestamp. There isn't a Figma design for messages without a timestamp.
This will make it easier to support comparing the conversations between subclasses of MessageBase. The message list tests on displayRecipient are now mostly exercising the logic on Conversation.isSameAs, which makes it reasonable to move the tests. Keep them here for now since this logic is more relevant to message lists than it is to the rest of the app. Dropped the comment on _equalIdSequences since it is now private in the short body of DmConversation.
This is NFC because MessageListMessageItem is still the only subclass of it.
This will make MessageItem compatible with other future subclasses of MessageListMessageBaseItem, in particular MessageListOutboxMessageItem, which do not need unread markers.
Thanks for the review! Updated the PR. |
This is a prep PR for #1453, toward #1441.