Merge pull request #2141 from famedly/krille/implement-mentions
Krille/implement mentions
This commit is contained in:
commit
a782e196d5
|
|
@ -1180,6 +1180,17 @@ class Event extends MatrixEvent {
|
||||||
(fileSendingStatus) => fileSendingStatus.name == status,
|
(fileSendingStatus) => fileSendingStatus.name == status,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the mentioned userIds and wether the event includes an @room
|
||||||
|
/// mention. This is only determined by the `m.mention` object in the event
|
||||||
|
/// content.
|
||||||
|
({List<String> userIds, bool room}) get mentions {
|
||||||
|
final mentionsMap = content.tryGetMap<String, Object?>('m.mentions');
|
||||||
|
return (
|
||||||
|
userIds: mentionsMap?.tryGetList<String>('user_ids') ?? [],
|
||||||
|
room: mentionsMap?.tryGet<bool>('room') ?? false,
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
enum FileSendingStatus {
|
enum FileSendingStatus {
|
||||||
|
|
|
||||||
|
|
@ -710,6 +710,7 @@ class Room {
|
||||||
String? threadRootEventId,
|
String? threadRootEventId,
|
||||||
String? threadLastEventId,
|
String? threadLastEventId,
|
||||||
StringBuffer? commandStdout,
|
StringBuffer? commandStdout,
|
||||||
|
bool addMentions = true,
|
||||||
}) {
|
}) {
|
||||||
if (parseCommands) {
|
if (parseCommands) {
|
||||||
return client.parseAndRunCommand(
|
return client.parseAndRunCommand(
|
||||||
|
|
@ -727,6 +728,41 @@ class Room {
|
||||||
'msgtype': msgtype,
|
'msgtype': msgtype,
|
||||||
'body': message,
|
'body': message,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (addMentions) {
|
||||||
|
var potentialMentions = message
|
||||||
|
.split('@')
|
||||||
|
.map(
|
||||||
|
(text) => text.startsWith('[')
|
||||||
|
? '@${text.split(']').first}]'
|
||||||
|
: '@${text.split(RegExp(r'\s+')).first}',
|
||||||
|
)
|
||||||
|
.toList()
|
||||||
|
..removeAt(0);
|
||||||
|
|
||||||
|
final hasRoomMention = potentialMentions.remove('@room');
|
||||||
|
|
||||||
|
potentialMentions = potentialMentions
|
||||||
|
.map(
|
||||||
|
(mention) =>
|
||||||
|
mention.isValidMatrixId ? mention : getMention(mention),
|
||||||
|
)
|
||||||
|
.nonNulls
|
||||||
|
.toSet() // Deduplicate
|
||||||
|
.toList()
|
||||||
|
..remove(client.userID); // We should never mention ourself.
|
||||||
|
|
||||||
|
// https://spec.matrix.org/v1.7/client-server-api/#mentioning-the-replied-to-user
|
||||||
|
if (inReplyTo != null) potentialMentions.add(inReplyTo.senderId);
|
||||||
|
|
||||||
|
if (hasRoomMention || potentialMentions.isNotEmpty) {
|
||||||
|
event['m.mentions'] = {
|
||||||
|
if (hasRoomMention) 'room': true,
|
||||||
|
if (potentialMentions.isNotEmpty) 'user_ids': potentialMentions,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (parseMarkdown) {
|
if (parseMarkdown) {
|
||||||
final html = markdown(
|
final html = markdown(
|
||||||
event['body'],
|
event['body'],
|
||||||
|
|
|
||||||
|
|
@ -243,6 +243,9 @@ void main() {
|
||||||
expect(sent, {
|
expect(sent, {
|
||||||
'msgtype': 'm.text',
|
'msgtype': 'm.text',
|
||||||
'body': '> <@test:fakeServer.notExisting> reply\n\nreply',
|
'body': '> <@test:fakeServer.notExisting> reply\n\nreply',
|
||||||
|
'm.mentions': {
|
||||||
|
'user_ids': ['@test:fakeServer.notExisting'],
|
||||||
|
},
|
||||||
'format': 'org.matrix.custom.html',
|
'format': 'org.matrix.custom.html',
|
||||||
'formatted_body':
|
'formatted_body':
|
||||||
'<mx-reply><blockquote><a href="https://matrix.to/#/!1234:fakeServer.notExisting/\$parent_event">In reply to</a> <a href="https://matrix.to/#/@test:fakeServer.notExisting">@test:fakeServer.notExisting</a><br>reply</blockquote></mx-reply>reply',
|
'<mx-reply><blockquote><a href="https://matrix.to/#/!1234:fakeServer.notExisting/\$parent_event">In reply to</a> <a href="https://matrix.to/#/@test:fakeServer.notExisting">@test:fakeServer.notExisting</a><br>reply</blockquote></mx-reply>reply',
|
||||||
|
|
|
||||||
|
|
@ -2951,5 +2951,28 @@ void main() async {
|
||||||
Timeline(room: room, chunk: TimelineChunk(events: [targetEvent]));
|
Timeline(room: room, chunk: TimelineChunk(events: [targetEvent]));
|
||||||
expect(await event.getReplyEvent(timeline), targetEvent);
|
expect(await event.getReplyEvent(timeline), targetEvent);
|
||||||
});
|
});
|
||||||
|
test('getMentions', () {
|
||||||
|
final event = Event.fromJson(
|
||||||
|
{
|
||||||
|
'content': {
|
||||||
|
'msgtype': 'text',
|
||||||
|
'body': 'Hello world @alice:matrix.org',
|
||||||
|
'm.mentions': {
|
||||||
|
'user_ids': ['@alice:matrix.org'],
|
||||||
|
'room': false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'event_id': '\$143273582443PhrSn:example.org',
|
||||||
|
'origin_server_ts': 1432735824653,
|
||||||
|
'room_id': room.id,
|
||||||
|
'sender': '@example:example.org',
|
||||||
|
'type': 'm.room.message',
|
||||||
|
'unsigned': {'age': 1234},
|
||||||
|
},
|
||||||
|
room,
|
||||||
|
);
|
||||||
|
expect(event.mentions.userIds, ['@alice:matrix.org']);
|
||||||
|
expect(event.mentions.room, false);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1038,6 +1038,36 @@ void main() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('sendEvent with room mention', () async {
|
||||||
|
FakeMatrixApi.calledEndpoints.clear();
|
||||||
|
final resp = await room.sendTextEvent(
|
||||||
|
'Hello world @room',
|
||||||
|
txid: 'testtxid',
|
||||||
|
addMentions: true,
|
||||||
|
);
|
||||||
|
expect(resp?.startsWith('\$event'), true);
|
||||||
|
final entry = FakeMatrixApi.calledEndpoints.entries
|
||||||
|
.firstWhere((p) => p.key.contains('/send/m.room.message/'));
|
||||||
|
final content = json.decode(entry.value.first);
|
||||||
|
expect(content['m.mentions'], {'room': true});
|
||||||
|
});
|
||||||
|
|
||||||
|
test('sendEvent with user mention', () async {
|
||||||
|
FakeMatrixApi.calledEndpoints.clear();
|
||||||
|
final resp = await room.sendTextEvent(
|
||||||
|
'Hello world @[Alice Margatroid]',
|
||||||
|
addMentions: true,
|
||||||
|
txid: 'testtxid',
|
||||||
|
);
|
||||||
|
expect(resp?.startsWith('\$event'), true);
|
||||||
|
final entry = FakeMatrixApi.calledEndpoints.entries
|
||||||
|
.firstWhere((p) => p.key.contains('/send/m.room.message/'));
|
||||||
|
final content = json.decode(entry.value.first);
|
||||||
|
expect(content['m.mentions'], {
|
||||||
|
'user_ids': ['@alice:matrix.org'],
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
test('send edit', () async {
|
test('send edit', () async {
|
||||||
FakeMatrixApi.calledEndpoints.clear();
|
FakeMatrixApi.calledEndpoints.clear();
|
||||||
final dynamic resp = await room.sendTextEvent(
|
final dynamic resp = await room.sendTextEvent(
|
||||||
|
|
@ -1089,6 +1119,9 @@ void main() {
|
||||||
expect(content, {
|
expect(content, {
|
||||||
'body': '> <@alice:example.org> Blah\n\nHello world',
|
'body': '> <@alice:example.org> Blah\n\nHello world',
|
||||||
'msgtype': 'm.text',
|
'msgtype': 'm.text',
|
||||||
|
'm.mentions': {
|
||||||
|
'user_ids': ['@alice:example.org'],
|
||||||
|
},
|
||||||
'format': 'org.matrix.custom.html',
|
'format': 'org.matrix.custom.html',
|
||||||
'formatted_body':
|
'formatted_body':
|
||||||
'<mx-reply><blockquote><a href="https://matrix.to/#/!localpart:server.abc/\$replyEvent">In reply to</a> <a href="https://matrix.to/#/@alice:example.org">@alice:example.org</a><br>Blah</blockquote></mx-reply>Hello world',
|
'<mx-reply><blockquote><a href="https://matrix.to/#/!localpart:server.abc/\$replyEvent">In reply to</a> <a href="https://matrix.to/#/@alice:example.org">@alice:example.org</a><br>Blah</blockquote></mx-reply>Hello world',
|
||||||
|
|
@ -1125,6 +1158,9 @@ void main() {
|
||||||
'body':
|
'body':
|
||||||
'> <@alice:example.org> <b>Blah</b>\n> beep\n\nHello world\nfox',
|
'> <@alice:example.org> <b>Blah</b>\n> beep\n\nHello world\nfox',
|
||||||
'msgtype': 'm.text',
|
'msgtype': 'm.text',
|
||||||
|
'm.mentions': {
|
||||||
|
'user_ids': ['@alice:example.org'],
|
||||||
|
},
|
||||||
'format': 'org.matrix.custom.html',
|
'format': 'org.matrix.custom.html',
|
||||||
'formatted_body':
|
'formatted_body':
|
||||||
'<mx-reply><blockquote><a href="https://matrix.to/#/!localpart:server.abc/\$replyEvent">In reply to</a> <a href="https://matrix.to/#/@alice:example.org">@alice:example.org</a><br><b>Blah</b><br>beep</blockquote></mx-reply>Hello world<br/>fox',
|
'<mx-reply><blockquote><a href="https://matrix.to/#/!localpart:server.abc/\$replyEvent">In reply to</a> <a href="https://matrix.to/#/@alice:example.org">@alice:example.org</a><br><b>Blah</b><br>beep</blockquote></mx-reply>Hello world<br/>fox',
|
||||||
|
|
@ -1162,6 +1198,9 @@ void main() {
|
||||||
expect(content, {
|
expect(content, {
|
||||||
'body': '> <@alice:example.org> plaintext meow\n\nHello world',
|
'body': '> <@alice:example.org> plaintext meow\n\nHello world',
|
||||||
'msgtype': 'm.text',
|
'msgtype': 'm.text',
|
||||||
|
'm.mentions': {
|
||||||
|
'user_ids': ['@alice:example.org'],
|
||||||
|
},
|
||||||
'format': 'org.matrix.custom.html',
|
'format': 'org.matrix.custom.html',
|
||||||
'formatted_body':
|
'formatted_body':
|
||||||
'<mx-reply><blockquote><a href="https://matrix.to/#/!localpart:server.abc/\$replyEvent">In reply to</a> <a href="https://matrix.to/#/@alice:example.org">@alice:example.org</a><br>meow</blockquote></mx-reply>Hello world',
|
'<mx-reply><blockquote><a href="https://matrix.to/#/!localpart:server.abc/\$replyEvent">In reply to</a> <a href="https://matrix.to/#/@alice:example.org">@alice:example.org</a><br>meow</blockquote></mx-reply>Hello world',
|
||||||
|
|
@ -1197,6 +1236,9 @@ void main() {
|
||||||
expect(content, {
|
expect(content, {
|
||||||
'body': '> <@alice:example.org> Hey @\u{200b}room\n\nHello world',
|
'body': '> <@alice:example.org> Hey @\u{200b}room\n\nHello world',
|
||||||
'msgtype': 'm.text',
|
'msgtype': 'm.text',
|
||||||
|
'm.mentions': {
|
||||||
|
'user_ids': ['@alice:example.org'],
|
||||||
|
},
|
||||||
'format': 'org.matrix.custom.html',
|
'format': 'org.matrix.custom.html',
|
||||||
'formatted_body':
|
'formatted_body':
|
||||||
'<mx-reply><blockquote><a href="https://matrix.to/#/!localpart:server.abc/\$replyEvent">In reply to</a> <a href="https://matrix.to/#/@alice:example.org">@alice:example.org</a><br>Hey @room</blockquote></mx-reply>Hello world',
|
'<mx-reply><blockquote><a href="https://matrix.to/#/!localpart:server.abc/\$replyEvent">In reply to</a> <a href="https://matrix.to/#/@alice:example.org">@alice:example.org</a><br>Hey @room</blockquote></mx-reply>Hello world',
|
||||||
|
|
@ -1214,6 +1256,9 @@ void main() {
|
||||||
'content': {
|
'content': {
|
||||||
'body': '> <@alice:example.org> Hey\n\nHello world',
|
'body': '> <@alice:example.org> Hey\n\nHello world',
|
||||||
'msgtype': 'm.text',
|
'msgtype': 'm.text',
|
||||||
|
'm.mentions': {
|
||||||
|
'user_ids': ['@alice:example.org'],
|
||||||
|
},
|
||||||
'format': 'org.matrix.custom.html',
|
'format': 'org.matrix.custom.html',
|
||||||
'formatted_body':
|
'formatted_body':
|
||||||
'<mx-reply><blockquote><a href="https://matrix.to/#/!localpart:server.abc/\$replyEvent">In reply to</a> <a href="https://matrix.to/#/@alice:example.org">@alice:example.org</a><br>Hey</blockquote></mx-reply>Hello world',
|
'<mx-reply><blockquote><a href="https://matrix.to/#/!localpart:server.abc/\$replyEvent">In reply to</a> <a href="https://matrix.to/#/@alice:example.org">@alice:example.org</a><br>Hey</blockquote></mx-reply>Hello world',
|
||||||
|
|
@ -1238,6 +1283,9 @@ void main() {
|
||||||
expect(content, {
|
expect(content, {
|
||||||
'body': '> <@alice:example.org> Hello world\n\nFox',
|
'body': '> <@alice:example.org> Hello world\n\nFox',
|
||||||
'msgtype': 'm.text',
|
'msgtype': 'm.text',
|
||||||
|
'm.mentions': {
|
||||||
|
'user_ids': ['@alice:example.org'],
|
||||||
|
},
|
||||||
'format': 'org.matrix.custom.html',
|
'format': 'org.matrix.custom.html',
|
||||||
'formatted_body':
|
'formatted_body':
|
||||||
'<mx-reply><blockquote><a href="https://matrix.to/#/!localpart:server.abc/\$replyEvent">In reply to</a> <a href="https://matrix.to/#/@alice:example.org">@alice:example.org</a><br>Hello world</blockquote></mx-reply>Fox',
|
'<mx-reply><blockquote><a href="https://matrix.to/#/!localpart:server.abc/\$replyEvent">In reply to</a> <a href="https://matrix.to/#/@alice:example.org">@alice:example.org</a><br>Hello world</blockquote></mx-reply>Fox',
|
||||||
|
|
@ -1296,7 +1344,7 @@ void main() {
|
||||||
test('sendFileEvent', () async {
|
test('sendFileEvent', () async {
|
||||||
final testFile = MatrixFile(bytes: Uint8List(0), name: 'file.jpeg');
|
final testFile = MatrixFile(bytes: Uint8List(0), name: 'file.jpeg');
|
||||||
final resp = await room.sendFileEvent(testFile, txid: 'testtxid');
|
final resp = await room.sendFileEvent(testFile, txid: 'testtxid');
|
||||||
expect(resp.toString(), '\$event10');
|
expect(resp.toString(), '\$event12');
|
||||||
});
|
});
|
||||||
|
|
||||||
test('pushRuleState', () async {
|
test('pushRuleState', () async {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue