fix(mobile): highlight full multi-word mentions (#1762)

Signed-off-by: npub1shglkdhngx3hrnhf4gf8vhpqdrmeludctechdvpwd3988zzs7ncq2cmtxu <85d1fb36f341a371cee9aa12765c2068f79ff1b85e7176b02e6c4a738850f4f0@sprout-oss.stage.blox.sqprod.co>
Co-authored-by: npub1shglkdhngx3hrnhf4gf8vhpqdrmeludctechdvpwd3988zzs7ncq2cmtxu <85d1fb36f341a371cee9aa12765c2068f79ff1b85e7176b02e6c4a738850f4f0@sprout-oss.stage.blox.sqprod.co>
This commit is contained in:
Tom Brow
2026-07-12 08:14:54 -07:00
committed by GitHub
co-authored by npub1shglkdhngx3hrnhf4gf8vhpqdrmeludctechdvpwd3988zzs7ncq2cmtxu
parent 2687a2a185
commit 92bb959ee1
2 changed files with 22 additions and 3 deletions
@@ -112,10 +112,10 @@ class MessageContent extends HookConsumerWidget {
var segment = mentionParts[i];
for (final name in mentionNames.values) {
if (name.contains(' ')) {
final nbspName = name.replaceAll(' ', '\u00A0');
final normalizedName = _markdownMentionName(name);
segment = segment.replaceAllMapped(
RegExp('@${RegExp.escape(name)}', caseSensitive: false),
(m) => '@$nbspName',
(m) => '@$normalizedName',
);
}
}
@@ -716,11 +716,13 @@ RegExp _buildPrefixPattern({
);
}
String _markdownMentionName(String name) => name.replaceAll(' ', '\u00A0');
Iterable<String> _mentionAliases(Iterable<String> mentionNames) sync* {
for (final name in mentionNames) {
final trimmed = name.trim();
if (trimmed.isEmpty) continue;
yield trimmed;
yield _markdownMentionName(trimmed);
final firstName = trimmed.split(RegExp(r'\s+')).first;
if (firstName.isNotEmpty) {
yield firstName;
@@ -732,6 +732,23 @@ void main() {
expect(find.text('@Alice'), findsOneWidget);
});
testWidgets('highlights an entire multi-word display name', (
tester,
) async {
await tester.pumpWidget(
_testable(
const MessageContent(
content: 'Hey @Kenny Lopez can you review this?',
mentionNames: {'pk1': 'Kenny Lopez'},
),
),
);
expect(find.text('@Kenny Lopez'), findsOneWidget);
expect(find.text('@Kenny'), findsNothing);
expect(_allRichText(tester), isNot(contains('Lopez Lopez')));
});
testWidgets('renders unknown @mention as-is', (tester) async {
await tester.pumpWidget(
_testable(