Skip to content

fix(emoji): Adjust picker layout for plain-text-emojis setting #1587 #1759

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 1 commit into
base: main
Choose a base branch
from

Conversation

loveucifer
Copy link

@loveucifer loveucifer commented Jul 28, 2025

Before After
before after
Before After
Before After

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.

Hi @loveucifer, thanks for the PR.

  • It needs a test, in the "EmojiPicker" group in test/widgets/emoji_reaction_test.dart.
    • The test should have a comment like "Regression test for #1587". It should pass with the change in this commit, and it should fail without the change.
    • In the test, set the "emojiset" to Emojiset.text, show the emoji picker, find a list item in there, and check that its height is correct. To check its height, try getting the render object with tester.renderObject and looking at its .size.height.
  • EmojiPickerListEntry.build has this comment: "// TODO deduplicate this logic with [_EmojiAutocompleteItem]
    • That can be out of scope for this PR, but the comment is a hint that some other code (in _EmojiAutocompleteItem) might have the same problem, with a similar fix. That seems to be the case; could you please make that fix and post screenshots of it too, and write a test for it?
  • Please revise the commit message according to the project style (follow links in the README)

@loveucifer
Copy link
Author

Hi @loveucifer, thanks for the PR.

  • It needs a test, in the "EmojiPicker" group in test/widgets/emoji_reaction_test.dart.

    • The test should have a comment like "Regression test for Emoji-reaction picker looks odd with plain-text-emojis setting #1587". It should pass with the change in this commit, and it should fail without the change.

    • In the test, set the "emojiset" to Emojiset.text, show the emoji picker, find a list item in there, and check that its height is correct. To check its height, try getting the render object with tester.renderObject and looking at its .size.height.

  • EmojiPickerListEntry.build has this comment: "// TODO deduplicate this logic with [_EmojiAutocompleteItem]

    • That can be out of scope for this PR, but the comment is a hint that some other code (in _EmojiAutocompleteItem) might have the same problem, with a similar fix. That seems to be the case; could you please make that fix and post screenshots of it too, and write a test for it?
  • Please revise the commit message according to the project style (follow links in the README)

oh okay will work on this

@loveucifer
Copy link
Author

wrote the test for emojI-reaction but having a hard time with autocomplete test dont know why will try to send one asap

TextEmojiDisplay() => null, // The text is already shown separately.
TextEmojiDisplay() => Text(' ', style: TextStyle(fontSize: _emojiSize)),
Copy link
Collaborator

Choose a reason for hiding this comment

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

When using the text-only emojis the emoji picker list items did not scale correctly with the system's text scale factor in the earlier pr . i think this was because the placeholder for the emoji glyph had a fixed, unscalable height, preventing the row from growing as we wanted.

Image and Unicode emoji don't scale with the system text-size setting (try it), so we shouldn't scale the empty-square placeholder either.

@loveucifer loveucifer force-pushed the fix/emoji-picker-plain-text-1587 branch from adeca3b to 8f92f0c Compare July 30, 2025 19:31
@loveucifer
Copy link
Author

wrote the test for emojI-reaction but having a hard time with autocomplete test dont know why will try to send one asap

I had some help from llm to write the test for autocomplete but it did pass for now , couldn't figure out why the one I wrote kept falling even though I applied almost the same logic

@loveucifer
Copy link
Author

wrote the test for emojI-reaction but having a hard time with autocomplete test dont know why will try to send one asap

I had some help from llm to write the test for autocomplete but it did pass for now , couldn't figure out why the one I wrote kept falling even though I applied almost the same logic

actually circling back and seeing why it failed I think it was a syntax error I think I used check(finder).findsOneWidget() instead of check(finder).findsOne()

@chrisbobbe
Copy link
Collaborator

OK, please comment when this is ready for another review. If you need help, see our README, in particular the "asking great questions" article linked from there: https://github.com/zulip/zulip-flutter?tab=readme-ov-file#asking-questions-getting-help

@loveucifer
Copy link
Author

OK, please comment when this is ready for another review. If you need help, see our README, in particular the "asking great questions" article linked from there: https://github.com/zulip/zulip-flutter?tab=readme-ov-file#asking-questions-getting-help

i have done it , it is running through the checks rn , please do check and give a review when possible

@loveucifer loveucifer requested a review from chrisbobbe July 30, 2025 19:59
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.

Comments below. Please squash the two commits together and do another pass on the commit message to make sure it matches our style.

// TODO deduplicate this logic with [EmojiPickerListEntry]
// This logic is now corrected to match EmojiPickerListEntry as per todo
Copy link
Collaborator

Choose a reason for hiding this comment

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

