diff --git a/lib/src/Event.dart b/lib/src/Event.dart index 011a151..1989a85 100644 --- a/lib/src/Event.dart +++ b/lib/src/Event.dart @@ -22,6 +22,7 @@ */ import 'dart:convert'; +import 'package:famedlysdk/src/sync/EventUpdate.dart'; import 'package:famedlysdk/src/utils/ChatTime.dart'; import 'package:famedlysdk/src/Client.dart'; import './User.dart'; @@ -148,6 +149,28 @@ class Event { ); } + /// Removes this event if the status is < 1. This event will just be removed + /// from the database and the timelines. + Future remove() async { + if (status < 1) { + room.client.connection.onEvent.add(EventUpdate( + roomID: room.id, + type: "timeline", + eventType: environment, + content: { + "event_id": id, + "status": -2, + })); + } + } + + /// Try to send this event again. Only works with events of status -1. + Future sendAgain({String txid}) async { + if (status != -1) return; + remove(); + room.sendTextEvent(text, txid: txid); + } + @Deprecated("Use [client.store.getEventList(Room room)] instead!") static Future> getEventList(Client matrix, Room room) async { List eventList = await matrix.store.getEventList(room); @@ -176,6 +199,7 @@ enum EventTypes { } final Map StatusTypes = { + "REMOVE": -2, "ERROR": -1, "SENDING": 0, "SENT": 1, diff --git a/lib/src/Store.dart b/lib/src/Store.dart index 4bb0a6a..32fd144 100644 --- a/lib/src/Store.dart +++ b/lib/src/Store.dart @@ -220,7 +220,10 @@ class Store { } // Save the event in the database - if ((status == 1 || status == -1) && + if (status == -2) { + txn.rawDelete( + "DELETE FROM Events WHERE id=?", [eventContent["event_id"]]); + } else if ((status == 1 || status == -1) && eventUpdate.content["txid"] is String) txn.rawUpdate("UPDATE Events SET status=?, id=?, WHERE id=?", [status, eventContent["event_id"], eventUpdate.content["txid"]]); diff --git a/lib/src/Timeline.dart b/lib/src/Timeline.dart index ab36ab0..e01802f 100644 --- a/lib/src/Timeline.dart +++ b/lib/src/Timeline.dart @@ -43,28 +43,37 @@ class Timeline { sub ??= room.client.connection.onEvent.stream.listen(_handleEventUpdate); } + int _findEvent({String event_id, String txid, String unsigned_txid}) { + int i; + for (i = 0; i < events.length; i++) { + if (events[i].content.containsKey("txid") && + events[i].content["txid"] == txid || + events[i].id == event_id || + (events[i].content["txid"] == unsigned_txid)) break; + } + return i; + } + void _handleEventUpdate(EventUpdate eventUpdate) async { try { if (eventUpdate.roomID != room.id) return; if (eventUpdate.type == "timeline" || eventUpdate.type == "history") { + if (eventUpdate.content["status"] == -2) { + int i = _findEvent(event_id: eventUpdate.content["event_id"]); + if (i < events.length) events.removeAt(i); + } // Is this event already in the timeline? - if (eventUpdate.content["status"] == 1 || + else if (eventUpdate.content["status"] == 1 || eventUpdate.content["status"] == -1 || (eventUpdate.content.containsKey("unsigned") && eventUpdate.content["unsigned"]["transaction_id"] is String)) { - 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["event_id"] || - (eventUpdate.content.containsKey("unsigned") && - eventUpdate.content["unsigned"]["transaction_id"] - is String && - events[i].content["txid"] == - eventUpdate.content["unsigned"]["transaction_id"])) - break; - } + int i = _findEvent( + event_id: eventUpdate.content["event_id"], + txid: eventUpdate.content["content"]["txid"], + unsigned_txid: eventUpdate.content.containsKey("unsigned") + ? eventUpdate.content["unsigned"]["transaction_id"] + : null); + if (i < events.length) { events[i] = Event.fromJson(eventUpdate.content, room); } diff --git a/test/Timeline_test.dart b/test/Timeline_test.dart index f1033f4..bd84dc3 100644 --- a/test/Timeline_test.dart +++ b/test/Timeline_test.dart @@ -161,5 +161,31 @@ void main() { expect(timeline.events[2].content["txid"], "errortxid"); expect(timeline.events[2].status, -1); }); + + test("Remove message", () async { + timeline.events[0].remove(); + + await new Future.delayed(new Duration(milliseconds: 50)); + + expect(updateCount, 13); + + expect(insertList, [0, 0, 0, 0, 0, 0, 0]); + expect(timeline.events.length, 6); + expect(timeline.events[0].content["txid"], "errortxid2"); + expect(timeline.events[0].status, -1); + }); + + test("Resend message", () async { + timeline.events[0].sendAgain(txid: "1234"); + + await new Future.delayed(new Duration(milliseconds: 50)); + + expect(updateCount, 16); + + expect(insertList, [0, 0, 0, 0, 0, 0, 0, 0]); + expect(timeline.events.length, 6); + expect(timeline.events[0].content["txid"], "1234"); + expect(timeline.events[0].status, 1); + }); }); }