Skip to content

Commit

Permalink
content: Handle @-topic mentions
Browse files Browse the repository at this point in the history
Fixes: #892
  • Loading branch information
rajveermalviya committed Dec 18, 2024
1 parent 28b3536 commit 0edabbf
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 6 deletions.
15 changes: 9 additions & 6 deletions lib/model/content.dart
Original file line number Diff line number Diff line change
Expand Up @@ -876,8 +876,9 @@ class _ZulipContentParser {
final debugHtmlNode = kDebugMode ? element : null;

final classes = element.className.split(' ')..sort();
assert(classes.contains('user-mention')
|| classes.contains('user-group-mention'));
assert(classes.contains('topic-mention')
|| classes.contains('user-mention')
|| classes.contains('user-group-mention'));
int i = 0;

if (i >= classes.length) return null;
Expand All @@ -895,12 +896,14 @@ class _ZulipContentParser {
}

if (i >= classes.length) return null;
if (classes[i] == 'user-mention'
if ((classes[i] == 'topic-mention' && !hasChannelWildcardClass)
|| classes[i] == 'user-mention'
|| (classes[i] == 'user-group-mention' && !hasChannelWildcardClass)) {
// The class we already knew we'd find before we called this function.
// We ignore the distinction between these; see [UserMentionNode].
// Also, we don't expect "user-group-mention" and "channel-wildcard-mention"
// to be in the list at the same time.
// to be in the list at the same time and neither we expect "topic-mention"
// and "channel-wildcard-mention" to be in the list at the same time.
i++;
}

Expand Down Expand Up @@ -931,9 +934,9 @@ class _ZulipContentParser {
/// Matches all className values that could be a UserMentionNode,
/// and no className values that could be any other type of node.
// Specifically, checks for `user-mention` or `user-group-mention`
// as a member of the list.
// or `topic-mention` as a member of the list.
static final _userMentionClassNameRegexp = RegExp(
r"(^| )" r"user(?:-group)?-mention" r"( |$)");
r"(^| )" r"(?:user(?:-group)?|topic)-mention" r"( |$)");

static final _emojiClassNameRegexp = () {
const specificEmoji = r"emoji(?:-[0-9a-f]+)+";
Expand Down
25 changes: 25 additions & 0 deletions test/model/content_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,27 @@ class ContentExample {
'<p><span class="silent user-mention" data-user-id="*">all</span></p>',
const UserMentionNode(nodes: [TextNode('all')]));

static final topicMentionPlain = ContentExample.inline(
'plain @-topic',
"@**topic**",
expectedText: '@topic',
'<p><span class="topic-mention">@topic</span></p>',
const UserMentionNode(nodes: [TextNode('@topic')]));

static final topicMentionSilent = ContentExample.inline(
'silent @-topic',
"@_**topic**",
expectedText: 'topic',
'<p><span class="topic-mention silent">topic</span></p>',
const UserMentionNode(nodes: [TextNode('topic')]));

static final topicMentionSilentClassOrderReversed = ContentExample.inline(
'silent @-topic, class order reversed',
"@_**topic**", // (hypothetical server variation)
expectedText: 'topic',
'<p><span class="silent topic-mention">topic</span></p>',
const UserMentionNode(nodes: [TextNode('topic')]));

static final emojiUnicode = ContentExample.inline(
'Unicode emoji, encoded in span element',
":thumbs_up:",
Expand Down Expand Up @@ -1262,6 +1283,10 @@ void main() {
testParseExample(ContentExample.legacyChannelWildcardMentionPlain);
testParseExample(ContentExample.legacyChannelWildcardMentionSilent);
testParseExample(ContentExample.legacyChannelWildcardMentionSilentClassOrderReversed);

testParseExample(ContentExample.topicMentionPlain);
testParseExample(ContentExample.topicMentionSilent);
testParseExample(ContentExample.topicMentionSilentClassOrderReversed);
});

testParseExample(ContentExample.emojiUnicode);
Expand Down
3 changes: 3 additions & 0 deletions test/widgets/content_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -669,6 +669,9 @@ void main() {
testContentSmoke(ContentExample.legacyChannelWildcardMentionPlain);
testContentSmoke(ContentExample.legacyChannelWildcardMentionSilent);
testContentSmoke(ContentExample.legacyChannelWildcardMentionSilentClassOrderReversed);
testContentSmoke(ContentExample.topicMentionPlain);
testContentSmoke(ContentExample.topicMentionSilent);
testContentSmoke(ContentExample.topicMentionSilentClassOrderReversed);

UserMention? findUserMentionInSpan(InlineSpan rootSpan) {
UserMention? result;
Expand Down

0 comments on commit 0edabbf

Please sign in to comment.