Fix recent-emoji list leaking into UI on unrelated parent rebuild - #269
Merged
Conversation
`updateRecentEmoji(refresh: false)` still mutated `_categoryEmoji`, the list held by reference in `EmojiViewState`. Only the `setState()` call was gated by `refresh`, so the "don't show yet" data surfaced on the next unrelated rebuild triggered by a parent widget — the RECENT tab would re-order under the user (originally reported in #238). Skip the displayed-category mutation entirely when `refresh` is false. The persisted store is already updated by the caller, so the change is not lost — it becomes visible on the next explicit refresh instead of leaking early. Adds a regression test covering both the refresh:false (no leak on parent rebuild) and refresh:true (immediate update) paths. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Fintasys
force-pushed
the
fix-recent-emoji-state-leak
branch
from
July 22, 2026 03:38
a93e1c0 to
70e5e21
Compare
Fintasys
marked this pull request as ready for review
July 22, 2026 03:49
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Reported in #238: selecting an emoji while the RECENT tab is visible could make the recent list suddenly re-order/jump later, in reaction to an unrelated rebuild triggered by a parent widget.
Root cause
EmojiPickerState.updateRecentEmoji(refresh: false)only gated thesetState()call with therefreshflag — it always mutated_categoryEmojiregardless:_categoryEmojiis the same list instance held by reference inEmojiViewState(_state = EmojiViewState(_categoryEmoji, ...)), andDefaultEmojiPickerViewrebuilds the recent grid straight from it on everybuild(). So on the RECENT tab, tapping an emoji reorders the data silently (nosetState, no visible change) — but the next stray rebuild from a parent widget paints that already-mutated data, and the recent list jumps.This is exactly the inconsistency described in the #238 discussion: "it updates the list in the state, but doesn't update the UI".
Fix
Skip the displayed-category mutation entirely when
refreshisfalse. The persisted store is already updated by the caller (addEmojiToRecentlyUsed/addEmojiToPopularUsedwrite before this call), so nothing is lost — the change simply becomes visible on the next explicit refresh instead of leaking in early.Test
Adds
test/recent_emoji_state_test.dart:EmojiPickerUtils.addEmojiToRecentlyUsedAPI (which callsupdateRecentEmoji(refresh: false)), then forces an unrelated parent rebuild and asserts the recent tab is unchanged. Fails on the old code, passes with the fix.Full suite (15 tests) passes;
flutter analyzeclean.🤖 Generated with Claude Code