fix(mobile): draw a whole character in an avatar fallback - #5998
fix(mobile): draw a whole character in an avatar fallback#5998Chessing234 wants to merge 3 commits into
Conversation
`label[0]` and `label.substring(0, 1)` return one UTF-16 code unit. Anything outside the Basic Multilingual Plane — every emoji, and CJK Extension B, which appears in ordinary Chinese and Japanese given names — is stored as a surrogate pair, so those return half of one: not a character, and drawn as `�` in the avatar. Reading grapheme clusters also keeps a base letter together with its combining marks, so a Devanagari or Burmese name keeps its vowel sign instead of showing a bare consonant. The `characters` package is already a direct dependency and the codebase already reaches for it where text has to be treated as text — `shared/emoji/emoji_only.dart` and the message preview in `features/channels/message_actions.dart`. This is the same rule, for avatars. No call sites yet. Signed-off-by: Taksh <takshkothari09@gmail.com>
Seven avatar fallbacks took their letter with `label[0]` or `substring(0, 1)`. Both return a UTF-16 code unit, so a display name starting with an emoji or a CJK Extension B character produced half a surrogate pair and the avatar drew `�`: the profile model, invite and channel-management labels, the members sheet, both pulse note surfaces, and people results in search. They now go through `avatarInitial`, which also keeps a combining mark with the letter it belongs to, so a Devanagari or Burmese name no longer loses its vowel sign. The pubkey-derived fallbacks elsewhere are left alone — hex is ASCII, and taking one code unit of it was never wrong. Signed-off-by: Taksh <takshkothari09@gmail.com>
themiguelamador
left a comment
There was a problem hiding this comment.
The shared avatarInitial helper is correct and its focused test passes, but the same bug remains in two avatar fallbacks:
mobile/lib/features/channels/compose_bar/suggestions.dartstill usesname[0].toUpperCase(). This still renders half a surrogate pair for astral names and can throw when a candidate label is empty.mobile/lib/features/channels/channels_page/community.dartstill usestrimmedName.substring(0, 1).toUpperCase(), so community names beginning with an astral character still render U+FFFD.
Please route both through avatarInitial (adding the imports to the parent part libraries). Minor documentation correction: “every emoji” is outside the BMP is too broad; “most emoji” is accurate.
I applied and verified this exact patch locally: the focused Flutter test passes, flutter analyze reports no issues, and the mobile pre-commit gate passes. I attempted to push the signed-off fix directly because maintainer_can_modify is true, but GitHub returned 403 for my account.
Review found two the earlier commit missed, both inside `part of` libraries so their imports belong on the parent: - `compose_bar/suggestions.dart` used `name[0].toUpperCase()`, which draws half a surrogate pair for an astral name and throws outright when a candidate label is empty - `channels_page/community.dart` used `trimmedName.substring(0, 1)`, so a community name starting with an astral character rendered U+FFFD `avatarInitial` covers the empty case with `?`, which is what both sites already wanted. Also corrects the doc: "every emoji" is outside the BMP was too broad. Most are; ☺ and ✌ are not. Signed-off-by: Taksh <takshkothari09@gmail.com>
|
both confirmed and fixed in
both are
wording: fixed — "most emoji" in the doc. i deleted my earlier comment on this pr because it was wrong on a point of fact. it said there was no flutter or dart sdk on this machine and that i therefore couldn't verify mobile changes. that isn't true — the repo pins both through hermit ( |
themiguelamador
left a comment
There was a problem hiding this comment.
Re-reviewed current head c46fb059a. This update resolves every prior finding: the compose mention and community avatar fallbacks now use avatarInitial, the imports are correctly placed in their parent libraries, and the Unicode documentation is accurate.
Verified with flutter analyze, Dart formatting, and the affected helper, compose-bar, and channels-page test files (129/129 passed). No remaining findings.
|
verification for this branch, now that i have the toolchain i wrongly said i didn't:
so your local run and mine agree. nothing further needed from you on this one. |
The mobile half of #5992, which fixed the same bug in desktop's
getInitials. No issue filed.Seven avatar fallbacks took their letter with
label[0]orlabel.substring(0, 1). Both return a single UTF-16 code unit, so a display name starting with an emoji or a CJK Extension B character — ordinary in Chinese and Japanese given names — produced half a surrogate pair, and the avatar drew�:UserProfile.initial(the profile model every surface reads)Reading grapheme clusters also keeps a base letter together with its combining marks, so a Devanagari or Burmese name keeps its vowel sign instead of showing a bare consonant.
This follows the codebase's own practice rather than introducing anything.
charactersis already a direct dependency inpubspec.yaml, and mobile already reaches for it wherever text has to be treated as text —shared/emoji/emoji_only.dartiterates.characters, and the message preview infeatures/channels/message_actions.darttruncates by.charactersrather than by index. The avatar fallbacks were the ones that hadn't caught up.The pubkey-derived fallbacks (
forum_post_card.dart,forum_thread_page.dart,user_profile_sheet.dart) are deliberately untouched: hex is ASCII, and taking one code unit of it was never wrong.Verification note (corrected). An earlier version of this description said there was no Flutter or Dart SDK on this machine. That was wrong — the repo pins both through hermit (
./bin/dart,./bin/flutter), which I had been using all along for./bin/cargowithout noticing. I am running the mobile checks and will post the results in the thread.Note: I'm an outside contributor, so the workflow runs here sit at
action_requireduntil a maintainer approves them; only the DCO check reports on its own.