Merge branch 'lists-enhance-fix-send-status' into 'master'
Lists enhance fix send status See merge request famedly/famedlysdk!15
This commit is contained in:
commit
e652e79a98
|
@ -165,45 +165,65 @@ class Room {
|
|||
type: "PUT",
|
||||
action: "/client/r0/rooms/${id}/send/m.room.message/$txid",
|
||||
data: {"msgtype": "m.text", "body": message});
|
||||
if (res["errcode"] == "M_LIMIT_EXCEEDED")
|
||||
client.connection.onError.add(res["error"]);
|
||||
if (res is ErrorResponse) client.connection.onError.add(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
Future<String> sendTextEvent(String message) async {
|
||||
Future<String> sendTextEvent(String message, {String txid = null}) async {
|
||||
final String type = "m.room.message";
|
||||
String messageID;
|
||||
final int now = DateTime.now().millisecondsSinceEpoch;
|
||||
final String messageID = "msg$now";
|
||||
if (txid == null) {
|
||||
messageID = "msg$now";
|
||||
} else
|
||||
messageID = txid;
|
||||
|
||||
// Display a *sending* event and store it.
|
||||
EventUpdate eventUpdate =
|
||||
EventUpdate(type: "timeline", roomID: id, eventType: type, content: {
|
||||
"type": type,
|
||||
"id": messageID,
|
||||
"id": null,
|
||||
"sender": client.userID,
|
||||
"status": 0,
|
||||
"origin_server_ts": now,
|
||||
"content": {
|
||||
"msgtype": "m.text",
|
||||
"body": message,
|
||||
"txid": messageID,
|
||||
}
|
||||
});
|
||||
client.connection.onEvent.add(eventUpdate);
|
||||
await client.store.transaction(() {
|
||||
await client.store?.transaction(() {
|
||||
client.store.storeEventUpdate(eventUpdate);
|
||||
});
|
||||
|
||||
// Send the text and on success, store and display a *sent* event.
|
||||
final dynamic res = await sendText(message, txid: messageID);
|
||||
|
||||
if (res is ErrorResponse) {
|
||||
client.store.db
|
||||
.rawUpdate("UPDATE Events SET status=-1 WHERE id=?", [messageID]);
|
||||
// On error, set status to -1
|
||||
eventUpdate.content["status"] = -1;
|
||||
client.connection.onEvent.add(eventUpdate);
|
||||
client.store?.db
|
||||
?.rawUpdate("UPDATE Events SET status=-1 WHERE id=?", [messageID]);
|
||||
} else {
|
||||
final String newEventID = res["event_id"];
|
||||
final List<Map<String, dynamic>> event = await client.store.db
|
||||
.rawQuery("SELECT * FROM Events WHERE id=?", [newEventID]);
|
||||
if (event.length > 0) {
|
||||
client.store.db.rawDelete("DELETE FROM Events WHERE id=?", [messageID]);
|
||||
} else {
|
||||
client.store.db.rawUpdate("UPDATE Events SET id=?, status=1 WHERE id=?",
|
||||
[newEventID, messageID]);
|
||||
eventUpdate.content["status"] = 1;
|
||||
eventUpdate.content["id"] = newEventID;
|
||||
client.connection.onEvent.add(eventUpdate);
|
||||
|
||||
// Store the result in database
|
||||
if (client.store != null) {
|
||||
final List<Map<String, dynamic>> eventQuery = await client.store.db
|
||||
.rawQuery("SELECT * FROM Events WHERE id=?", [newEventID]);
|
||||
if (eventQuery.length > 0) {
|
||||
client.store.db
|
||||
.rawDelete("DELETE FROM Events WHERE id=?", [messageID]);
|
||||
} else {
|
||||
client.store.db.rawUpdate(
|
||||
"UPDATE Events SET id=?, status=1 WHERE id=?",
|
||||
[newEventID, messageID]);
|
||||
}
|
||||
}
|
||||
return newEventID;
|
||||
}
|
||||
|
@ -310,6 +330,7 @@ class Room {
|
|||
});
|
||||
}
|
||||
|
||||
/// Sets this room as a direct chat for this user.
|
||||
Future<dynamic> addToDirectChat(String userID) async {
|
||||
Map<String, List<String>> directChats =
|
||||
await client.store.getAccountDataDirectChats();
|
||||
|
@ -327,6 +348,7 @@ class Room {
|
|||
return resp;
|
||||
}
|
||||
|
||||
/// Sends *m.fully_read* and *m.read* for the given event ID.
|
||||
Future<dynamic> sendReadReceipt(String eventID) async {
|
||||
final dynamic resp = client.connection.jsonRequest(
|
||||
type: "POST",
|
||||
|
@ -399,6 +421,7 @@ class Room {
|
|||
return room;
|
||||
}
|
||||
|
||||
/// Creates a timeline from the store. Returns a [Timeline] object.
|
||||
Future<Timeline> getTimeline(
|
||||
{onTimelineUpdateCallback onUpdate,
|
||||
onTimelineInsertCallback onInsert}) async {
|
||||
|
|
|
@ -37,6 +37,8 @@ class Timeline {
|
|||
final onTimelineUpdateCallback onUpdate;
|
||||
final onTimelineInsertCallback onInsert;
|
||||
|
||||
Set<String> waitToReplace = {};
|
||||
|
||||
StreamSubscription<EventUpdate> sub;
|
||||
|
||||
Timeline({this.room, this.events, this.onUpdate, this.onInsert}) {
|
||||
|
@ -47,20 +49,40 @@ class Timeline {
|
|||
try {
|
||||
if (eventUpdate.roomID != room.id) return;
|
||||
if (eventUpdate.type == "timeline" || eventUpdate.type == "history") {
|
||||
if (!eventUpdate.content.containsKey("id"))
|
||||
eventUpdate.content["id"] = eventUpdate.content["event_id"];
|
||||
// Is this event already in the timeline?
|
||||
if (eventUpdate.content["status"] == 1 ||
|
||||
eventUpdate.content["status"] == -1 ||
|
||||
waitToReplace.contains(eventUpdate.content["id"])) {
|
||||
int i;
|
||||
for (i = 0; i < events.length; i++) {
|
||||
if (events[i].content.containsKey("txid") &&
|
||||
events[i].content["txid"] ==
|
||||
eventUpdate.content["content"]["txid"] ||
|
||||
events[i].id == eventUpdate.content["id"]) break;
|
||||
}
|
||||
if (i < events.length) {
|
||||
events[i] = Event.fromJson(eventUpdate.content, room);
|
||||
if (eventUpdate.content["content"]["txid"] is String)
|
||||
waitToReplace.add(eventUpdate.content["id"]);
|
||||
else
|
||||
waitToReplace.remove(eventUpdate.content["id"]);
|
||||
}
|
||||
} else {
|
||||
if (!eventUpdate.content.containsKey("id"))
|
||||
eventUpdate.content["id"] = eventUpdate.content["event_id"];
|
||||
|
||||
User user = await room.client.store
|
||||
?.getUser(matrixID: eventUpdate.content["sender"], room: room);
|
||||
if (user != null) {
|
||||
eventUpdate.content["displayname"] = user.displayName;
|
||||
eventUpdate.content["avatar_url"] = user.avatarUrl.mxc;
|
||||
User user = await room.client.store
|
||||
?.getUser(matrixID: eventUpdate.content["sender"], room: room);
|
||||
if (user != null) {
|
||||
eventUpdate.content["displayname"] = user.displayName;
|
||||
eventUpdate.content["avatar_url"] = user.avatarUrl.mxc;
|
||||
}
|
||||
|
||||
Event newEvent = Event.fromJson(eventUpdate.content, room);
|
||||
|
||||
events.insert(0, newEvent);
|
||||
if (onInsert != null) onInsert(0);
|
||||
}
|
||||
|
||||
Event newEvent = Event.fromJson(eventUpdate.content, room);
|
||||
|
||||
events.insert(0, newEvent);
|
||||
if (onInsert != null) onInsert(0);
|
||||
}
|
||||
sortAndUpdate();
|
||||
} catch (e) {
|
||||
|
|
|
@ -376,7 +376,12 @@ class FakeMatrixApi extends MockClient {
|
|||
},
|
||||
"/client/r0/rooms/!localpart:server.abc/read_markers": (var reqI) => {},
|
||||
},
|
||||
"PUT": {},
|
||||
"PUT": {
|
||||
"/client/r0/rooms/!1234:example.com/send/m.room.message/1234":
|
||||
(var reqI) => {
|
||||
"event_id": "42",
|
||||
},
|
||||
},
|
||||
"DELETE": {
|
||||
"/unknown/token": (var req) => {"errcode": "M_UNKNOWN_TOKEN"},
|
||||
},
|
||||
|
|
|
@ -27,6 +27,7 @@ import 'package:famedlysdk/src/Room.dart';
|
|||
import 'package:famedlysdk/src/Timeline.dart';
|
||||
import 'package:famedlysdk/src/sync/EventUpdate.dart';
|
||||
import 'package:famedlysdk/src/utils/ChatTime.dart';
|
||||
import 'FakeMatrixApi.dart';
|
||||
|
||||
void main() {
|
||||
/// All Tests related to the MxContent
|
||||
|
@ -36,21 +37,22 @@ void main() {
|
|||
int updateCount = 0;
|
||||
List<int> insertList = [];
|
||||
|
||||
Client client = Client("testclient", debug: true);
|
||||
client.connection.httpClient = FakeMatrixApi();
|
||||
client.homeserver = "https://fakeServer.notExisting";
|
||||
|
||||
Room room = Room(id: roomID, client: client);
|
||||
Timeline timeline = Timeline(
|
||||
room: room,
|
||||
events: [],
|
||||
onUpdate: () {
|
||||
updateCount++;
|
||||
},
|
||||
onInsert: (int insertID) {
|
||||
insertList.add(insertID);
|
||||
});
|
||||
|
||||
test("Create", () async {
|
||||
Client client = Client("testclient");
|
||||
client.homeserver = "https://testserver.abc";
|
||||
|
||||
Room room = Room(id: roomID, client: client);
|
||||
Timeline timeline = Timeline(
|
||||
room: room,
|
||||
events: [],
|
||||
onUpdate: () {
|
||||
updateCount++;
|
||||
},
|
||||
onInsert: (int insertID) {
|
||||
insertList.add(insertID);
|
||||
});
|
||||
|
||||
client.connection.onEvent.add(EventUpdate(
|
||||
type: "timeline",
|
||||
roomID: roomID,
|
||||
|
@ -91,5 +93,48 @@ void main() {
|
|||
expect(timeline.events[0].getBody(), "Testcase");
|
||||
expect(timeline.events[0].time > timeline.events[1].time, true);
|
||||
});
|
||||
|
||||
test("Send message", () async {
|
||||
room.sendTextEvent("test", txid: "1234");
|
||||
|
||||
await new Future.delayed(new Duration(milliseconds: 50));
|
||||
|
||||
expect(updateCount, 4);
|
||||
expect(insertList, [0, 0, 0]);
|
||||
expect(timeline.events[0].content["txid"], "1234");
|
||||
expect(timeline.events[0].id, "42");
|
||||
expect(timeline.events[0].status, 1);
|
||||
|
||||
client.connection.onEvent.add(EventUpdate(
|
||||
type: "timeline",
|
||||
roomID: roomID,
|
||||
eventType: "m.room.message",
|
||||
content: {
|
||||
"type": "m.room.message",
|
||||
"content": {"msgtype": "m.text", "body": "test"},
|
||||
"sender": "@alice:example.com",
|
||||
"status": 2,
|
||||
"id": "42",
|
||||
"origin_server_ts": DateTime.now().millisecondsSinceEpoch
|
||||
}));
|
||||
|
||||
await new Future.delayed(new Duration(milliseconds: 50));
|
||||
|
||||
expect(updateCount, 5);
|
||||
expect(insertList, [0, 0, 0]);
|
||||
expect(timeline.events[0].id, "42");
|
||||
expect(timeline.events[0].status, 2);
|
||||
});
|
||||
|
||||
test("Send message with error", () async {
|
||||
room.sendTextEvent("test", txid: "errortxid");
|
||||
|
||||
await new Future.delayed(new Duration(milliseconds: 50));
|
||||
|
||||
expect(updateCount, 7);
|
||||
expect(insertList, [0, 0, 0, 0]);
|
||||
expect(timeline.events[0].content["txid"], "errortxid");
|
||||
expect(timeline.events[0].status, -1);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue