diff --git a/lib/src/client.dart b/lib/src/client.dart index d2b9bc88..710fcd59 100644 --- a/lib/src/client.dart +++ b/lib/src/client.dart @@ -1706,12 +1706,23 @@ class Client extends MatrixApi { ), ); } else { - if (stateEvent.type != EventTypes.Message || - stateEvent.relationshipType != RelationshipTypes.edit || - stateEvent.relationshipEventId == room.lastEvent?.eventId || - ((room.lastEvent?.relationshipType == RelationshipTypes.edit && + // We want to set state the in-memory cache for the room with the new event. + // To do this, we have to respect to not save edits, unless they edit the + // current last event. + // Additionally, we only store the event in-memory if the room has either been + // post-loaded or the event is animportant state event. + final noMessageOrNoEdit = stateEvent.type != EventTypes.Message || + stateEvent.relationshipType != RelationshipTypes.edit; + final editingLastEvent = + stateEvent.relationshipEventId == room.lastEvent?.eventId; + final consecutiveEdit = + room.lastEvent?.relationshipType == RelationshipTypes.edit && stateEvent.relationshipEventId == - room.lastEvent?.relationshipEventId))) { + room.lastEvent?.relationshipEventId; + final importantOrRoomLoaded = + !room.partial || importantStateEvents.contains(stateEvent.type); + if ((noMessageOrNoEdit || editingLastEvent || consecutiveEdit) && + importantOrRoomLoaded) { room.setState(stateEvent); } } diff --git a/test/client_test.dart b/test/client_test.dart index 7e11af25..7c18bca8 100644 --- a/test/client_test.dart +++ b/test/client_test.dart @@ -348,6 +348,152 @@ void main() { expect(archive[1].name, 'The room name 2'); }); + test('sync state event in-memory handling', () async { + final roomId = '!726s6s6q:example.com'; + final room = matrix.getRoomById(roomId)!; + // put an important state event in-memory + await matrix.handleSync(SyncUpdate.fromJson({ + 'next_batch': 'fakesync', + 'rooms': { + 'join': { + roomId: { + 'state': { + 'events': [ + { + 'sender': '@alice:example.com', + 'type': 'm.room.name', + 'content': {'name': 'foxies'}, + 'state_key': '', + 'origin_server_ts': 1417731086799, + 'event_id': '66697273743033:example.com' + } + ] + } + } + } + } + })); + expect(room.getState('m.room.name')?.content['name'], 'foxies'); + + // drop an unimportant state event from in-memory handling + await matrix.handleSync(SyncUpdate.fromJson({ + 'next_batch': 'fakesync', + 'rooms': { + 'join': { + roomId: { + 'state': { + 'events': [ + { + 'sender': '@alice:example.com', + 'type': 'com.famedly.custom', + 'content': {'name': 'foxies'}, + 'state_key': '', + 'origin_server_ts': 1417731086799, + 'event_id': '66697273743033:example.com' + } + ] + } + } + } + } + })); + expect(room.getState('com.famedly.custom'), null); + + // persist normal room messages + await matrix.handleSync(SyncUpdate.fromJson({ + 'next_batch': 'fakesync', + 'rooms': { + 'join': { + roomId: { + 'timeline': { + 'events': [ + { + 'sender': '@alice:example.com', + 'type': 'm.room.message', + 'content': { + 'msgtype': 'm.text', + 'body': 'meow' + }, + 'origin_server_ts': 1417731086799, + 'event_id': '\$last:example.com' + } + ] + } + } + } + } + })); + expect(room.getState('m.room.message')!.content['body'], 'meow'); + + // ignore edits + await matrix.handleSync(SyncUpdate.fromJson({ + 'next_batch': 'fakesync', + 'rooms': { + 'join': { + roomId: { + 'timeline': { + 'events': [ + { + 'sender': '@alice:example.com', + 'type': 'm.room.message', + 'content': { + 'msgtype': 'm.text', + 'body': '* floooof', + 'm.new_content': { + 'msgtype': 'm.text', + 'body': 'floooof', + }, + 'm.relates_to': { + 'rel_type': 'm.replace', + 'event_id': '\$other:example.com' + }, + }, + 'origin_server_ts': 1417731086799, + 'event_id': '\$edit:example.com' + } + ] + } + } + } + } + })); + expect(room.getState('m.room.message')!.content['body'], 'meow'); + + // accept edits to the last event + await matrix.handleSync(SyncUpdate.fromJson({ + 'next_batch': 'fakesync', + 'rooms': { + 'join': { + roomId: { + 'timeline': { + 'events': [ + { + 'sender': '@alice:example.com', + 'type': 'm.room.message', + 'content': { + 'msgtype': 'm.text', + 'body': '* floooof', + 'm.new_content': { + 'msgtype': 'm.text', + 'body': 'floooof', + }, + 'm.relates_to': { + 'rel_type': 'm.replace', + 'event_id': '\$last:example.com' + }, + }, + 'origin_server_ts': 1417731086799, + 'event_id': '\$edit:example.com' + } + ] + } + } + } + } + })); + expect(room.getState('m.room.message')!.content['body'], '* floooof'); + }); + test('getProfileFromUserId', () async { final profile = await matrix.getProfileFromUserId('@getme:example.com', getFromRooms: false);