fix(mobile): stop cutting previews and transcripts through an emoji - #6001
fix(mobile): stop cutting previews and transcripts through an emoji#6001Chessing234 wants to merge 3 commits into
Conversation
`substring` and `length` count UTF-16 code units. Anything outside the Basic Multilingual Plane — every emoji, and CJK Extension B — is stored as a surrogate pair, so a cut that lands inside one leaves a lone surrogate: not a character, and drawn as `�` at the end of the preview. Counting characters also makes the decision to truncate and the cut itself agree with each other, and with what the reader sees. The reminder preview in `features/channels/message_actions.dart` already does this with `.characters.take(...)`. This is that rule, shared, so the next caller doesn't have to rediscover it. No call sites yet. Signed-off-by: Taksh <takshkothari09@gmail.com>
Three places shortened user-facing text with
`text.length > n ? '${text.substring(0, n)}…' : text`. Both halves count
UTF-16 code units, so a forum post ending "…thanks 🎉" cut at 200 loses half
the emoji and the card shows `…thanks �`. The agent transcript does the same
to a tool result at 500 and 2000 characters, where model output carrying
emoji is routine.
Route them through `truncateWithEllipsis`. The limits are unchanged — only
where the cut lands, and that the decision to cut now counts the same units
as the cut itself.
Signed-off-by: Taksh <takshkothari09@gmail.com>
themiguelamador
left a comment
There was a problem hiding this comment.
The grapheme-safe truncation implementation is correct and consistently applied, but the new test file is not in canonical Dart format, so just mobile-check fails (dart format --output=none --set-exit-if-changed reports test/shared/text/truncate_test.dart changed).\n\nI applied the formatter-only fix in signed commit 8a52c9402 and published it at https://github.com/Complear/buzz/tree/review/pr-6001-fix. Please cherry-pick that commit (GitHub rejected my direct push to the fork despite the PR advertising maintainer edits).\n\nVerification after the fix: focused truncation tests 6/6, full mobile suite 1,423/1,423, flutter analyze clean, Dart format check clean, file-size check clean, and git diff --check clean. No Flutter build/run/clean/upgrade command was used.
`dart format --output=none --set-exit-if-changed .` reported the new test changed, so `just mobile-check` failed on this branch. I had hand-wrapped one `expect` across two lines; the formatter joins it, since it fits. Formatter output only — no assertion or behaviour change. Signed-off-by: Taksh <takshkothari09@gmail.com>
|
fixed in reproduced first — - expect(truncateWithEllipsis(body, 200, '...'),
- '${'x' * 199}\u{1F389}...');
+ expect(truncateWithEllipsis(body, 200, '...'), '${'x' * 199}\u{1F389}...');formatter output only, no assertion changed. i'd assumed it would split the call tall-style; it joins it, since it fits in 80. verification, run here rather than taken on trust:
i owe you a correction on this one. i said on this pr and on #5998 that there was no flutter or dart sdk on this machine and that i therefore couldn't verify mobile work. that was wrong — the repo pins both through hermit ( |
The mobile half of #5996, which fixed the same bug in desktop's display truncation. No issue filed.
Three places shorten user-facing text like this:
Both halves count UTF-16 code units. Anything outside the Basic Multilingual Plane — every emoji, and CJK Extension B — is a surrogate pair, so a cut landing inside one leaves a lone surrogate: a forum post ending "…thanks 🎉" cut at 200 shows
…thanks �. The agent transcript does the same to a metadata section at 500 and a tool result at 2000, where model output carrying emoji is routine.Mobile already knows this. The reminder preview in
features/channels/message_actions.darttruncates with.characters.take(...), andshared/emoji/emoji_only.dartiterates.characters.charactersis a direct dependency inpubspec.yaml. These three sites are the ones that hadn't caught up, so this shares the rule rather than introducing one.truncateWithEllipsisalso fixes something subtler than the split: the decision to truncate and the cut itself now count the same units. Previouslylength(code units) decided andsubstring(code units) cut, but the reader sees characters, so a string of 200 emoji was treated as 400 long and truncated when it didn't need to be.Limits are unchanged — only where the cut lands.
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.Sibling PR: #5998 fixes the avatar-initial half of the same class and adds
mobile/lib/shared/text/initial.dartbeside this file. They touch different lines and merge in either order.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.