Skip to content

Commit 20c3911

Browse files
committed
content: Support the new class of channel wildcard mentions
For channel wildcard mentions, the class in the corresponding HTML used to be the same as the user mentions (class="user-mention"), but now there's an additional class added. Now it looks like the following: class="user-mention channel-wildcard-mention". Fixes: zulip#1064
1 parent 215527a commit 20c3911

File tree

3 files changed

+77
-3
lines changed

3 files changed

+77
-3
lines changed

lib/model/content.dart

+22-2
Original file line numberDiff line numberDiff line change
@@ -713,7 +713,7 @@ class UserMentionNode extends InlineContainerNode {
713713
// (e.g., silent mentions' text lacks a leading "@"),
714714
// and we show that text in the same style for all types of @-mention.
715715
// We'll need these for implementing the post-2023 Zulip design, though.
716-
// final UserMentionType mentionType; // TODO(#646)
716+
// final UserMentionType mentionType; // TODO(#646)
717717
// final bool isSilent; // TODO(#647)
718718
}
719719

@@ -880,16 +880,28 @@ class _ZulipContentParser {
880880
|| classes.contains('user-group-mention'));
881881
int i = 0;
882882

883+
if (i >= classes.length) return null;
884+
bool isChannelWildcardClassIncluded = false;
885+
if (classes[i] == 'channel-wildcard-mention') {
886+
// A newly-added class for channel wildcard mentions.
887+
// See: https://github.com/zulip/zulip/pull/31075
888+
i++;
889+
isChannelWildcardClassIncluded = true;
890+
}
891+
883892
if (i >= classes.length) return null;
884893
if (classes[i] == 'silent') {
885894
// A silent @-mention. We ignore this flag; see [UserMentionNode].
886895
i++;
887896
}
888897

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

@@ -923,6 +935,14 @@ class _ZulipContentParser {
923935
// as a member of the list.
924936
static final _userMentionClassNameRegexp = RegExp(
925937
r"(^| )" r"user(?:-group)?-mention" r"( |$)");
938+
// static final _userMentionClassNameRegexp = () {
939+
// // This matches the classes `user-mention`, `user-group-mention`,
940+
// // or `user-mention channel-wildcard-mention`, plus an optional
941+
// // class `silent`, appearing in either order.
942+
// const mentionClass = r"user(?:-group)?-mention|"
943+
// "(?:user-mention channel-wildcard-mention)";
944+
// return RegExp("^(?:$mentionClass)(?: silent)?|silent (?:$mentionClass)\$");
945+
// }();
926946

927947
static final _emojiClassNameRegexp = () {
928948
const specificEmoji = r"emoji(?:-[0-9a-f]+)+";

test/model/content_test.dart

+49-1
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,48 @@ class ContentExample {
139139
'<p><span class="silent user-group-mention" data-user-group-id="186">test-empty</span></p>',
140140
const UserMentionNode(nodes: [TextNode('test-empty')]));
141141

142+
static final channelWildcardMentionPlain = ContentExample.inline(
143+
'plain channel wildcard @-mention',
144+
"@**all**",
145+
expectedText: '@all',
146+
'<p><span class="user-mention channel-wildcard-mention" data-user-id="*">@all</span></p>',
147+
const UserMentionNode(nodes: [TextNode('@all')]));
148+
149+
static final channelWildcardMentionSilent = ContentExample.inline(
150+
'silent channel wildcard @-mention',
151+
"@_**everyone**",
152+
expectedText: 'everyone',
153+
'<p><span class="user-mention channel-wildcard-mention silent" data-user-id="*">everyone</span></p>',
154+
const UserMentionNode(nodes: [TextNode('everyone')]));
155+
156+
static final channelWildcardMentionSilentClassOrderReversed = ContentExample.inline(
157+
'silent channel wildcard @-mention, class order reversed',
158+
"@_**channel**", // (hypothetical server variation)
159+
expectedText: 'channel',
160+
'<p><span class="silent user-mention channel-wildcard-mention" data-user-id="*">channel</span></p>',
161+
const UserMentionNode(nodes: [TextNode('channel')]));
162+
163+
static final legacyChannelWildcardMentionPlain = ContentExample.inline(
164+
'legacy plain channel wildcard @-mention',
165+
"@**channel**",
166+
expectedText: '@channel',
167+
'<p><span class="user-mention" data-user-id="*">@channel</span></p>',
168+
const UserMentionNode(nodes: [TextNode('@channel')]));
169+
170+
static final legacyChannelWildcardMentionSilent = ContentExample.inline(
171+
'legacy silent channel wildcard @-mention',
172+
"@_**stream**",
173+
expectedText: 'stream',
174+
'<p><span class="user-mention silent" data-user-id="*">stream</span></p>',
175+
const UserMentionNode(nodes: [TextNode('stream')]));
176+
177+
static final legacyChannelWildcardMentionSilentClassOrderReversed = ContentExample.inline(
178+
'legacy silent channel wildcard @-mention, class order reversed',
179+
"@_**all**", // (hypothetical server variation)
180+
expectedText: 'all',
181+
'<p><span class="silent user-mention" data-user-id="*">all</span></p>',
182+
const UserMentionNode(nodes: [TextNode('all')]));
183+
142184
static final emojiUnicode = ContentExample.inline(
143185
'Unicode emoji, encoded in span element',
144186
":thumbs_up:",
@@ -1213,7 +1255,13 @@ void main() {
12131255
testParseExample(ContentExample.groupMentionSilent);
12141256
testParseExample(ContentExample.groupMentionSilentClassOrderReversed);
12151257

1216-
// TODO test wildcard mentions
1258+
testParseExample(ContentExample.channelWildcardMentionPlain);
1259+
testParseExample(ContentExample.channelWildcardMentionSilent);
1260+
testParseExample(ContentExample.channelWildcardMentionSilentClassOrderReversed);
1261+
1262+
testParseExample(ContentExample.legacyChannelWildcardMentionPlain);
1263+
testParseExample(ContentExample.legacyChannelWildcardMentionSilent);
1264+
testParseExample(ContentExample.legacyChannelWildcardMentionSilentClassOrderReversed);
12171265
});
12181266

12191267
testParseExample(ContentExample.emojiUnicode);

test/widgets/content_test.dart

+6
Original file line numberDiff line numberDiff line change
@@ -650,6 +650,12 @@ void main() {
650650
testContentSmoke(ContentExample.userMentionSilent);
651651
testContentSmoke(ContentExample.groupMentionPlain);
652652
testContentSmoke(ContentExample.groupMentionSilent);
653+
testContentSmoke(ContentExample.channelWildcardMentionPlain);
654+
testContentSmoke(ContentExample.channelWildcardMentionSilent);
655+
testContentSmoke(ContentExample.channelWildcardMentionSilentClassOrderReversed);
656+
testContentSmoke(ContentExample.legacyChannelWildcardMentionPlain);
657+
testContentSmoke(ContentExample.legacyChannelWildcardMentionSilent);
658+
testContentSmoke(ContentExample.legacyChannelWildcardMentionSilentClassOrderReversed);
653659

654660
UserMention? findUserMentionInSpan(InlineSpan rootSpan) {
655661
UserMention? result;

0 commit comments

Comments
 (0)