Skip to content

autocomplete: Implement new design for @-mention autocomplete items #995

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

Merged
merged 7 commits into from
Mar 4, 2025

Conversation

fombalang
Copy link
Contributor

Hello everyone,

This PR implements the updated design for the @-mention autocomplete items as detailed in this Figma File
https://www.figma.com/design/1JTNtYo9memgW7vV6d0ygq/Zulip-Mobile?node-id=3859-3131&m=dev

I added new contextMenuItemLabel and contextMenuItemMeta color variables to the designVariables class from the design.
I also had to manually set the line height to match the design exactly.

As Greg described here, the autocomplete item only shows the user's real email address when the user has allowed their email to be visible, if not it doesn't show anything. I used the _getDisplayEmailFor() method from the profile page to get the user's real email. I am not sure if it is a good idea to have a copy of the same method here, maybe we should find a way to not have multiple copies of the same method.

Screenshot_20241011-114402

I updated autocomplete tests to also check if the email(metaData) is also shown as the updated design now shows extra metadata.

I attempted to add another test to verify if the email is not shown when the user's emailAddressVisibility != emailAddressVisibility.everyone, while doing so I learned a bit more about how the app manages users and data, but to be honest I couldn't get it to work properly, and I did not want to massively change up the current test file. Still trying to wrap my head around that.
This also leads me to a bug I think, which I discovered in the example_data.dart initialSnapshot method where some of the arguments from the intialSnapshot method aren't being passed down to the method, I think someone missed that when setting up the method.

Please review when you can, thank you

Fixes: #913

@chrisbobbe chrisbobbe self-assigned this Oct 12, 2024
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! Comments below.

In the Figma:

  • The gap between the avatar photo and the text is 6px, not 8px
  • The outer padding is top: 4, right: 8, bottom: 4, left: 4 (not top: 8, right: 16, bottom: 8, left: 16) Since left and right are unequal, we should use EdgeInsetsDirectional for this.
  • Please post screenshots showing the "…" effect when the name or metadata text are very long (not sure this is implemented in this revision)
  • The avatar photo is a 36px rounded square with 4px border radius (not a 32px square with 3px border radius)
  • Our designer doesn't want the "ink splash" effect on buttons. We should remove the InkWell widget and implement the on-pressed appearance specified here:
    https://www.figma.com/design/1JTNtYo9memgW7vV6d0ygq/Zulip-Mobile?node-id=3732-28939&node-type=symbol&m=dev
    image

Comment on lines 245 to 246
final Color contextMenuItemLabel;
final Color contextMenuItemMeta;
Copy link
Collaborator

Choose a reason for hiding this comment

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

Since these are variables in the Figma, they don't belong in this section, which is marked

  // Not named variables in Figma; taken from older Figma drafts, or elsewhere.

They should appear alphabetically in the section at the top:

  final Color background;
  final Color bgCounterUnread;
  final Color bgTopBar;
  // [etc.]

When moving them there, please also update the other places these names appear in the class, such as the lerp method.