This TODO still applies; please don't delete it. The comment doesn't need to be changed. ("Deduplicate" means make a helper function or something that can be invoked in both places. As I mentioned earlier, you don't have to write that helper function as part of this PR.)

Comment on lines 352 to 353
// Use a simple SizedBox for a perfect, non-scaling placeholder.
TextEmojiDisplay() => const SizedBox.square(dimension: _size),
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
// Use a simple SizedBox for a perfect, non-scaling placeholder.
TextEmojiDisplay() => const SizedBox.square(dimension: _size),
// The text is already shown; just put a placeholder here to set the row height.
TextEmojiDisplay() => const SizedBox.square(dimension: _size),

child: glyph),
const SizedBox(width: 6),
],
// The `if (glyph != null)` check is removed, as the glyph is always present.
Copy link
Collaborator

Choose a reason for hiding this comment

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

This comment isn't needed; it refers to something that isn't visible in the code.

Comment on lines 585 to 586
TextEmojiDisplay() => Text(' ',
style: TextStyle(fontSize: _emojiSize), textScaler: TextScaler.noScaling),
Copy link
Collaborator

Choose a reason for hiding this comment

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

We should use an empty square placeholder here too.

await tester.pumpAndSettle(); // Ensure store update is fully processed.

// Phase 1: Get the height of the item when it has an image.
// This two-step `enterText` call is a more reliable way to trigger the autocomplete view.
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
// This two-step `enterText` call is a more reliable way to trigger the autocomplete view.
// TODO(#226): Remove this extra edit when this bug is fixed.

(here and the other place(s) where it applies)

Comment on lines 573 to 584
// Close the emoji picker. This also closes the underlying action sheet also.
Navigator.of(tester.element(find.byType(EmojiPicker))).pop();
await tester.pumpAndSettle(); // Let dismiss animations finish.

// We are now back at the message list. Let's start over to see the setting change.
// now we Long-press the message to open the action sheet again.
await tester.longPress(find.byType(MessageContent));
await tester.pumpAndSettle();

// now we Tap the button to open the emoji picker, which will now use the new setting.
await tester.tap(find.byIcon(ZulipIcons.chevron_right));
await tester.pumpAndSettle();
Copy link
Collaborator

Choose a reason for hiding this comment

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

Is it necessary to close and re-open the emoji picker? What happens if the test doesn't do that?

Copy link
Author

Choose a reason for hiding this comment

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

I thought that byy completely closing the emoji picker and re-opening it, we could be be sure that it was a brand-new widget built with the updated "Text only" setting, is that bad?

@loveucifer
Copy link
Author

Comments below. Please squash the two commits together and do another pass on the commit message to make sure it matches our style.

as mentioned in my other pr im not sure if im doing the rebase thing correctly I havent used it yet ,will try another go again, also trying another pass on the commit style and as an update the test still works without reopening the emoji-picker

@loveucifer loveucifer force-pushed the fix/emoji-picker-plain-text-1587 branch from 8f92f0c to f301858 Compare July 30, 2025 20:46
@loveucifer loveucifer requested a review from chrisbobbe July 31, 2025 03:29
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.

Please find the place in our commit-discipline doc where it says how to wrap the commit-message body text. If that's difficult for you, please explain where you looked and how we can make it more obvious for future contributors.

Looking back at the issue #1587 and your screenshots (thanks for posting those!), I've also realized that we don't actually want to add any horizontal whitespace, only vertical whitespace. The empty space on the left looks odd. So in the text-emoji case, instead of creating a padded SizedBox.square, we should put a zero-width SizedBox(height: n) where n is whatever would make the rows the same height as in the non-text-emoji case.

Comment on lines 579 to 580
final renderBox = tester.renderObject<RenderBox>(listEntryFinder);
check(renderBox.size.height).isLessThan(45.0);
Copy link
Collaborator

Choose a reason for hiding this comment

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

