diff --git a/lib/src/client.dart b/lib/src/client.dart index 2b6ab05..2fa06a7 100644 --- a/lib/src/client.dart +++ b/lib/src/client.dart @@ -986,16 +986,17 @@ class Client { final syncResp = await _syncRequest; if (hash != _syncRequest.hashCode) return; _timeoutFactor = 1; - final futures = handleSync(syncResp); + if (database != null) { + await database.transaction(() async { + await handleSync(syncResp); + if (prevBatch != syncResp['next_batch']) { + await database.storePrevBatch(syncResp['next_batch'], id); + } + }); + } else { + await handleSync(syncResp); + } if (_disposed) return; - await database?.transaction(() async { - for (final f in futures) { - await f(); - } - if (prevBatch != syncResp['next_batch']) { - await database.storePrevBatch(syncResp['next_batch'], id); - } - }); if (prevBatch == null) { onFirstSync.add(true); prevBatch = syncResp['next_batch']; @@ -1015,34 +1016,33 @@ class Client { } /// Use this method only for testing utilities! - List Function()> handleSync(dynamic sync) { - final dbActions = Function()>[]; + Future handleSync(dynamic sync) async { if (sync['to_device'] is Map && sync['to_device']['events'] is List) { _handleToDeviceEvents(sync['to_device']['events']); } if (sync['rooms'] is Map) { if (sync['rooms']['join'] is Map) { - _handleRooms(sync['rooms']['join'], Membership.join, dbActions); + await _handleRooms(sync['rooms']['join'], Membership.join); } if (sync['rooms']['invite'] is Map) { - _handleRooms(sync['rooms']['invite'], Membership.invite, dbActions); + await _handleRooms(sync['rooms']['invite'], Membership.invite); } if (sync['rooms']['leave'] is Map) { - _handleRooms(sync['rooms']['leave'], Membership.leave, dbActions); + await _handleRooms(sync['rooms']['leave'], Membership.leave); } } if (sync['presence'] is Map && sync['presence']['events'] is List) { - _handleGlobalEvents(sync['presence']['events'], 'presence', dbActions); + await _handleGlobalEvents(sync['presence']['events'], 'presence'); } if (sync['account_data'] is Map && sync['account_data']['events'] is List) { - _handleGlobalEvents( - sync['account_data']['events'], 'account_data', dbActions); + await _handleGlobalEvents( + sync['account_data']['events'], 'account_data'); } if (sync['device_lists'] is Map) { - _handleDeviceListsEvents(sync['device_lists'], dbActions); + await _handleDeviceListsEvents(sync['device_lists']); } if (sync['device_one_time_keys_count'] is Map) { _handleDeviceOneTimeKeysCount(sync['device_one_time_keys_count']); @@ -1054,7 +1054,6 @@ class Client { ); } onSync.add(sync); - return dbActions; } void _handleDeviceOneTimeKeysCount( @@ -1071,15 +1070,13 @@ class Client { } } - void _handleDeviceListsEvents(Map deviceLists, - List Function()> dbActions) { + Future _handleDeviceListsEvents(Map deviceLists) async { if (deviceLists['changed'] is List) { for (final userId in deviceLists['changed']) { if (_userDeviceKeys.containsKey(userId)) { _userDeviceKeys[userId].outdated = true; if (database != null) { - dbActions - .add(() => database.storeUserDeviceKeysInfo(id, userId, true)); + await database.storeUserDeviceKeysInfo(id, userId, true); } } } @@ -1175,9 +1172,10 @@ class Client { } } - void _handleRooms(Map rooms, Membership membership, - List Function()> dbActions) { - rooms.forEach((String id, dynamic room) { + Future _handleRooms(Map rooms, Membership membership) async { + for (final entry in rooms.entries) { + final id = entry.key; + final room = entry.value; // calculate the notification counts, the limitedTimeline and prevbatch num highlight_count = 0; num notification_count = 0; @@ -1224,8 +1222,7 @@ class Client { roomObj.resetSortOrder(); } if (database != null) { - dbActions.add( - () => database.storeRoomUpdate(this.id, update, getRoomById(id))); + await database.storeRoomUpdate(this.id, update, getRoomById(id)); } onRoomUpdate.add(update); @@ -1235,45 +1232,44 @@ class Client { if (room['state'] is Map && room['state']['events'] is List && room['state']['events'].isNotEmpty) { - _handleRoomEvents(id, room['state']['events'], 'state', dbActions); + await _handleRoomEvents(id, room['state']['events'], 'state'); handledEvents = true; } if (room['invite_state'] is Map && room['invite_state']['events'] is List) { - _handleRoomEvents( - id, room['invite_state']['events'], 'invite_state', dbActions); + await _handleRoomEvents( + id, room['invite_state']['events'], 'invite_state'); } if (room['timeline'] is Map && room['timeline']['events'] is List && room['timeline']['events'].isNotEmpty) { - _handleRoomEvents( - id, room['timeline']['events'], 'timeline', dbActions); + await _handleRoomEvents( + id, room['timeline']['events'], 'timeline'); handledEvents = true; } if (room['ephemeral'] is Map && room['ephemeral']['events'] is List) { - _handleEphemerals(id, room['ephemeral']['events'], dbActions); + await _handleEphemerals(id, room['ephemeral']['events']); } if (room['account_data'] is Map && room['account_data']['events'] is List) { - _handleRoomEvents( - id, room['account_data']['events'], 'account_data', dbActions); + await _handleRoomEvents( + id, room['account_data']['events'], 'account_data'); } if (handledEvents && database != null && roomObj != null) { - dbActions.add(() => roomObj.updateSortOrder()); + await roomObj.updateSortOrder(); } - }); + } } - void _handleEphemerals(String id, List events, - List Function()> dbActions) { + Future _handleEphemerals(String id, List events) async { for (num i = 0; i < events.length; i++) { - _handleEvent(events[i], id, 'ephemeral', dbActions); + await _handleEvent(events[i], id, 'ephemeral'); // Receipt events are deltas between two states. We will create a // fake room account data event for this and store the difference @@ -1310,20 +1306,18 @@ class Client { } } events[i]['content'] = receiptStateContent; - _handleEvent(events[i], id, 'account_data', dbActions); + await _handleEvent(events[i], id, 'account_data'); } } } - void _handleRoomEvents(String chat_id, List events, String type, - List Function()> dbActions) { + Future _handleRoomEvents(String chat_id, List events, String type) async { for (num i = 0; i < events.length; i++) { - _handleEvent(events[i], chat_id, type, dbActions); + await _handleEvent(events[i], chat_id, type); } } - void _handleGlobalEvents(List events, String type, - List Function()> dbActions) { + Future _handleGlobalEvents(List events, String type) async { for (var i = 0; i < events.length; i++) { if (events[i]['type'] is String && events[i]['content'] is Map) { @@ -1333,15 +1327,14 @@ class Client { content: events[i], ); if (database != null) { - dbActions.add(() => database.storeUserEventUpdate(id, update)); + await database.storeUserEventUpdate(id, update); } onUserEvent.add(update); } } } - void _handleEvent(Map event, String roomID, String type, - List Function()> dbActions) { + Future _handleEvent(Map event, String roomID, String type) async { if (event['type'] is String && event['content'] is Map) { // The client must ignore any new m.room.encryption event to prevent // man-in-the-middle attacks! @@ -1365,7 +1358,7 @@ class Client { update = update.decrypt(room); } if (type != 'ephemeral' && database != null) { - dbActions.add(() => database.storeEventUpdate(id, update)); + await database.storeEventUpdate(id, update); } _updateRoomsByEventUpdate(update); onEvent.add(update); diff --git a/lib/src/timeline.dart b/lib/src/timeline.dart index 2762a8b..9b765f8 100644 --- a/lib/src/timeline.dart +++ b/lib/src/timeline.dart @@ -116,19 +116,6 @@ class Timeline { try { if (eventUpdate.roomID != room.id) return; - // try to decrypt the event first, if needed - if (eventUpdate.eventType == 'm.room.encrypted' && room.client.database != null) { - try { - await room.loadInboundGroupSessionKey(eventUpdate.content['content']['session_id']); - eventUpdate = eventUpdate.decrypt(room); - if (eventUpdate.eventType != 'm.room.encrypted') { - await room.client.database.storeEventUpdate(room.client.id, eventUpdate); - } - } catch (err) { - print('[WARNING] (_handleEventUpdate) Failed to decrypt event: ${err.toString()}'); - } - } - if (eventUpdate.type == 'timeline' || eventUpdate.type == 'history') { // Redaction events are handled as modification for existing events. if (eventUpdate.eventType == 'm.room.redaction') { diff --git a/test/client_test.dart b/test/client_test.dart index d30b4cf..5772511 100644 --- a/test/client_test.dart +++ b/test/client_test.dart @@ -207,7 +207,7 @@ void main() { .verified, false); - matrix.handleSync({ + await matrix.handleSync({ 'device_lists': { 'changed': [ '@alice:example.com', @@ -221,7 +221,7 @@ void main() { expect(matrix.userDeviceKeys.length, 2); expect(matrix.userDeviceKeys['@alice:example.com'].outdated, true); - matrix.handleSync({ + await matrix.handleSync({ 'rooms': { 'join': { '!726s6s6q:example.com': { @@ -527,7 +527,7 @@ void main() { test('Track oneTimeKeys', () async { if (matrix.encryptionEnabled) { var last = matrix.lastTimeKeysUploaded ?? DateTime.now(); - matrix.handleSync({ + await matrix.handleSync({ 'device_one_time_keys_count': {'signed_curve25519': 49} }); await Future.delayed(Duration(milliseconds: 50)); @@ -542,7 +542,7 @@ void main() { expect(matrix.rooms[1].outboundGroupSession == null, true); await matrix.rooms[1].createOutboundGroupSession(); expect(matrix.rooms[1].outboundGroupSession != null, true); - matrix.handleSync({ + await matrix.handleSync({ 'device_lists': { 'changed': [ '@alice:example.com', @@ -562,7 +562,7 @@ void main() { expect(matrix.rooms[1].outboundGroupSession == null, true); await matrix.rooms[1].createOutboundGroupSession(); expect(matrix.rooms[1].outboundGroupSession != null, true); - matrix.handleSync({ + await matrix.handleSync({ 'rooms': { 'join': { '!726s6s6q:example.com': {