diff --git a/lib/src/room.dart b/lib/src/room.dart
index ce1403d2..830aaca7 100644
--- a/lib/src/room.dart
+++ b/lib/src/room.dart
@@ -17,6 +17,7 @@
*/
import 'dart:async';
+import 'dart:convert';
import 'package:html_unescape/html_unescape.dart';
import 'package:matrix_file_e2ee/matrix_file_e2ee.dart';
@@ -583,7 +584,8 @@ class Room {
if (parseMarkdown) {
final html = markdown(event['body'], emotePacks ?? this.emotePacks);
// if the decoded html is the same as the body, there is no need in sending a formatted message
- if (HtmlUnescape().convert(html) != event['body']) {
+ if (HtmlUnescape().convert(html.replaceAll(RegExp(r'
\n?'), '\n')) !=
+ event['body']) {
event['format'] = 'org.matrix.custom.html';
event['formatted_body'] = html;
}
@@ -754,9 +756,22 @@ class Room {
}
replyText = replyTextLines.join('\n');
content['format'] = 'org.matrix.custom.html';
+ // be sure that we strip any previous reply fallbacks
+ final replyHtml = (inReplyTo.formattedText.isNotEmpty
+ ? inReplyTo.formattedText
+ : htmlEscape.convert(inReplyTo.body).replaceAll('\n', '
'))
+ .replaceAll(
+ RegExp(r'.*<\/mx-reply>',
+ caseSensitive: false, multiLine: false, dotAll: true),
+ '');
+ final repliedHtml = content.tryGet(
+ 'formatted_body',
+ htmlEscape
+ .convert(content.tryGet('body', ''))
+ .replaceAll('\n', '
'));
content['formatted_body'] =
- 'In reply to ${inReplyTo.senderId}
${inReplyTo.body}
${content["formatted_body"] ?? content["body"]}';
- content['body'] = replyText + "\n\n${content["body"] ?? ""}";
+ 'In reply to ${inReplyTo.senderId}
$replyHtml
$repliedHtml';
+ content['body'] = replyText + "\n\n${content.tryGet('body', '')}";
content['m.relates_to'] = {
'm.in_reply_to': {
'event_id': inReplyTo.eventId,
diff --git a/test/room_test.dart b/test/room_test.dart
index 191128f3..23c30dcf 100644
--- a/test/room_test.dart
+++ b/test/room_test.dart
@@ -420,12 +420,12 @@ void main() {
'sender': '@alice:example.org',
}, room);
FakeMatrixApi.calledEndpoints.clear();
- final dynamic resp = await room.sendTextEvent('Hello world',
+ var resp = await room.sendTextEvent('Hello world',
txid: 'testtxid', inReplyTo: event);
expect(resp.startsWith('\$event'), true);
- final entry = FakeMatrixApi.calledEndpoints.entries
+ var entry = FakeMatrixApi.calledEndpoints.entries
.firstWhere((p) => p.key.contains('/send/m.room.message/'));
- final content = json.decode(entry.value.first);
+ var content = json.decode(entry.value.first);
expect(content, {
'body': '> <@alice:example.org> Blah\n\nHello world',
'msgtype': 'm.text',
@@ -438,6 +438,67 @@ void main() {
},
},
});
+
+ event = Event.fromJson({
+ 'event_id': '\$replyEvent',
+ 'content': {
+ 'body': 'Blah\nbeep',
+ 'msgtype': 'm.text',
+ },
+ 'type': 'm.room.message',
+ 'sender': '@alice:example.org',
+ }, room);
+ FakeMatrixApi.calledEndpoints.clear();
+ resp = await room.sendTextEvent('Hello world\nfox',
+ txid: 'testtxid', inReplyTo: event);
+ expect(resp.startsWith('\$event'), true);
+ entry = FakeMatrixApi.calledEndpoints.entries
+ .firstWhere((p) => p.key.contains('/send/m.room.message/'));
+ content = json.decode(entry.value.first);
+ expect(content, {
+ 'body':
+ '> <@alice:example.org> Blah\n> beep\n\nHello world\nfox',
+ 'msgtype': 'm.text',
+ 'format': 'org.matrix.custom.html',
+ 'formatted_body':
+ 'In reply to @alice:example.org
<b>Blah</b>
beep
Hello world
fox',
+ 'm.relates_to': {
+ 'm.in_reply_to': {
+ 'event_id': '\$replyEvent',
+ },
+ },
+ });
+
+ event = Event.fromJson({
+ 'event_id': '\$replyEvent',
+ 'content': {
+ 'format': 'org.matrix.custom.html',
+ 'formatted_body': 'heyameow',
+ 'body': 'plaintext meow',
+ 'msgtype': 'm.text',
+ },
+ 'type': 'm.room.message',
+ 'sender': '@alice:example.org',
+ }, room);
+ FakeMatrixApi.calledEndpoints.clear();
+ resp = await room.sendTextEvent('Hello world',
+ txid: 'testtxid', inReplyTo: event);
+ expect(resp.startsWith('\$event'), true);
+ entry = FakeMatrixApi.calledEndpoints.entries
+ .firstWhere((p) => p.key.contains('/send/m.room.message/'));
+ content = json.decode(entry.value.first);
+ expect(content, {
+ 'body': '> <@alice:example.org> plaintext meow\n\nHello world',
+ 'msgtype': 'm.text',
+ 'format': 'org.matrix.custom.html',
+ 'formatted_body':
+ 'In reply to @alice:example.org
meow
Hello world',
+ 'm.relates_to': {
+ 'm.in_reply_to': {
+ 'event_id': '\$replyEvent',
+ },
+ },
+ });
});
test('send reaction', () async {