Fix emoji suggestion list reopening after closing FAB with ESC#95456
Conversation
Co-authored-by: huult <huult@users.noreply.github.com>
|
I created this PR from an upstream branch since I don't have push access to your fork. To take ownership of this branch and be able to push updates, run: Then you can close this PR and open a new one from your fork. |
|
The only failing check right now is That check isn't something I can fix by pushing code. It fails because:
Per policy I can't fill out the human-only If any of the still-pending checks ( |
Codecov Report✅ Changes either increased or maintained existing code coverage, great job!
|
|
@MelvinBot Please mark it ready and we can remove the comments within the Tests and QA Steps section since the use case is related to the offline scenario. Also, please check all the PR Author checklist items. |
|
🤖 Done,
Let me know if you'd like anything tweaked. |
Reviewer Checklist
Screenshots/VideosAndroid: HybridAppScreen.Recording.2026-07-07.at.22.04.41.movAndroid: mWeb ChromeScreen.Recording.2026-07-07.at.22.05.38.moviOS: HybridAppScreen.Recording.2026-07-07.at.22.09.46.moviOS: mWeb SafariScreen.Recording.2026-07-07.at.22.10.09.movMacOS: Chrome / SafariScreen.Recording.2026-07-07.at.21.59.44.mov |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 837a9b53df
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| // Block the next suggestion calculation so refocusing the composer (e.g. after closing the | ||
| // FAB/action-menu popover with ESC) does not reopen the list the user just dismissed. The flag | ||
| // is one-shot: calculateEmojiSuggestion clears it on its next run, so typing re-enables suggestions. | ||
| shouldBlockCalc.current = true; |
There was a problem hiding this comment.
Preserve suggestions after the next typed character
If the user dismisses an emoji suggestion with Escape and then continues typing before a focus-driven recalculation consumes this flag, the next calculateEmojiSuggestion() run sees shouldBlockCalc.current, clears it, calls resetSuggestions(), and returns without evaluating the updated text. For example, pressing Escape on :sm and immediately typing i leaves the :smi suggestions hidden until a second edit, which regresses the expected re-show-on-typing behavior; the block needs to be scoped to the unchanged refocus calculation rather than any next calculation.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
@MelvinBot Could you review it? I was able to reproduce the issue.
There was a problem hiding this comment.
@MelvinBot Could you review codex's comment? I was able to reproduce the issue.
|
Update: all real CI checks are now passing. The only remaining failing check is That check fails until a reviewer completes the PR Reviewer Checklist — it's a human-only step, not something I can tick or push a fix for. There's nothing to fix in the code here. Once a reviewer fills out the reviewer checklist, that check will pass. |
|
The one remaining failing check is
To turn that check green, edit that comment and tick every box once you've verified each item. That's a human reviewer action — I can't complete the reviewer checklist on your behalf. |
|
🤖 Review — the fix is correct, minimal, and targets the right code path. A couple of things to confirm manually before merge (see below). Why it works: the ESC branch now sets the existing one-shot
Please double-check test step 5 (the one tradeoff of this approach): because the flag makes the next Other notes
|
|
🤖 Reviewed codex's comment — it's correct, and your repro confirms it. This is a real regression, and it's exactly the behavior the PR's own Test step 5 promises ("typing another character after dismissing with ESC re-shows suggestions normally"). Why it happens: the block flag is one-shot but not scoped to the refocus case — it's consumed by whatever calculation runs next, including a typed character. Mechanism
The FAB-refocus flow the PR targets works only because no text change happens in between, so the refocus recalc is the one that consumes the flag. Recommended fix — scope the block to the unchanged refocus recalc. Instead of an unconditional one-shot boolean, snapshot the dismissed
Using a dedicated ref (rather than overloading Want me to push this fix? Reply |
|
@MelvinBot implement this |
…w emoji suggestions Snapshot the composer value/cursor on ESC instead of unconditionally blocking the next calculation. Only suppress the recalc when the value and cursor are unchanged (the FAB-refocus case); a typed character changes the value and now re-shows suggestions immediately. Add SuggestionEmojiTest covering ESC-then-refocus (stays closed) and ESC-then-type (re-shows). Co-authored-by: huult <huult@users.noreply.github.com>
|
🤖 Implemented and pushed in a794361. What changed:
Added a regression test — Local checks (green):
Notes
|
Failing check analysisThe only failing check is Why the checklist check failsThis PR adds a new file, That dynamically appends 10 "new component" review items to the author checklist. The check requires zero unchecked boxes, and those 10 are unchecked — hence both How to clear itI intentionally don't auto-fill the PR Author Checklist — those boxes exist for the author to consciously confirm, so this is yours to action:
Once those boxes are checked, the checklist check will re-run and pass. |
|
Nothing has changed since my previous analysis — there's no code fix to push here. The only failing check is still To clear it: in the PR description, tick the 10 |
|
@codex review |
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
|
@codex review |
|
@huult could you add manual test evidence to your reviewer checklist please? Also heads up that the C+ workflow changed a bit recently, check out https://github.com/Expensify/App/blob/main/contributingGuides/HOW_TO_WORK_WITH_MELVINBOT.md - basically even when working with Melvin, you should approve Melvin's proposal in the bug GH so that an internal engineer gets assigned for proposal acceptance before the PR phase 🙇♀️ |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: a7943613a4
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
Same situation as my earlier comment — nothing here needs a code push. All 37 functional checks pass (typecheck, tests, ESLint, Storybook, builds, perf, etc.). The only red check is It fails because the added test file This one is yours to clear, |
@amyevans Thanks for the reminder! I'll follow the new Melvin workflow from now on. I appreciate the heads up. |
|
All checks are green now — nothing to fix. ✅ 38 checks pass and 0 are failing, including both The PR shows |
|
🚧 amyevans has triggered a test Expensify/App build. You can view the workflow run here. |
|
✋ This PR was not deployed to staging yet because QA is ongoing. It will be automatically deployed to staging after the next production release. |
|
🧪🧪 Use the links below to test this adhoc build on Android, iOS, and Web. Happy testing! 🧪🧪
|
|
🚀 Deployed to staging by https://github.com/amyevans in version: 9.4.29-0 🚀
|
|
🤖 Help site review: no changes required I reviewed the changes in this PR against Expensify's help site files under This is a narrow bug fix for a UI interaction glitch — after typing an emoji shortcode (e.g. It does not change any documented feature, setting, label, tab, or user-facing workflow. The only emoji references in the help site are generic (adding an emoji from the message bar, status emoji) and none document the shortcode suggestion list or its keyboard-dismissal behavior. So there is nothing to update, and I did not create a draft docs PR. If you disagree and think a help article should cover this behavior, let me know which article and I'll draft the update. |
|
🚀 Deployed to staging by https://github.com/amyevans in version: 9.4.31-0 🚀
|
|
🤖 Help site review: no changes required I reviewed the changes in this PR against the help site files under This PR is a narrow bug fix for a keyboard-interaction edge case: after typing an emoji shortcode (e.g. Why no docs update is needed:
No draft PR was created since no help site changes are warranted. |
|
🚀 Deployed to production by https://github.com/grgia in version: 9.4.31-0 🚀
Bundle Size Analysis (Sentry): |
Explanation of Change
After typing an emoji shortcode such as
:smand pressing ESC to dismiss the emoji suggestion list, opening the+action menu / FAB popover and closing it with ESC made the dismissed emoji list reopen.Pressing ESC only called
resetSuggestions(), which clears the visible list but leaves the:smtext and cursor in the composer and records nothing about the dismissal. Closing the popover refocuses the composer, which flipsisComposerFocusedback totrueand re-runs the suggestion-calculation effect against the unchanged:smtext — regenerating the identical list.This change sets the existing one-shot
shouldBlockCalc.current = trueflag in the ESC branch oftriggerHotkeyActions, right beforeresetSuggestions().calculateEmojiSuggestionalready consumes and clears that flag on its very next run, so the refocus-triggered recalculation is suppressed (the list stays closed), while typing another character or moving the cursor immediately re-enables suggestions.Scope is limited to
SuggestionEmoji.tsxfor now, as requested by the assignee. The@mention list (SuggestionMention.tsx) has the same structure and could receive the same one-line guard in a follow-up if desired.This implements MelvinBot's approved proposal.
Fixed Issues
$ #95441
PROPOSAL: #95441 (comment)
Tests
:smin the composer to show the emoji suggestion list.+(create) action button / FAB, then press ESC to close the popover.i) after dismissing with ESC re-shows suggestions normally.Offline tests
Same as tests.
QA Steps
:smin the composer to show the emoji suggestion list.+(create) action button / FAB, then press ESC to close the popover.i) after dismissing with ESC re-shows suggestions normally.PR Author Checklist
### Fixed Issuessection aboveTestssectionOffline stepssectionQA stepssectiontoggleReportand notonIconClick)Avatar, I verified the components usingAvatarare working as expected)StyleUtils.getBackgroundAndBorderStyle(theme.componentBG))npm run compress-svg)Avataris modified, I verified thatAvataris working as expected in all cases)Designlabel and/or tagged@Expensify/designso the design team can review the changes.mainbranch was merged into this PR after a review, I tested again and verified the outcome was still expected according to theTeststeps./** comment above it */thisproperly so there are no scoping issues (i.e. foronClick={this.submit}the methodthis.submitshould be bound tothisin the constructor)thisare necessary to be bound (i.e. avoidthis.submit = this.submit.bind(this);ifthis.submitis never passed to a component event handler likeonClick)Screenshots/Videos
Android: Native
Android: mWeb Chrome
iOS: Native
iOS: mWeb Safari
MacOS: Chrome / Safari