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:
Marcel 2019-06-26 15:01:15 +00:00
commit e652e79a98
4 changed files with 137 additions and 42 deletions

View file

@ -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 {

View file

@ -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) {

View file

@ -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"},
},

View file

@ -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);
});
});
}