Skip to content

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

Open
wants to merge 7 commits into
base: main
Choose a base branch
from

Conversation

PIG208
Copy link
Member

@PIG208 PIG208 commented Apr 17, 2025

This is a prep PR for #1453, toward #1441.

@PIG208 PIG208 added the maintainer review PR ready for review by Zulip maintainers label Apr 17, 2025
Copy link
Collaborator

@chrisbobbe chrisbobbe left a 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});
Copy link
Collaborator

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 the false 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 {
Copy link
Collaborator

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"

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;
Copy link
Collaborator

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.

Copy link
Collaborator

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.

Copy link
Member Author

@PIG208 PIG208 Apr 22, 2025

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.

@PIG208
Copy link
Member Author

PIG208 commented Apr 22, 2025

Thanks for the review! Updated the PR.

Copy link
Collaborator

@chrisbobbe chrisbobbe left a 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 {
Copy link
Collaborator

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'

@chrisbobbe chrisbobbe assigned gnprice and unassigned chrisbobbe Apr 23, 2025
@chrisbobbe chrisbobbe added integration review Added by maintainers when PR may be ready for integration and removed maintainer review PR ready for review by Zulip maintainers labels Apr 23, 2025
@chrisbobbe chrisbobbe requested a review from gnprice April 23, 2025 23:15
Copy link
Member

@gnprice gnprice left a 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.

/// Returns whether an item has been appended or not.
///
/// The caller must append a [MessageListMessageBaseItem] after this.
bool _maybeAppendAuxillaryItem(MessageBase message, {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: spelling, "auxiliary"

Suggested change
bool _maybeAppendAuxillaryItem(MessageBase message, {
bool _maybeAppendAuxiliaryItem(MessageBase message, {

if (senderRow != null)
Padding(padding: const EdgeInsets.fromLTRB(16, 2, 16, 0),
child: senderRow),
if (item.showSender) _SenderRow(message: message, showTimestamp: true),
Copy link
Member

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:

Suggested change
if (item.showSender) _SenderRow(message: message, showTimestamp: true),
if (item.showSender)
_SenderRow(message: message, showTimestamp: true),

height: (18 / 16),
fontFeatures: const [FontFeature.enable('c2sc'), FontFeature.enable('smcp')],
).merge(weightVariableTextStyle(context))),
]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: comma

Comment on lines +654 to +655
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;
Copy link
Member

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.

Comment on lines 600 to 601
/// Whether [this] and [other] have the same canonical form.
bool isSameAs(Conversation other);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
/// 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.

@@ -36,17 +36,29 @@ class MessageListDateSeparatorItem extends MessageListItem {
}

/// A message to show in the message list.
Copy link
Member

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;
Copy link
Member

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.

Copy link
Member

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.

PIG208 added 7 commits April 25, 2025 13:12
Also removed a stale comment that refers to resolved issues
(zulip#173 and zulip#175).

We will reuse this helper when handling outbox messages.
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.
@PIG208
Copy link
Member Author

PIG208 commented Apr 25, 2025

Thanks for the review! Updated the PR.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
integration review Added by maintainers when PR may be ready for integration
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants