mirror of
https://github.com/block/buzz.git
synced 2026-10-30 14:01:37 +00:00
### Summary Inbox rows and search results show each message as a 2-line preview. That preview was a capped `MessageContent`, so gpt_markdown parsed and laid out the whole source (syntax-highlighted code blocks and measured tables included), even though only two lines are painted. A native trace on an iPhone 12 mini attributed a 102 ms inbox-open frame mostly to this work. Previews now skip Markdown entirely. `messagePreviewSource` takes only the leading lines a preview can show, and at most the first 4,000 characters of a single long line, so link normalization, mention binding and emoji lookup never scan the rest of a long message. `messagePreviewPieces` is then a linear pass over those lines, similar to desktop's `getMarkdownPreviewText`. It drops block syntax (headings, quotes, list markers, rules, table dividers, code fences) and unwraps inline emphasis and `<u>`, honoring backslash escapes and keeping inline (including multi-backtick) and fenced code as literal text. It also replaces links with their label. The new `MessagePreview` widget renders the result as a single `Text.rich` with `maxLines` and an ellipsis. Tokens keep the look they have in the thread view: - A bound mention is the same `MessageMentionPill` chip, with the bot icon for agents. An ambiguous mention stays as text. - `#channel` tokens and `buzz://channel/...` links are the same channel token chip. - A `buzz://message`, repo, PR or issue link that shows its own URL previews with the thread view's short label, such as `general · abcdef01`. Both use the shared `buzzLinkLabel` helper. - Custom emoji render as inline images. Only shortcodes the message names are looked up in the palette. - Media links show as "Image", "Video" or "Audio". Chips in previews are not tappable, and tapping the row opens the message. Bold, italic, inline code and link styling are no longer shown in previews. The timeline and thread view are unchanged, and so is the profile status line, which still uses `MessageContent`. This replaces this PR's earlier approach of cutting the Markdown source before parsing. That approach needed delimiter-balance heuristics, and a security review found a real case (`**` inside a link label) where the heuristic misfired. ### Validation - `preview_text_test.dart` is a table test of the parser: block syntax, emphasis that must and must not unwrap (`snake_case`, a lone `*`), inline and fenced code, unpaired backticks, links, tables, the line limit and the long-line cap. It also covers mentions (bound, ambiguous, inside emphasis, link labels and code), custom emoji (including adjacent `🅰️b:`), channel tokens and links, message and repo link labels, and media. The long-line row also asserts that `messagePreviewSource` returns a bounded prefix. - `message_preview_test.dart` checks the widget: no `GptMarkdown`, one capped and ellipsized paragraph, mention chip, custom emoji image, channel chip, media label and empty content. - Existing inbox and search tests updated to find `MessagePreview`, including the agent-chip test in search. - `flutter analyze` and the full mobile test suite pass at8c721ba3a(with `--dart-define=BUZZ_PUSH_GATEWAY_URL=https://push.example`, as `just mobile-test` runs it). - Device A/B on an iPhone 12 mini, using Profile builds against the real inbox on the internal relay. Each run was a cold launch followed by 6 Inbox opens, in the order main, fix, main, fix: | | maineda26b942| this PR6661d594a| |---|---|---| | First open, worst frame (run 1 / run 2) | 40.4 / 34.9 ms | 22.4 / 23.2 ms | | First open, build total (run 1 / run 2) | 77.8 / 91.1 ms | 38.5 / 52.3 ms | | All opens, median worst frame | 27.2 ms | 23.3 ms | | All opens, median build total | 43.4 ms | 26.6 ms | First open drops about 40% in build time and about 14 ms in worst frame. On warm opens, build time also drops about 40%, but the worst frame barely moves, so what remains in those frames is not the preview parse. ## Codex review status Codex reviewed this PR over four rounds. Every finding about cost or correctness is fixed, and those threads are resolved. Later rounds turned up narrower and narrower preview edge cases, so the author decided to stop iterating on Codex findings. Any Codex thread still open, or any finding Codex posts afterf538853ed, is a deliberately accepted preview limitation and doesn't block merging. Example: a [code span that continues across a line break](https://github.com/block/buzz/pull/8675#discussion_r4415196032) can preview a mention as a chip. The full message view is unaffected. Only the one- or two-line inbox and search previews can differ from it. buzz-review-completed 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Signed-off-by: Tom Brow <tomb@block.xyz> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>