feat: Auto refresh last event after limited timeline
This adds a new behavior on sync that the app automatically fetches the last event from server after we receive a limited timeline and the lastEvent has not changed.
This commit is contained in:
parent
7f290f42a2
commit
8a4eda5201
|
|
@ -1740,6 +1740,28 @@ class FakeMatrixApi extends BaseClient {
|
|||
'origin_server_ts': 1432735824653,
|
||||
'unsigned': {'age': 1234},
|
||||
},
|
||||
'/client/v3/rooms/!localpart%3Aserver.abc/messages?dir=b&limit=1&filter=%7B%22types%22%3A%5B%22m.room.message%22%2C%22m.room.encrypted%22%2C%22m.sticker%22%2C%22m.call.invite%22%2C%22m.call.answer%22%2C%22m.call.reject%22%2C%22m.call.hangup%22%2C%22com.famedly.call.member%22%5D%7D':
|
||||
(var req) => {
|
||||
'start': 't47429-4392820_219380_26003_2265',
|
||||
'end': 't47409-4357353_219380_26003_2265',
|
||||
'chunk': [
|
||||
{
|
||||
'content': {
|
||||
'body': 'This is an example text message',
|
||||
'msgtype': 'm.text',
|
||||
'format': 'org.matrix.custom.html',
|
||||
'formatted_body':
|
||||
'<b>This is an example text message</b>',
|
||||
},
|
||||
'type': 'm.room.message',
|
||||
'event_id': '3143273582443PhrSn:example.org',
|
||||
'room_id': '!1234:example.com',
|
||||
'sender': '@example:example.org',
|
||||
'origin_server_ts': 1432735824653,
|
||||
'unsigned': {'age': 1234},
|
||||
},
|
||||
],
|
||||
},
|
||||
'/client/v3/rooms/new_room_id/messages?from=emptyHistoryResponse&dir=b&limit=30&filter=%7B%22lazy_load_members%22%3Atrue%7D':
|
||||
(var req) => emptyHistoryResponse,
|
||||
'/client/v3/rooms/new_room_id/messages?from=1&dir=b&limit=30&filter=%7B%22lazy_load_members%22%3Atrue%7D':
|
||||
|
|
|
|||
|
|
@ -2632,13 +2632,15 @@ class Client extends MatrixApi {
|
|||
final id = entry.key;
|
||||
final syncRoomUpdate = entry.value;
|
||||
|
||||
final room = await _updateRoomsByRoomUpdate(id, syncRoomUpdate);
|
||||
|
||||
// Is the timeline limited? Then all previous messages should be
|
||||
// removed from the database!
|
||||
if (syncRoomUpdate is JoinedRoomUpdate &&
|
||||
syncRoomUpdate.timeline?.limited == true) {
|
||||
await database.deleteTimelineForRoom(id);
|
||||
room.lastEvent = null;
|
||||
}
|
||||
final room = await _updateRoomsByRoomUpdate(id, syncRoomUpdate);
|
||||
|
||||
final timelineUpdateType = direction != null
|
||||
? (direction == Direction.b
|
||||
|
|
@ -2739,6 +2741,12 @@ class Client extends MatrixApi {
|
|||
continue;
|
||||
}
|
||||
await database.storeRoomUpdate(id, syncRoomUpdate, room.lastEvent, this);
|
||||
|
||||
if (syncRoomUpdate is JoinedRoomUpdate &&
|
||||
syncRoomUpdate.timeline?.limited == true &&
|
||||
room.lastEvent == null) {
|
||||
runInRoot(room.refreshLastEvent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -3035,13 +3043,6 @@ class Client extends MatrixApi {
|
|||
}
|
||||
if (type != EventUpdateType.timeline) break;
|
||||
|
||||
// If last event is null or not a valid room preview event anyway,
|
||||
// just use this:
|
||||
if (room.lastEvent == null) {
|
||||
room.lastEvent = event;
|
||||
break;
|
||||
}
|
||||
|
||||
// Is this event redacting the last event?
|
||||
if (event.type == EventTypes.Redaction &&
|
||||
({
|
||||
|
|
|
|||
|
|
@ -377,6 +377,55 @@ class Room {
|
|||
|
||||
Event? lastEvent;
|
||||
|
||||
/// Fetches the most recent event in the timeline from the server to have
|
||||
/// a valid preview after receiving a limited timeline from the sync. Will
|
||||
/// be triggered by the sync loop on demand.
|
||||
Future<Event?> refreshLastEvent() async {
|
||||
if (membership != Membership.join) return null;
|
||||
|
||||
final filter = StateFilter(types: client.roomPreviewLastEvents.toList());
|
||||
final result = await client.getRoomEvents(
|
||||
id,
|
||||
Direction.b,
|
||||
limit: 1,
|
||||
filter: jsonEncode(filter.toJson()),
|
||||
);
|
||||
final matrixEvent = result.chunk.firstOrNull;
|
||||
if (matrixEvent == null) {
|
||||
Logs().d('No last event found for room', id);
|
||||
return null;
|
||||
}
|
||||
var event = Event.fromMatrixEvent(
|
||||
matrixEvent,
|
||||
this,
|
||||
status: EventStatus.synced,
|
||||
);
|
||||
if (event.type == EventTypes.Encrypted) {
|
||||
final encryption = client.encryption;
|
||||
if (encryption != null) {
|
||||
event = await encryption.decryptRoomEvent(event);
|
||||
}
|
||||
}
|
||||
lastEvent = event;
|
||||
|
||||
Logs().d('Refreshed last event for room', id);
|
||||
|
||||
// Trigger sync handling so that lastEvent gets stored and room list gets
|
||||
// updated.
|
||||
await _handleFakeSync(
|
||||
SyncUpdate(
|
||||
nextBatch: '',
|
||||
rooms: RoomsUpdate(
|
||||
join: {
|
||||
id: JoinedRoomUpdate(timeline: TimelineUpdate(limited: false)),
|
||||
},
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
return event;
|
||||
}
|
||||
|
||||
void setEphemeral(BasicEvent ephemeral) {
|
||||
ephemerals[ephemeral.type] = ephemeral;
|
||||
if (ephemeral.type == 'm.typing') {
|
||||
|
|
|
|||
|
|
@ -883,6 +883,29 @@ void main() {
|
|||
expect(timeline.events.length, 17);
|
||||
});
|
||||
|
||||
test('Refresh last event', () async {
|
||||
expect(room.lastEvent?.eventId, '12');
|
||||
final lastEventUpdate =
|
||||
room.client.onSync.stream.firstWhere((u) => u.nextBatch.isEmpty);
|
||||
await room.client.handleSync(
|
||||
SyncUpdate(
|
||||
nextBatch: 'abcd',
|
||||
rooms: RoomsUpdate(
|
||||
join: {
|
||||
room.id: JoinedRoomUpdate(
|
||||
timeline: TimelineUpdate(
|
||||
events: [],
|
||||
limited: true,
|
||||
),
|
||||
),
|
||||
},
|
||||
),
|
||||
),
|
||||
);
|
||||
await lastEventUpdate;
|
||||
expect(room.lastEvent?.eventId, '3143273582443PhrSn:example.org');
|
||||
});
|
||||
|
||||
test('isFederated', () {
|
||||
expect(room.isFederated, true);
|
||||
room.setState(
|
||||
|
|
|
|||
Loading…
Reference in New Issue