Files
buzz/mobile/lib/shared/custom_emoji
Mohammad Asfour 1a54eec3db fix(mobile): keep token labels visible in authored Markdown links (#7545)
## Summary

On iOS, an authored Markdown link renders as blank when its label is
recognized as a Buzz channel, mention, or custom emoji. For example:

```markdown
[#2959](https://example.com/)
```

The surrounding text remains visible, but the link has no visible label
or tap target.

Buzz's `_ChannelLinkMd`, `_MentionMd`, and `CustomEmojiMd` components
return `WidgetSpan`s. `gpt_markdown` also renders an authored link
through a `WidgetSpan` and reparses its label through the registered
components. Because the Buzz components were allowed to run inside link
labels, the result was a placeholder nested inside another placeholder,
which does not paint on iOS.

This PR adds the same scope restriction used by `gpt_markdown`'s
built-in link component:

```dart
@override
Set<MarkdownScope> get scopes =>
    MarkdownComponent.allScopesExceptLinkLabel;
```

The override is applied to all three widget-based components. Authored
labels such as `[#2959](url)`, `[@Alice](url)`, and `[👋](url)`
therefore remain ordinary link text, while the same tokens outside links
continue rendering as Buzz pills and custom emoji.

The PR also updates the shared test helpers to find `RichText`
subclasses. Since the upgrade to `gpt_markdown` 1.2.1, body paragraphs
can render through `BidiRichText`; `find.byType(RichText)` does not
match that subclass and could allow an absence assertion to pass without
inspecting the message text.

The handling of unknown bare `#tokens` is deliberately unchanged.
Whether those should remain non-interactive pills or become plain text
is a separate product decision.

### Related issue

Fixes #6124.

This supersedes #6135. That PR solves the same issue by maintaining a
custom fork of `gpt_markdown`'s link component; this PR instead uses the
scoped-component API already available in `gpt_markdown` 1.2.1.

### Testing

Focused suites:

```bash
flutter test \
  test/features/channels/message_content_test.dart \
  test/features/channels/message_content_custom_emoji_test.dart
```

Result: 95 tests passed, 0 failed.

Additional checks:

- `just mobile-check` — passed; analyzer reported no issues.
- `just mobile-fmt` — passed; 549 files formatted with 0 changes.
- Six new regression tests cover channel, mention, emoji, plain-link
control, and outside-link behavior.
- Removing the `_ChannelLinkMd` override causes two regression tests to
fail; removing `_MentionMd` or `CustomEmojiMd` causes one test to fail
in each case.
- Three tests in `message_content_test.dart` directly assert that the
nested-placeholder structure is absent. The custom-emoji tests
separately verify literal text and the absence or presence of
`CustomEmojiImage`, depending on whether the shortcode is inside or
outside a link.

The complete local mobile suite reports 15 failures that reproduce
identically on a clean checkout of `main` at `44316ff7`. In [CI for that
same commit](https://github.com/block/buzz/actions/runs/34238736818),
`Clients / Mobile`, `Mobile`, and `Mobile Swift Domain / Mobile Swift`
all passed.

No native-device screenshot is included. The nested-placeholder fix was
verified through the rendered widget structure, but an iOS simulator
build was blocked by the existing `MLImage.framework` arm64-simulator
incompatibility.

Signed-off-by: Mohammad Asfour <masfour700@gmail.com>
Signed-off-by: Samin Yeasar Sohag <sssohag172@gmail.com>
Co-authored-by: Samin Yeasar Sohag <sssohag172@gmail.com>
2026-10-21 10:24:32 -07:00
..