Skip to content

Commit 0a5c4a6

Browse files
committed
content: Add UserGroupMentionNode and update parseMention
1 parent 03b5c04 commit 0a5c4a6

File tree

2 files changed

+53
-17
lines changed

2 files changed

+53
-17
lines changed

lib/model/content.dart

Lines changed: 50 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1097,7 +1097,7 @@ class UserMentionNode extends MentionNode {
10971097

10981098
/// The ID of the user being mentioned.
10991099
///
1100-
/// This is null for wildcard mentions, user group mentions,
1100+
/// This is null for wildcard mentions
11011101
/// or when the user ID is unavailable in the HTML (e.g., legacy mentions).
11021102
final int? userId;
11031103

@@ -1108,6 +1108,27 @@ class UserMentionNode extends MentionNode {
11081108
}
11091109
}
11101110

1111+
class UserGroupMentionNode extends MentionNode {
1112+
const UserGroupMentionNode({
1113+
super.debugHtmlNode,
1114+
required super.nodes,
1115+
required super.isSilent,
1116+
required this.userGroupId,
1117+
});
1118+
1119+
/// The ID of the user group being mentioned.
1120+
///
1121+
/// This is non-nullable because user group mentions
1122+
/// always have data-user-group-id.
1123+
final int userGroupId;
1124+
1125+
@override
1126+
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
1127+
super.debugFillProperties(properties);
1128+
properties.add(IntProperty('userGroupId', userGroupId));
1129+
}
1130+
}
1131+
11111132
// TODO(#646) add WildcardMentionNode
11121133

11131134
sealed class EmojiNode extends InlineContentNode {
@@ -1325,15 +1346,16 @@ class _ZulipInlineContentParser {
13251346
i++;
13261347
}
13271348

1349+
String? mentionType;
13281350
if (i >= classes.length) return null;
13291351
if ((classes[i] == 'topic-mention' && !hasChannelWildcardClass)
13301352
|| classes[i] == 'user-mention'
13311353
|| (classes[i] == 'user-group-mention' && !hasChannelWildcardClass)) {
13321354
// The class we already knew we'd find before we called this function.
1333-
// We ignore the distinction between these; see [UserMentionNode].
1334-
// Also, we don't expect "user-group-mention" and "channel-wildcard-mention"
1355+
// We don't expect "user-group-mention" and "channel-wildcard-mention"
13351356
// to be in the list at the same time and neither we expect "topic-mention"
13361357
// and "channel-wildcard-mention" to be in the list at the same time.
1358+
mentionType = classes[i];
13371359
i++;
13381360
}
13391361

@@ -1342,21 +1364,35 @@ class _ZulipInlineContentParser {
13421364
return null;
13431365
}
13441366

1345-
final userId = switch (element.attributes['data-user-id']) {
1346-
// For legacy, user group or wildcard mentions.
1347-
null || '*' => null,
1348-
final userIdString => int.tryParse(userIdString, radix: 10),
1349-
};
1350-
13511367
// TODO assert MentionNode can't contain LinkNode;
13521368
// either a debug-mode check, or perhaps we can make expectations much
13531369
// tighter on a MentionNode's contents overall.
13541370
final nodes = parseInlineContentList(element.nodes);
1355-
return UserMentionNode(
1356-
nodes: nodes,
1357-
userId: userId,
1358-
isSilent: isSilent,
1359-
debugHtmlNode: debugHtmlNode);
1371+
1372+
if (mentionType case 'user-group-mention') {
1373+
final userGroupId = int.tryParse(
1374+
element.attributes['data-user-group-id'] ?? '',
1375+
radix: 10);
1376+
if (userGroupId == null) {
1377+
return null;
1378+
}
1379+
return UserGroupMentionNode(
1380+
nodes: nodes,
1381+
isSilent: isSilent,
1382+
userGroupId: userGroupId,
1383+
debugHtmlNode: debugHtmlNode);
1384+
} else {
1385+
final userId = switch (element.attributes['data-user-id']) {
1386+
// For legacy or wildcard mentions.
1387+
null || '*' => null,
1388+
final userIdString => int.tryParse(userIdString, radix: 10),
1389+
};
1390+
return UserMentionNode(
1391+
nodes: nodes,
1392+
isSilent: isSilent,
1393+
userId: userId,
1394+
debugHtmlNode: debugHtmlNode);
1395+
}
13601396
}
13611397

13621398
/// The links found so far in the current block inline container.

test/model/content_test.dart

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -132,21 +132,21 @@ class ContentExample {
132132
"@*test-empty*",
133133
expectedText: '@test-empty',
134134
'<p><span class="user-group-mention" data-user-group-id="186">@test-empty</span></p>',
135-
const UserMentionNode(nodes: [TextNode('@test-empty')], isSilent: false, userId: null));
135+
const UserGroupMentionNode(nodes: [TextNode('@test-empty')], isSilent: false, userGroupId: 186));
136136

137137
static final groupMentionSilent = ContentExample.inline(
138138
'silent group @-mention',
139139
"@_*test-empty*",
140140
expectedText: 'test-empty',
141141
'<p><span class="user-group-mention silent" data-user-group-id="186">test-empty</span></p>',
142-
const UserMentionNode(nodes: [TextNode('test-empty')], isSilent: true, userId: null));
142+
const UserGroupMentionNode(nodes: [TextNode('test-empty')], isSilent: true, userGroupId: 186));
143143

144144
static final groupMentionSilentClassOrderReversed = ContentExample.inline(
145145
'silent group @-mention, class order reversed',
146146
"@_*test-empty*", // (hypothetical server variation)
147147
expectedText: 'test-empty',
148148
'<p><span class="silent user-group-mention" data-user-group-id="186">test-empty</span></p>',
149-
const UserMentionNode(nodes: [TextNode('test-empty')], isSilent: true, userId: null));
149+
const UserGroupMentionNode(nodes: [TextNode('test-empty')], isSilent: true, userGroupId: 186));
150150

151151
static final channelWildcardMentionPlain = ContentExample.inline(
152152
'plain channel wildcard @-mention',

0 commit comments

Comments
 (0)