Why check that the height is less than a number? The point of this test is to make sure the height is large enough. In other words (as you've written in a comment at the top), it's a regression test for #1587.

Comment on lines 561 to 562
tester.platformDispatcher.textScaleFactorTestValue = 2.0;
addTearDown(tester.platformDispatcher.clearTextScaleFactorTestValue);
Copy link
Collaborator

Choose a reason for hiding this comment

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

The reproduction recipe for #1587 doesn't involve setting the system text-size setting, so I don't think these lines are needed in a regression test for #1587. What happens if we remove them?

Comment on lines 565 to 631
// Set up the emoji picker, which leaves it open.
await setupEmojiPicker(tester, message: message, narrow: TopicNarrow.ofMessage(message));
Copy link
Collaborator

Choose a reason for hiding this comment

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

nit: Remove the comment; it describes something that's already obvious from reading the code

// Set up the emoji picker, which leaves it open.
await setupEmojiPicker(tester, message: message, narrow: TopicNarrow.ofMessage(message));

// Now, change the setting to text-only emoji.
Copy link
Collaborator

Choose a reason for hiding this comment

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

nit: also remove this comment for the same reason

await store.handleEvent(UserSettingsUpdateEvent(id: 1,
property: UserSettingName.emojiset,
value: Emojiset.text));
// The picker is already open and will rebuild with the new setting.
Copy link
Collaborator

Choose a reason for hiding this comment

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

nit: and this one


final composeInputFinder = await setupToComposeInput(tester);

// Set up a realm emoji so we have a reliable image emoji to test against.
Copy link
Collaborator

Choose a reason for hiding this comment

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

nit: Remove this comment; it explains something that's already obvious from reading the code

await store.handleEvent(RealmEmojiUpdateEvent(id: 1, realmEmoji: {
'1': eg.realmEmojiItem(emojiCode: '1', emojiName: 'an_image_emoji'),
}));
await tester.pumpAndSettle(); // Ensure store update is fully processed.
Copy link
Collaborator

Choose a reason for hiding this comment

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

Can this just be an await tester.pump()? Also the comment doesn't seem necessary.

check(imageItemFinder).findsOne();
final imageItemHeight = tester.getSize(imageItemFinder).height;

//TODO(#226): Remove this extra edit when this bug is fixed.
Copy link
Collaborator

Choose a reason for hiding this comment

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

nit: space after //

// TODO(#226): Remove this extra edit when this bug is fixed.
await tester.enterText(composeInputFinder, ':an_imag');
await tester.enterText(composeInputFinder, ':an_image');
await tester.pumpAndSettle();
Copy link
Collaborator

Choose a reason for hiding this comment

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

nit: Can this just be an await tester.pump()? What do the other tests do?

Comment on lines 393 to 396
final imageItemFinder = find.ancestor(
of: find.text('an_image_emoji'),
matching: find.byType(InkWell),
);
Copy link
Collaborator

Choose a reason for hiding this comment

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

Can this be find.widgetWithText(InkWell, 'an_image_emoji')? (and similarly below)

@loveucifer
Copy link
Author

loveucifer commented Aug 1, 2025

So in the text-emoji case, instead of creating a padded SizedBox.square, we should put a zero-width SizedBox(height: n) where n is whatever would make the rows the same height as in the non-text-emoji case.

I gave this code initially -- final imageHeight = imageRenderBox.size.height; but the test failed and gave output he following TestFailure was thrown running a test: Expected: a double that: is within <1.0> of <40.0> Actual: <44.0> Which: differs by <4.0> so im changing it to this for now to see how it will go
40.0 (Target Height) - 10.0 (Top Padding) - 10.0 (Bottom Padding) = 20.0

@loveucifer loveucifer force-pushed the fix/emoji-picker-plain-text-1587 branch from f301858 to 24826ef Compare August 1, 2025 07:22
@loveucifer
Copy link
Author

Thanks, comments below.

Please find the place in our commit-discipline doc where it says how to wrap the commit-message body text. If that's difficult for you, please explain where you looked and how we can make it more obvious for future contributors.

Looking back at the issue #1587 and your screenshots (thanks for posting those!), I've also realized that we don't actually want to add any horizontal whitespace, only vertical whitespace. The empty space on the left looks odd. So in the text-emoji case, instead of creating a padded SizedBox.square, we should put a zero-width SizedBox(height: n) where n is whatever would make the rows the same height as in the non-text-emoji case.

also updating the image addressing this new change for autocomplete

@loveucifer loveucifer force-pushed the fix/emoji-picker-plain-text-1587 branch from 24826ef to 2603c0d Compare August 1, 2025 07:40
Comment on lines 583 to 585
if (glyph != null)
Padding(
Padding(
padding: const EdgeInsets.all(10),
child: glyph),
Copy link
Collaborator

Choose a reason for hiding this comment

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

This adds horizontal padding (const EdgeInsets.all(10)). We don't want to do that, as I mentioned in #1759 (review).

I suggest keeping null for glyph in the text-emoji case, and adding an else here that makes a SizedBox(height: _emojiSize + 10 + 10). Similarly in the other case.

Copy link
Author

Choose a reason for hiding this comment

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

okay will work on that

@loveucifer loveucifer force-pushed the fix/emoji-picker-plain-text-1587 branch from 2603c0d to ffe4843 Compare August 1, 2025 20:03
@loveucifer loveucifer marked this pull request as draft August 5, 2025 13:02
@loveucifer loveucifer force-pushed the fix/emoji-picker-plain-text-1587 branch 2 times, most recently from 2e74f56 to bfc715b Compare August 5, 2025 14:52
@loveucifer
Copy link
Author

@loveucifer loveucifer marked this pull request as ready for review August 5, 2025 15:12
Previously, text-only emoji rows in the emoji picker and autocomplete lists were shorter than rows with image emoji, causing layout inconsistency.

This commit fixes the layout by conditionally adding a `SizedBox` spacer for text-only items. The spacer's height is set to match the total height of a padded image glyph, ensuring all rows have a consistent height without adding unwanted horizontal padding.

This change is applied to both `EmojiPickerListEntry` and `_EmojiAutocompleteItem`. The corresponding regression tests are updated to verify that the height of a text-only item is identical to an image-based item.

Fixes zulip#1587.
@loveucifer loveucifer force-pushed the fix/emoji-picker-plain-text-1587 branch from bfc715b to 058422a Compare August 5, 2025 15:17
@loveucifer loveucifer requested a review from chrisbobbe August 5, 2025 16:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants