From 4721adde22af20f1b60d37fb37a24f1a000af388 Mon Sep 17 00:00:00 2001 From: td Date: Tue, 6 May 2025 11:26:15 +0200 Subject: [PATCH 1/2] fix: make sure prev_batch is updated after a limited timeline --- lib/fake_matrix_api.dart | 4 ++ lib/src/client.dart | 3 +- test/timeline_test.dart | 106 ++++++++++++++++++++++++++++++++++++++- 3 files changed, 111 insertions(+), 2 deletions(-) diff --git a/lib/fake_matrix_api.dart b/lib/fake_matrix_api.dart index 6bbbc67a..dc2641af 100644 --- a/lib/fake_matrix_api.dart +++ b/lib/fake_matrix_api.dart @@ -1759,6 +1759,10 @@ class FakeMatrixApi extends BaseClient { (var req) => messagesResponsePast, '/client/v3/rooms/!1234%3Aexample.com/messages?from=1234&dir=b&limit=30&filter=%7B%22lazy_load_members%22%3Atrue%7D': (var req) => messagesResponsePast, + '/client/v3/rooms/!1234%3Aexample.com/messages?from=room_preset_1234&dir=b&limit=30&filter=%7B%22lazy_load_members%22%3Atrue%7D': + (var req) => messagesResponsePast, + '/client/v3/rooms/!1234%3Aexample.com/messages?from=room_preset_1234_after_limited&dir=b&limit=30&filter=%7B%22lazy_load_members%22%3Atrue%7D': + (var req) => messagesResponsePast, '/client/v3/rooms/!localpart%3Aserver.abc/messages?from=t456&dir=f&to=1234&limit=10&filter=%7B%22lazy_load_members%22%3Atrue%7D': (var req) => messagesResponseFuture, '/client/v3/rooms/!1234%3Aexample.com/messages?from=t456&dir=f&limit=30&filter=%7B%22lazy_load_members%22%3Atrue%7D': diff --git a/lib/src/client.dart b/lib/src/client.dart index afc54e5d..b557e09e 100644 --- a/lib/src/client.dart +++ b/lib/src/client.dart @@ -2991,7 +2991,8 @@ class Client extends MatrixApi { chatUpdate.timeline?.prevBatch != null)) { /// [InvitedRoomUpdate] doesn't have prev_batch, so we want to set it in case /// the room first appeared in sync update when membership was invite. - if (rooms[roomIndex].membership == Membership.invite && + if ((rooms[roomIndex].membership == Membership.invite || + chatUpdate.timeline?.limited == true) && chatUpdate.timeline?.prevBatch != null) { rooms[roomIndex].prev_batch = chatUpdate.timeline?.prevBatch; } diff --git a/test/timeline_test.dart b/test/timeline_test.dart index 1bd989e8..1643b5f4 100644 --- a/test/timeline_test.dart +++ b/test/timeline_test.dart @@ -78,7 +78,7 @@ void main() { room = Room( id: roomID, client: client, - prev_batch: '1234', + prev_batch: 'room_preset_1234', roomAccountData: {}, ); timeline = Timeline( @@ -1203,6 +1203,110 @@ void main() { 'edit 11', ); }); + + test('make sure a limited timeline resets the prev_batch', () async { + timeline.events.clear(); + + await client.handleSync( + SyncUpdate( + nextBatch: 'something', + rooms: RoomsUpdate( + join: { + timeline.room.id: JoinedRoomUpdate( + timeline: TimelineUpdate( + prevBatch: 'null', + events: [ + MatrixEvent.fromJson({ + 'type': 'm.room.message', + 'content': {'msgtype': 'm.text', 'body': 'Testcase'}, + 'event_id': '11', + 'sender': '@alice:example.com', + 'origin_server_ts': DateTime.now().millisecondsSinceEpoch, + }), + MatrixEvent.fromJson({ + 'type': 'm.room.message', + 'content': {'msgtype': 'm.text', 'body': 'Testcase'}, + 'event_id': '22', + 'sender': '@alice:example.com', + 'origin_server_ts': DateTime.now().millisecondsSinceEpoch, + }), + ], + ), + ), + }, + ), + ), + ); + + Timeline t = await room.getTimeline(); + + expect(t.events.length, 2); + expect(t.room.prev_batch, 'room_preset_1234'); + + await client.handleSync( + SyncUpdate( + nextBatch: 'something2', + rooms: RoomsUpdate( + join: { + timeline.room.id: JoinedRoomUpdate( + timeline: TimelineUpdate( + prevBatch: 'room_preset_1234_after_limited', + limited: true, + events: [ + MatrixEvent.fromJson({ + 'type': 'm.room.message', + 'content': { + 'msgtype': 'm.text', + 'body': '* edit 11', + 'm.new_content': { + 'msgtype': 'm.text', + 'body': 'edit 11', + 'm.mentions': {}, + }, + 'm.mentions': {}, + 'm.relates_to': { + 'rel_type': 'm.replace', + 'event_id': '11', + }, + }, + 'event_id': '33', + 'sender': '@alice:example.com', + 'origin_server_ts': DateTime.now().millisecondsSinceEpoch, + }), + MatrixEvent.fromJson({ + 'type': 'm.room.message', + 'content': { + 'msgtype': 'm.text', + 'body': '* edit 22', + 'm.new_content': { + 'msgtype': 'm.text', + 'body': 'edit 22', + 'm.mentions': {}, + }, + 'm.mentions': {}, + 'm.relates_to': { + 'rel_type': 'm.replace', + 'event_id': '22', + }, + }, + 'event_id': '44', + 'sender': '@alice:example.com', + 'origin_server_ts': DateTime.now().millisecondsSinceEpoch, + }), + ], + ), + ), + }, + ), + ), + ); + + t = await room.getTimeline(); + expect(t.events.length, 2); + expect(t.room.prev_batch, 'room_preset_1234_after_limited'); + await t.requestHistory(); + expect(t.room.prev_batch, 't47409-4357353_219380_26003_2265'); + }); test('logout', () async { await client.logout(); }); From ec855ee52581dafe476dccb01ce1aca30a1f4235 Mon Sep 17 00:00:00 2001 From: td Date: Tue, 6 May 2025 11:31:38 +0200 Subject: [PATCH 2/2] fix: sanity if room prev_batch null, populate it --- lib/src/client.dart | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/src/client.dart b/lib/src/client.dart index b557e09e..fdbc4374 100644 --- a/lib/src/client.dart +++ b/lib/src/client.dart @@ -2991,8 +2991,9 @@ class Client extends MatrixApi { chatUpdate.timeline?.prevBatch != null)) { /// [InvitedRoomUpdate] doesn't have prev_batch, so we want to set it in case /// the room first appeared in sync update when membership was invite. - if ((rooms[roomIndex].membership == Membership.invite || - chatUpdate.timeline?.limited == true) && + if ((rooms[roomIndex].membership == Membership.invite || + chatUpdate.timeline?.limited == true || + rooms[roomIndex].prev_batch == null) && chatUpdate.timeline?.prevBatch != null) { rooms[roomIndex].prev_batch = chatUpdate.timeline?.prevBatch; }