Merge branch 'event-feature-add-replies' into 'master'
[Event] Add support for replies See merge request famedly/famedlysdk!184
This commit is contained in:
commit
fb9d8613ee
|
@ -23,6 +23,7 @@
|
||||||
|
|
||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
import 'package:famedlysdk/famedlysdk.dart';
|
import 'package:famedlysdk/famedlysdk.dart';
|
||||||
|
import 'package:famedlysdk/src/utils/matrix_id_string_extension.dart';
|
||||||
import 'package:famedlysdk/src/utils/receipt.dart';
|
import 'package:famedlysdk/src/utils/receipt.dart';
|
||||||
import './room.dart';
|
import './room.dart';
|
||||||
|
|
||||||
|
@ -366,6 +367,23 @@ class Event {
|
||||||
/// Redacts this event. Returns [ErrorResponse] on error.
|
/// Redacts this event. Returns [ErrorResponse] on error.
|
||||||
Future<dynamic> redact({String reason, String txid}) =>
|
Future<dynamic> redact({String reason, String txid}) =>
|
||||||
room.redactEvent(eventId, reason: reason, txid: txid);
|
room.redactEvent(eventId, reason: reason, txid: txid);
|
||||||
|
|
||||||
|
/// Whether this event is in reply to another event.
|
||||||
|
bool get isReply =>
|
||||||
|
content['m.relates_to'] is Map<String, dynamic> &&
|
||||||
|
content['m.relates_to']['m.in_reply_to'] is Map<String, dynamic> &&
|
||||||
|
content['m.relates_to']['m.in_reply_to']['event_id'] is String &&
|
||||||
|
(content['m.relates_to']['m.in_reply_to']['event_id'] as String)
|
||||||
|
.isValidMatrixId &&
|
||||||
|
(content['m.relates_to']['m.in_reply_to']['event_id'] as String).sigil ==
|
||||||
|
"\$";
|
||||||
|
|
||||||
|
/// Searches for the reply event in the given timeline.
|
||||||
|
Future<Event> getReplyEvent(Timeline timeline) async {
|
||||||
|
if (!isReply) return null;
|
||||||
|
final String replyEventId = content['m.relates_to']['m.in_reply_to'];
|
||||||
|
return await timeline.getEventById(replyEventId);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
enum MessageTypes {
|
enum MessageTypes {
|
||||||
|
|
|
@ -290,13 +290,15 @@ class Room {
|
||||||
return res["event_id"];
|
return res["event_id"];
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<String> sendTextEvent(String message, {String txid}) =>
|
Future<String> sendTextEvent(String message,
|
||||||
sendEvent({"msgtype": "m.text", "body": message}, txid: txid);
|
{String txid, Event inReplyTo}) =>
|
||||||
|
sendEvent({"msgtype": "m.text", "body": message},
|
||||||
|
txid: txid, inReplyTo: inReplyTo);
|
||||||
|
|
||||||
/// Sends a [file] to this room after uploading it. The [msgType] is optional
|
/// Sends a [file] to this room after uploading it. The [msgType] is optional
|
||||||
/// and will be detected by the mimetype of the file.
|
/// and will be detected by the mimetype of the file.
|
||||||
Future<String> sendFileEvent(MatrixFile file,
|
Future<String> sendFileEvent(MatrixFile file,
|
||||||
{String msgType = "m.file", String txid}) async {
|
{String msgType = "m.file", String txid, Event inReplyTo}) async {
|
||||||
if (msgType == "m.image") return sendImageEvent(file);
|
if (msgType == "m.image") return sendImageEvent(file);
|
||||||
if (msgType == "m.audio") return sendVideoEvent(file);
|
if (msgType == "m.audio") return sendVideoEvent(file);
|
||||||
if (msgType == "m.video") return sendAudioEvent(file);
|
if (msgType == "m.video") return sendAudioEvent(file);
|
||||||
|
@ -315,11 +317,11 @@ class Room {
|
||||||
"size": file.size,
|
"size": file.size,
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
return await sendEvent(content, txid: txid);
|
return await sendEvent(content, txid: txid, inReplyTo: inReplyTo);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<String> sendAudioEvent(MatrixFile file,
|
Future<String> sendAudioEvent(MatrixFile file,
|
||||||
{String txid, int width, int height}) async {
|
{String txid, int width, int height, Event inReplyTo}) async {
|
||||||
String fileName = file.path.split("/").last;
|
String fileName = file.path.split("/").last;
|
||||||
final String uploadResp = await client.upload(file);
|
final String uploadResp = await client.upload(file);
|
||||||
Map<String, dynamic> content = {
|
Map<String, dynamic> content = {
|
||||||
|
@ -332,11 +334,11 @@ class Room {
|
||||||
"size": file.size,
|
"size": file.size,
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
return await sendEvent(content, txid: txid);
|
return await sendEvent(content, txid: txid, inReplyTo: inReplyTo);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<String> sendImageEvent(MatrixFile file,
|
Future<String> sendImageEvent(MatrixFile file,
|
||||||
{String txid, int width, int height}) async {
|
{String txid, int width, int height, Event inReplyTo}) async {
|
||||||
String fileName = file.path.split("/").last;
|
String fileName = file.path.split("/").last;
|
||||||
final String uploadResp = await client.upload(file);
|
final String uploadResp = await client.upload(file);
|
||||||
Map<String, dynamic> content = {
|
Map<String, dynamic> content = {
|
||||||
|
@ -350,7 +352,7 @@ class Room {
|
||||||
"h": height,
|
"h": height,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
return await sendEvent(content, txid: txid);
|
return await sendEvent(content, txid: txid, inReplyTo: inReplyTo);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<String> sendVideoEvent(MatrixFile file,
|
Future<String> sendVideoEvent(MatrixFile file,
|
||||||
|
@ -360,7 +362,8 @@ class Room {
|
||||||
int duration,
|
int duration,
|
||||||
MatrixFile thumbnail,
|
MatrixFile thumbnail,
|
||||||
int thumbnailWidth,
|
int thumbnailWidth,
|
||||||
int thumbnailHeight}) async {
|
int thumbnailHeight,
|
||||||
|
Event inReplyTo}) async {
|
||||||
String fileName = file.path.split("/").last;
|
String fileName = file.path.split("/").last;
|
||||||
final String uploadResp = await client.upload(file);
|
final String uploadResp = await client.upload(file);
|
||||||
Map<String, dynamic> content = {
|
Map<String, dynamic> content = {
|
||||||
|
@ -396,10 +399,11 @@ class Room {
|
||||||
content["info"]["thumbnail_info"]["h"] = thumbnailHeight;
|
content["info"]["thumbnail_info"]["h"] = thumbnailHeight;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return await sendEvent(content, txid: txid);
|
return await sendEvent(content, txid: txid, inReplyTo: inReplyTo);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<String> sendEvent(Map<String, dynamic> content, {String txid}) async {
|
Future<String> sendEvent(Map<String, dynamic> content,
|
||||||
|
{String txid, Event inReplyTo}) async {
|
||||||
final String type = "m.room.message";
|
final String type = "m.room.message";
|
||||||
|
|
||||||
// Create new transaction id
|
// Create new transaction id
|
||||||
|
@ -411,6 +415,23 @@ class Room {
|
||||||
messageID = txid;
|
messageID = txid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (inReplyTo != null) {
|
||||||
|
String replyText = "<${inReplyTo.senderId}> " + inReplyTo.body;
|
||||||
|
List<String> replyTextLines = replyText.split("\n");
|
||||||
|
for (int i = 0; i < replyTextLines.length; i++) {
|
||||||
|
replyTextLines[i] = "> " + replyTextLines[i];
|
||||||
|
}
|
||||||
|
replyText = replyTextLines.join("\n");
|
||||||
|
content["format"] = "org.matrix.custom.html";
|
||||||
|
content["formatted_body"] = '<mx-reply><blockquote><a href="https://matrix.to/#/${inReplyTo.room.id}/${inReplyTo.eventId}">In reply to</a> <a href="https://matrix.to/#/${inReplyTo.senderId}">${inReplyTo.senderId}</a><br>${inReplyTo.body}</blockquote></mx-reply>${content["formatted_body"] ?? content["body"]}';
|
||||||
|
content["body"] = replyText + "\n\n${content["body"] ?? ""}";
|
||||||
|
content["m.relates_to"] = {
|
||||||
|
"m.in_reply_to": {
|
||||||
|
"event_id": inReplyTo.eventId,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
// Display a *sending* event and store it.
|
// Display a *sending* event and store it.
|
||||||
EventUpdate eventUpdate =
|
EventUpdate eventUpdate =
|
||||||
EventUpdate(type: "timeline", roomID: id, eventType: type, content: {
|
EventUpdate(type: "timeline", roomID: id, eventType: type, content: {
|
||||||
|
|
|
@ -41,7 +41,7 @@ void main() {
|
||||||
final String formatted_body = "<b>Hello</b> World";
|
final String formatted_body = "<b>Hello</b> World";
|
||||||
|
|
||||||
final String contentJson =
|
final String contentJson =
|
||||||
'{"msgtype":"$msgtype","body":"$body","formatted_body":"$formatted_body"}';
|
'{"msgtype":"$msgtype","body":"$body","formatted_body":"$formatted_body","m.relates_to":{"m.in_reply_to":{"event_id":"\$1234:example.com"}}}';
|
||||||
|
|
||||||
Map<String, dynamic> jsonObj = {
|
Map<String, dynamic> jsonObj = {
|
||||||
"event_id": id,
|
"event_id": id,
|
||||||
|
@ -67,6 +67,7 @@ void main() {
|
||||||
expect(event.formattedText, formatted_body);
|
expect(event.formattedText, formatted_body);
|
||||||
expect(event.body, body);
|
expect(event.body, body);
|
||||||
expect(event.type, EventTypes.Message);
|
expect(event.type, EventTypes.Message);
|
||||||
|
expect(event.isReply, true);
|
||||||
jsonObj["state_key"] = "";
|
jsonObj["state_key"] = "";
|
||||||
Event state = Event.fromJson(jsonObj, null);
|
Event state = Event.fromJson(jsonObj, null);
|
||||||
expect(state.eventId, id);
|
expect(state.eventId, id);
|
||||||
|
|
Loading…
Reference in a new issue