@@ -167,6 +169,8 @@ class DesignVariables extends ThemeExtension<DesignVariables> {
// TODO(design-dark) need proper dark-theme color (this is ad hoc)
subscriptionListHeaderText: const HSLColor.fromAHSL(1.0, 240, 0.1, 0.75).toColor(),
unreadCountBadgeTextForChannel: Colors.white.withValues(alpha: 0.9),
contextMenuItemLabel: const Color(0xffDFE1E8),
Copy link
Collaborator

Choose a reason for hiding this comment

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

I think we more often use lowercase letters in these.

/// The given user's real email address, if known, for displaying in the UI.
///
/// Returns null if self-user isn't able to see [user]'s real email address.
String? _getDisplayEmailFor(User user, {required PerAccountStore store}) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Yes, as you suggested in the PR description, we should avoid copy-pasting this complicated logic from somewhere else. If we have some complicated logic written twice, and it needs to be updated, there's a risk that we'll update one place and forget the other.

Maybe a good place for a reusable function is lib/api/model/model.dart, below the User class? That refactor should be in an NFC prep commit.

avatar = Avatar(userId: userId, size: 32, borderRadius: 3);
label = PerAccountStoreWidget.of(context).users[userId]!.fullName;
label = user!.fullName;
metaData = _getDisplayEmailFor(user, store: store) ?? '';
Copy link
Collaborator

Choose a reason for hiding this comment

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

nit: Since "metadata" is one word, the variable should be called metadata.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Also, let's make it nullable, so String? metadata;, so its empty value is null instead of the empty string.

switch (option) {
case UserMentionAutocompleteResult(:var userId):
final store = PerAccountStoreWidget.of(context);
final user = store.users[userId];
Copy link
Collaborator

Choose a reason for hiding this comment

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

Suggested change
final user = store.users[userId];
final user = store.users[userId]!;

instead of putting the ! later, when we try to access .fullName.

Comment on lines 253 to 262
Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(label, style: TextStyle(fontSize: 18, height: 1.1, color: designVariables.contextMenuItemLabel) //Creates a line height equavalent to ~20
.merge(weightVariableTextStyle(context, wght: 600))),
Visibility(
visible: metaData.isNotEmpty,
child: Text(metaData, style: TextStyle(height: 1.14, color: designVariables.contextMenuItemMeta)), //Creates a line height equavalent to ~16
)])])));
Copy link
Collaborator

Choose a reason for hiding this comment

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

indentation and line lengths:

Suggested change
Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(label, style: TextStyle(fontSize: 18, height: 1.1, color: designVariables.contextMenuItemLabel) //Creates a line height equavalent to ~20
.merge(weightVariableTextStyle(context, wght: 600))),
Visibility(
visible: metaData.isNotEmpty,
child: Text(metaData, style: TextStyle(height: 1.14, color: designVariables.contextMenuItemMeta)), //Creates a line height equavalent to ~16
)])])));
Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
style: TextStyle(
fontSize: 18,
height: 1.1, // Creates a line height equavalent to ~20
color: designVariables.contextMenuItemLabel,
)
.merge(weightVariableTextStyle(context, wght: 600)),
label),
Visibility(
visible: metaData.isNotEmpty,
child: Text(
style: TextStyle(
height: 1.14, // Creates a line height equavalent to ~16
color: designVariables.contextMenuItemMeta,
),
metaData)),
]),
])));

mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(label, style: TextStyle(fontSize: 18, height: 1.1, color: designVariables.contextMenuItemLabel) //Creates a line height equavalent to ~20
Copy link
Collaborator

Choose a reason for hiding this comment

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

See other places where we set height; here, we would express it as 20 / 18.

.merge(weightVariableTextStyle(context, wght: 600))),
Visibility(
visible: metaData.isNotEmpty,
child: Text(metaData, style: TextStyle(height: 1.14, color: designVariables.contextMenuItemMeta)), //Creates a line height equavalent to ~16
Copy link
Collaborator

Choose a reason for hiding this comment

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

height: 16 / 14

Copy link
Collaborator

Choose a reason for hiding this comment

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

Also, this should have an explicit fontSize: 14. Even if that matches the default, let's be explicit here.

children: [
Text(label, style: TextStyle(fontSize: 18, height: 1.1, color: designVariables.contextMenuItemLabel) //Creates a line height equavalent to ~20
.merge(weightVariableTextStyle(context, wght: 600))),
Visibility(
Copy link
Collaborator

Choose a reason for hiding this comment

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

Instead of Visibility, how about using Dart's "collection if" feature:

if (metaData.isNotEmpty) Text(/* … */),

, but combined with my earlier suggestions it would be

if (metadata != null) Text(/* … */),

@gnprice
Copy link
Member

gnprice commented Oct 12, 2024

This also leads me to a bug I think, which I discovered in the example_data.dart initialSnapshot method where some of the arguments from the intialSnapshot method aren't being passed down to the method, I think someone missed that when setting up the method.

Sure, this would be good to fix — please go ahead and add a commit with that fix if you think you already see how to do it, or start a thread in #mobile-team and we can discuss in more detail.

@fombalang
Copy link
Contributor Author

Okay, thank you for the review, I will make the changes.
For the changes such as the bug and the refactor of the email logic, should I add those into this PR, or should it be in a different PR?

@gnprice
Copy link
Member

gnprice commented Oct 14, 2024

If it's needed for the other work you're doing in this PR, then a commit in this PR is a good way to do it.

If it's not related to what's in this PR, then a separate PR is best.

@fombalang
Copy link
Contributor Author

If it's needed for the other work you're doing in this PR, then a commit in this PR is a good way to do it.

If it's not related to what's in this PR, then a separate PR is best.

Okay

@fombalang
Copy link
Contributor Author

  • Our designer doesn't want the "ink splash" effect on buttons. We should remove the InkWell widget and implement the on-pressed appearance specified here:

About the splash, I kept the inkwell widget, because a gesture detector doesn't show splashes, but I removed the sparkle effect, and left just the color change on tap. I also added a border radius in the splash as shown on the design, it's a bit difficult to see here but it is there. Would this work according to the design?

screen-20241014-204642.mp4

@fombalang
Copy link
Contributor Author

I also did the updates for the case where the user has a really long name or email.

Before
Screenshot_20241014-191455

After
Screenshot_20241014-191948

@chrisbobbe
Copy link
Collaborator

Would this work according to the design?

If your code causes any noticeable differences from the design, please identify them and say why you think they are OK. This will shorten the path to deciding if the code will work. :)

It looks like you haven't pushed your latest revision to GitHub. When it's ready for another review, please do that, and comment saying that it's ready for review.

@fombalang
Copy link
Contributor Author

fombalang commented Oct 15, 2024

It looks like you haven't pushed your latest revision to GitHub. When it's ready for another review, please do that, and comment saying that it's ready for review.

No, I haven't yet.

That is because I have been facing some problems with the ComposeAutocomplete test, I found that changing the dimensions of the avatar widget from 32 to 36 causes the test to fail. Not only that I found that there was a threshold of sizes for which the test passed, 32 -33 are good, and from 34 upward the test fails.

And I have looked at the test, and tried to do some searching as to why it might be failing, and I haven't succeeded. I did not see any obvious place where the avatar widget size was checked in the test. I also thought it might be because of an outdated golden test snapshot, but I could not find any references to a snapshot file. So I have been confused and stumped.

I was just about to comment on that before seeing your comment, wondering if anyone can help point me in the right direction.

@gnprice
Copy link
Member

gnprice commented Oct 15, 2024

If you push the code here, and then start a conversation in #mobile-dev-help with the test failure you're seeing, that will probably be the most efficient way to get help investigating it.

@fombalang
Copy link
Contributor Author

If you push the code here, and then start a conversation in #mobile-dev-help with the test failure you're seeing, that will probably be the most efficient way to get help investigating it.

Okay, I will do that

@fombalang fombalang force-pushed the autocomplete-results-list branch from 17aea85 to e107e03 Compare October 15, 2024 20:25
@fombalang
Copy link
Contributor Author

It looks like you haven't pushed your latest revision to GitHub. When it's ready for another review, please do that, and comment saying that it's ready for review.

I have pushed my changes, please review

@fombalang

This comment was marked as resolved.

@chrisbobbe

This comment was marked as resolved.

@chrisbobbe
Copy link
Collaborator

If you push the code here, and then start a conversation in #mobile-dev-help with the test failure you're seeing, that will probably be the most efficient way to get help investigating it.

Thanks for starting that conversation. Here's a link, so people reading this will know the conversation is happening and where to find it: https://chat.zulip.org/#narrow/channel/516-mobile-dev-help/topic/ComposeAutocomplete.20test.20failure.20help/near/1963058

@fombalang
Copy link
Contributor Author

If it's needed for the other work you're doing in this PR, then a commit in this PR is a good way to do it.

If it's not related to what's in this PR, then a separate PR is best.

Hello
I have created a PR for this bug, please review when you can.
#1011

@chrisbobbe
Copy link
Collaborator

#1011

Thanks; I'll add this to my review queue. 🙂

I see Greg has replied in that discussion about the test failures. Please comment here when those failures are resolved and this PR is ready for another review. 🙂

@fombalang fombalang force-pushed the autocomplete-results-list branch from e107e03 to 5b85e89 Compare October 29, 2024 05:38
@fombalang
Copy link
Contributor Author

I see Greg has replied in that discussion about the test failures. Please comment here when those failures are resolved and this PR is ready for another review. 🙂

Hello
I have resolved the issues with the test and pushed an update here. Please review.

I did an interactive rebase and merged the test fix to the previous commit before the latest one, I think it caused it to not run the pipeline since the latest commit is still the same one from before, maybe we might have to trigger it manually.

@gnprice
Copy link
Member

gnprice commented Oct 29, 2024

It's puzzling that GitHub didn't run the CI checks on the latest revision.

It's not because the commits are the same; they're different. Even though the last commit has the same changes in it as the last commit of the previous revision, it's still a different commit as far as Git is concerned because it has a different history. You can see here:
image

fombalang force-pushed the autocomplete-results-list branch from e107e03 to 5b85e89 1 hour ago

that the latest revision's tip commit is 5b85e89 and the revision before that was e107e03.

Anyway, we can run the tests locally, and as long as they pass when run locally then that confirms that they pass.

@gnprice gnprice dismissed chrisbobbe’s stale review October 29, 2024 06:45

see if this causes CI to run

@gnprice
Copy link
Member

gnprice commented Oct 29, 2024

I tried the "dismiss review" button on Chris's previous "request changes" review, just in case that was related to why CI wasn't running. Doesn't seem like it had an effect — still not running.

I don't even have a button to tell checks to run. Instead the "Checks" tab just looks like this:
image

Workflow runs completed with no jobs

It's as if there weren't any files under .github/workflows/ at all. But in reality there is; your branch doesn't touch that directory, so it has the same workflow file in it as it has in main.

🤷 We'll just rely on running checks locally, then. If this odd GitHub behavior starts happening repeatedly, we'll have to investigate further.

@fombalang
Copy link
Contributor Author

that the latest revision's tip commit is 5b85e89 and the revision before that was e107e03.

Okay, I see. which means it should have triggered again.

@fombalang
Copy link
Contributor Author

🤷 We'll just rely on running checks locally, then. If this odd GitHub behavior starts happening repeatedly, we'll have to investigate further.

Okay then.
Everything passes locally on my end.

image

@chrisbobbe
Copy link
Collaborator

The GitHub UI is showing that there are some rebase conflicts:

image

Could you please resolve those and comment here when that's done? If you need help, please ask in #git help in the development community.

@fombalang
Copy link
Contributor Author

development community

I can just resolve using the GitHub UI right? or would that add an unwanted commit?

@fombalang fombalang force-pushed the autocomplete-results-list branch from 5b85e89 to e3fb734 Compare October 31, 2024 09:24
@fombalang
Copy link
Contributor Author

The GitHub UI is showing that there are some rebase conflicts:

I have resolved the conflicts. I rebased my changes on top of the latest changes from main and fixed the conflicts. Please review when you can.

fombalang added a commit to fombalang/zulip-flutter that referenced this pull request Jan 12, 2025
Add `findAvatarImage` to check userId instead of URL,
making it resilient to changes in avatar image details like size.
Previous finder used 'findNetworkImage' which would fail if the avatar size is different

Relevant Discussion:
https://chat.zulip.org/#narrow/channel/516-mobile-dev-help/topic/ComposeAutocomplete.20test.20failure.20help
zulip#995 (comment)
@fombalang fombalang force-pushed the autocomplete-results-list branch from 87d149c to c584432 Compare January 12, 2025 01:46
@fombalang
Copy link
Contributor Author

Hi all, and Happy New Year! 🎉

I've rebased my changes on top of the latest main, faced some difficulties cause they had diverged quite a bit but I was able to get it done.
I also separated the test cases for the delivery email into two as @gnprice suggested, one for when the email is available and one where it is not.

One thing to note, so a while ago we did the update about changing the implementation for the findNetworkImage to findAvatarImage to make it less brittle to changes like the avatar size, since we hadn't merged yet, the new tests for the emojis still use the findNetworkImage method.

I did not want to touch that, so I added the new findAvatarImage we did as a separate method which is used for the autocomplete (@mentions) group of tests.
Is that okay, or should we go back and merge both methods? I figured it'd be fine to separate it since the findAvatarImage is more specific for avatars only, and the findNetworkImage can still be used in other areas (the emojis for example.)

@fombalang fombalang force-pushed the autocomplete-results-list branch from c584432 to a31cb4a Compare January 12, 2025 02:02
@gnprice
Copy link
Member

gnprice commented Jan 16, 2025

Thanks @fombalang for the revision! Happy New Year.

since we hadn't merged yet, the new tests for the emojis still use the findNetworkImage method.

That's fine — the emoji image URLs don't have the same tricky dependency on external facts (the device pixel ratio) that the avatar URLs do. Each image emoji has just a single size of image and a single URL to find it at. (Well, animated emoji have a second URL for the non-animated version; but the setting that controls whether to use that is a user setting entirely internal to the app, so is well controlled in tests.) So findNetworkImage is fine for those.

Looking at the rest of the changes now.

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 for the revision! Generally the implementation all looks good, with a couple of nits below. The remaining comments are mainly on the tests.

It looks like the commit I'd added to the tip of the branch earlier:
87d149c autocomplete: Update emoji-results style to follow design
got lost in the rebase. I'll push an updated version of it back to the PR branch. Before making your next changes, do be sure to fetch the updated version of the branch — git fetch me or git fetch origin, depending on the name you use for the Git remote pointing at your own GitHub fork of this repo. That way you'll have the version with my added commit and should naturally be able to carry it along as you revise.

Comment on lines 131 to 132
Finder findAvatarImage(int userId) =>
find.byWidgetPredicate((widget) => widget is AvatarImage && widget.userId == userId);
Copy link
Member

Choose a reason for hiding this comment

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

nit:

Suggested change
Finder findAvatarImage(int userId) =>
find.byWidgetPredicate((widget) => widget is AvatarImage && widget.userId == userId);
Finder findAvatarImage(int userId) =>
find.byWidgetPredicate((widget) => widget is AvatarImage && widget.userId == userId);

Comment on lines 255 to 257
child: Row(
children: [
avatar,
Copy link
Member

Choose a reason for hiding this comment

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

nit: preserve formatting of the parts you aren't otherwise changing:

Suggested change
child: Row(
children: [
avatar,
child: Row(children: [
avatar,

Comment on lines 259 to 260
Expanded(child: Column(
mainAxisSize: MainAxisSize.min,
Copy link
Member

Choose a reason for hiding this comment

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

nit: two-space indents, here and elsewhere

Suggested change
Expanded(child: Column(
mainAxisSize: MainAxisSize.min,
Expanded(child: Column(
mainAxisSize: MainAxisSize.min,

Comment on lines -150 to +173
checkUserShown(user1, store, expected: false);
checkUserShown(user2, store, expected: true);
checkUserShown(user3, store, expected: true);
checkUserShown(user1, expected: false);
checkUserShown(user2, expected: true);
checkUserShown(user3, expected: true);
Copy link
Member

Choose a reason for hiding this comment

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

The change where checkUserShown stops taking a store parameter should happen separately from the main "Implement new design" commit. That way it doesn't add more things happening inside that commit (which is the most complex commit in the branch).

In particular that way the reader doesn't have to wonder why the design change needs all these changes to the existing tests (which looks like what would happen if the design change were breaking something the existing tests were checking).

Probably cleanest is to have this change happen in the same commit that switches to findAvatarImage, because that's the change that makes the store unnecessary for this helper.

Copy link
Member

Choose a reason for hiding this comment

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

For making that revision, the key tool is git rebase -i. The #git help channel is a good place to ask for advice.

The way I'd probably do it is:

  1. git rebase -i
  2. in the rebase TODO, put a break command before this commit
  3. at that point, create a new commit that just makes this helper stop taking store
  4. let the rebase finish
  5. then in a second round of git rebase -i, squash that new commit into the earlier findAvatarImage commit

For step 3, git checkout -p main is handy for taking pieces of the later commits in the branch. I'd probably use a mix of that together with just making the edits by hand in the IDE, for those parts where the desired change is mixed in with changes that should happen later. The command git diff -R main is handy for comparing your current tree to the tip of the branch, to see what changes will remain for the later commits in the branch.

final user1 = eg.user(userId: 1, fullName: 'User One', avatarUrl: 'user1.png');
final user2 = eg.user(userId: 2, fullName: 'User Two', avatarUrl: 'user2.png');
final user3 = eg.user(userId: 3, fullName: 'User Three', avatarUrl: 'user3.png');
final user1 = eg.user(userId: 1, fullName: 'User One', avatarUrl: 'user1.png',deliveryEmail: '[email protected]');
Copy link
Member

Choose a reason for hiding this comment

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

bump

});

testWidgets('delivery email not visible when unavailable', (tester) async {
final user1 = eg.user(userId: 1, fullName: 'User One', avatarUrl: 'user1.png',);
Copy link
Member

Choose a reason for hiding this comment

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

Is the avatar URL needed? I think it shouldn't be relevant for this test — should be something the reader doesn't need to think about to understand the test. In that case we can keep this test case focused by leaving it out.

See also this description of how the data in a test should be "maximally boring":
https://chat.zulip.org/#narrow/channel/6-frontend/topic/typescript.20node.20tests/near/1896899

Similarly, is userId needed?

(OTOH fullName is relevant because it's what the test uses for finding the user in autocomplete.)

Comment on lines 194 to 196
// Options are filtered correctly for query
// TODO(#226): Remove this extra edit when this bug is fixed.
await tester.enterText(composeInputFinder, 'hello @user ');
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
// Options are filtered correctly for query
// TODO(#226): Remove this extra edit when this bug is fixed.
await tester.enterText(composeInputFinder, 'hello @user ');
// TODO(#226): Remove this extra edit when this bug is fixed.
await tester.enterText(composeInputFinder, 'hello @user ');

This test isn't checking anything about filtering. (The existing test above is checking filtering: "user t" matches "User Two" but not "User One".)

Comment on lines 191 to 192
TypingNotifier.debugEnable = false;
addTearDown(TypingNotifier.debugReset);
Copy link
Member

Choose a reason for hiding this comment

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

Huh, why do these two new tests need this and the existing test doesn't?

I suspect these don't need it either — it looks like setupToComposeInput handles it.

debugNetworkImageHttpClientProvider = null;
});
testWidgets('delivery email visible when available', (tester) async {
final user1 = eg.user(userId: 1, fullName: 'User One', avatarUrl: 'user1.png', deliveryEmail: '[email protected]');
Copy link
Member

Choose a reason for hiding this comment

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

line too long — important information is past 80 columns

Concretely, here's what that line looks like for me right now:
image

As you can see, the delivery email is invisible.

Copy link
Member

Choose a reason for hiding this comment

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

(I have a big monitor, but I use that horizontal space to show multiple things side by side, especially when reviewing. Often that's:

  • the code, in my IDE
  • another IDE pane with a related file, e.g. to read tests side by side with the code they're testing
  • a terminal with git log --stat -p output, showing the content of the PR
  • a terminal with git range-diff output, to compare the current revision of a PR with a previous one
  • the browser window with the GitHub page I'm typing the review into

)

Comment on lines 200 to 201
// Check "User One"'s delivery email is not visible
checkUserShown(user1, expected: true, deliveryEmailExpected: false);
Copy link
Member

Choose a reason for hiding this comment

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

This comment doesn't make a lot of sense, since User One has no delivery email in the first place 🙂

OTOH as I wrote at #995 (review) , this test case should check that user.email doesn't appear. It's easy to imagine having a bug where when there's no user.deliveryEmail, we show user.email instead — which would be wrong because user.email in that case is a meaningless fake email made up by the Zulip server.

Copy link
Member

Choose a reason for hiding this comment

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

It may be cleanest to do that check by inlining the contents of checkUserShown into this test case (and the contrasting test case below), and adapting the details, rather than giving checkUserShown more parameters and conditions.

@PIG208
Copy link
Member

PIG208 commented Feb 4, 2025

Hi @fombalang. Thanks for working on this! Do you think you will have time to continue working on this addressing the review comments?

@gnprice gnprice added this to the M6: Post-launch milestone Feb 6, 2025
@gnprice
Copy link
Member

gnprice commented Feb 6, 2025

(The issue this addresses is an M6 Post-launch issue, but I'm still eager to get this PR finished and merged, as an exception to our stricter focus on launch issues — a lot of effort has gone into this already, and it's close to merge and will be great to have.)

PIG208 pushed a commit to PIG208/zulip-flutter that referenced this pull request Feb 28, 2025
Add `findAvatarImage` to check userId instead of URL,
making it resilient to changes in avatar image details like size.
Previous finder used 'findNetworkImage' which would fail if the avatar size is different

Relevant Discussion:
https://chat.zulip.org/#narrow/channel/516-mobile-dev-help/topic/ComposeAutocomplete.20test.20failure.20help
zulip#995 (comment)
@PIG208
Copy link
Member

PIG208 commented Feb 28, 2025

In a call, we found that this PR is actually for an M5-a issue.

I think the mislabeling is probably due to #913 (M5-a) and #914 (M6) being similar issues for different parts of the design. #913 is more feasible for completion near term because it only focuses on the redesign for autocomplete items.

I will pick up this PR (reusing this branch) from here and address the comments. Thanks for all the work @fombalang, and the prior reviews from Chris and Greg!

@PIG208 PIG208 removed this from the M6: Post-launch milestone Feb 28, 2025
PIG208 pushed a commit to PIG208/zulip-flutter that referenced this pull request Mar 1, 2025
Add `findAvatarImage` to check userId instead of URL,
making it resilient to changes in avatar image details like size.
Previous finder used 'findNetworkImage' which would fail if the avatar size is different

Relevant Discussion:
https://chat.zulip.org/#narrow/channel/516-mobile-dev-help/topic/ComposeAutocomplete.20test.20failure.20help
zulip#995 (comment)
@PIG208 PIG208 force-pushed the autocomplete-results-list branch from e0d2988 to 6fc4065 Compare March 1, 2025 00:29
@PIG208
Copy link
Member

PIG208 commented Mar 1, 2025

The PR has been updated. It preserves most of the design changes, and on top of that:

  • reuse the sub label style, applying it to wildcard autocomplete result items (that previously followed web);
  • update to match the design's lighter font weight for items where the sub label is not visible.
Updated screenshot

mixed options

@PIG208 PIG208 force-pushed the autocomplete-results-list branch from 6fc4065 to c558e72 Compare March 1, 2025 00:38
@PIG208 PIG208 requested a review from gnprice March 1, 2025 00:39
@gnprice
Copy link
Member

gnprice commented Mar 3, 2025

Thanks @PIG208 for picking this up! Taking a look now.

I think the mislabeling is probably due to #913 (M5-a) and #914 (M6) being similar issues for different parts of the design.

Aha — yeah, that is a likely diagnosis of the mixup.

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 @PIG208 for picking this up! Just small comments below.

/// The given user's real email address, if known, for displaying in the UI.
///
/// Returns null if self-user isn't able to see [user]'s real email address.
String? userDisplayEmail(User user) {
Copy link
Member

Choose a reason for hiding this comment

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

Logically this belongs on UserStore, but I guess it's in the same boat as hasPassedWaitingPeriod — we'll first need to arrange a good way for UserStore to access the realm settings.

Copy link
Member

Choose a reason for hiding this comment

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

Perhaps like Unreads that rely on a reference to a ChannelStoreImpl, we can split out realm settings for UserStore. Probably a good refactor project as a follow-up.

Copy link
Member

Choose a reason for hiding this comment

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

Yeah, or I'd organize it slightly differently to match the existing way UserStore works: see #1327 (comment) .

(Small correction: Unreads takes a ChannelStore, not a ChannelStoreImpl. Generally the only references to the "impl" classes are in PerAccountStore.)

required BuildContext context,
required PerAccountStore store,
Copy link
Member

Choose a reason for hiding this comment

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

I wouldn't necessarily add this from scratch, but no need to cut it — it's an optimization, saving a duplicate PerAccountStoreWidget.of, and it's very cheap in terms of the code it requires.

avatar,
const SizedBox(width: 8),
label,
SizedBox.square(dimension: 36, child: avatar),
Copy link
Member

Choose a reason for hiding this comment

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

How does this work in the wildcard case, with the 24px icon? Do we need to do something to get the icon centered?

… Well, your screenshot in #995 (comment) seems to show it centered. I guess the Icon widget takes care of that internally.

Copy link
Member

Choose a reason for hiding this comment

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

Anyway, in the user/avatar case, this SizedBox is redundant. Let's simplify a bit by moving it to within the wildcard case.

So effectively it becomes part of the avatar local's job to control its size, to avoid redundancy since when Avatar is used it will be controlling the size anyway.

Copy link
Member

Choose a reason for hiding this comment

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

Yeah, from Icon.build:

    return Semantics(
      label: semanticLabel,
      child: ExcludeSemantics(
        child: SizedBox(width: iconSize, height: iconSize, child: Center(child: iconWidget)),
      ),
    );

Copy link
Member

Choose a reason for hiding this comment

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

The SizedBox is ignored because the SizedBox in our code, and iconWidget is a RichText whose fontSize is iconSize.

@@ -236,6 +233,67 @@ void main() {

debugNetworkImageHttpClientProvider = null;
});

group('subLabel', () {
Copy link
Member

Choose a reason for hiding this comment

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

nit: match name to the one in the code (i.e. "sublabel")

Comment on lines +293 to +296
).merge(weightVariableTextStyle(context,
wght: sublabel == null ? 500 : 600)),
Copy link
Member

Choose a reason for hiding this comment

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

Huh interesting, subtle.

fombalang and others added 7 commits March 3, 2025 22:58
Moved method to PerAccountStore, renamed method from
getDisplayEmailFor to userDisplayEmail and
refactored usages to remove duplication.
Add `findAvatarImage` to check userId instead of URL,
making it resilient to changes in avatar image details like size.
Previous finder used 'findNetworkImage' which would fail if the avatar size is different

Relevant Discussion:
https://chat.zulip.org/#narrow/channel/516-mobile-dev-help/topic/ComposeAutocomplete.20test.20failure.20help
zulip#995 (comment)
Implemented new design for @-mention autocomplete items.
Added new `contextMenuItemLabel` and `contextMenuItemMeta`
color variables to `designVariables` class.

Fixes: zulip#913

Co-authored-by: Zixuan James Li <[email protected]>
Signed-off-by: Zixuan James Li <[email protected]>
Fix some wrong color variables that were
assigned to the contextMenuItemText field.
This follows the new design for user-mention results, but adapted
for emoji based on the design for the emoji picker.  See comment
for details.
@PIG208 PIG208 force-pushed the autocomplete-results-list branch from c558e72 to 2841a13 Compare March 4, 2025 04:18
@PIG208
Copy link
Member

PIG208 commented Mar 4, 2025

Thanks! This should be ready for review.

@gnprice gnprice merged commit 2841a13 into zulip:main Mar 4, 2025
1 check passed
@gnprice
Copy link
Member

gnprice commented Mar 4, 2025

Thanks! Looks good; merging.

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.

Redesign for @-mention autocomplete items
4 participants