Merge pull request #1571 from TheOneWithTheBraid/braid/store-left-rooms-in-archive

chore: incrementally add left rooms to archive
This commit is contained in:
Nicolas Werner 2023-11-02 09:56:51 +01:00 committed by GitHub
commit 23776e53ad
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 82 additions and 54 deletions

View File

@ -261,7 +261,7 @@ class Client extends MatrixApi {
bool enableDehydratedDevices = false; bool enableDehydratedDevices = false;
/// Wether read receipts are sent as public receipts by default or just as private receipts. /// Whether read receipts are sent as public receipts by default or just as private receipts.
bool receiptsPublicByDefault = true; bool receiptsPublicByDefault = true;
/// Whether this client supports end-to-end encryption using olm. /// Whether this client supports end-to-end encryption using olm.
@ -940,60 +940,76 @@ class Client extends MatrixApi {
final leave = syncResp.rooms?.leave; final leave = syncResp.rooms?.leave;
if (leave != null) { if (leave != null) {
for (final entry in leave.entries) { for (final entry in leave.entries) {
final id = entry.key; await _storeArchivedRoom(entry.key, entry.value);
final room = entry.value;
final leftRoom = Room(
id: id,
membership: Membership.leave,
client: this,
roomAccountData:
room.accountData?.asMap().map((k, v) => MapEntry(v.type, v)) ??
<String, BasicRoomEvent>{},
);
final timeline = Timeline(
room: leftRoom,
chunk: TimelineChunk(
events: room.timeline?.events?.reversed
.toList() // we display the event in the other sence
.map((e) => Event.fromMatrixEvent(e, leftRoom))
.toList() ??
[]));
leftRoom.prev_batch = room.timeline?.prevBatch;
room.state?.forEach((event) {
leftRoom.setState(Event.fromMatrixEvent(
event,
leftRoom,
));
});
room.timeline?.events?.forEach((event) {
leftRoom.setState(Event.fromMatrixEvent(
event,
leftRoom,
));
});
for (var i = 0; i < timeline.events.length; i++) {
// Try to decrypt encrypted events but don't update the database.
if (leftRoom.encrypted && leftRoom.client.encryptionEnabled) {
if (timeline.events[i].type == EventTypes.Encrypted) {
timeline.events[i] =
await leftRoom.client.encryption!.decryptRoomEvent(
leftRoom.id,
timeline.events[i],
);
}
}
}
_archivedRooms.add(ArchivedRoom(room: leftRoom, timeline: timeline));
} }
} }
return _archivedRooms; return _archivedRooms;
} }
/// [_storeArchivedRoom]
/// @leftRoom we can pass a room which was left so that we don't loose states
Future<void> _storeArchivedRoom(
String id,
LeftRoomUpdate update, {
Room? leftRoom,
}) async {
final roomUpdate = update;
final archivedRoom = leftRoom ??
Room(
id: id,
membership: Membership.leave,
client: this,
roomAccountData: roomUpdate.accountData
?.asMap()
.map((k, v) => MapEntry(v.type, v)) ??
<String, BasicRoomEvent>{},
);
// Set membership of room to leave, in the case we got a left room passed, otherwise
// the left room would have still membership join, which would be wrong for the setState later
archivedRoom.membership = Membership.leave;
final timeline = Timeline(
room: archivedRoom,
chunk: TimelineChunk(
events: roomUpdate.timeline?.events?.reversed
.toList() // we display the event in the other sence
.map((e) => Event.fromMatrixEvent(e, archivedRoom))
.toList() ??
[]));
archivedRoom.prev_batch = update.timeline?.prevBatch;
update.state?.forEach((event) {
archivedRoom.setState(Event.fromMatrixEvent(
event,
archivedRoom,
));
});
update.timeline?.events?.forEach((event) {
archivedRoom.setState(Event.fromMatrixEvent(
event,
archivedRoom,
));
});
for (var i = 0; i < timeline.events.length; i++) {
// Try to decrypt encrypted events but don't update the database.
if (archivedRoom.encrypted && archivedRoom.client.encryptionEnabled) {
if (timeline.events[i].type == EventTypes.Encrypted) {
await archivedRoom.client.encryption!
.decryptRoomEvent(
archivedRoom.id,
timeline.events[i],
)
.then(
(decrypted) => timeline.events[i] = decrypted,
);
}
}
}
_archivedRooms.add(ArchivedRoom(room: archivedRoom, timeline: timeline));
}
/// Uploads a file and automatically caches it in the database, if it is small enough /// Uploads a file and automatically caches it in the database, if it is small enough
/// and returns the mxc url. /// and returns the mxc url.
@override @override
@ -1892,7 +1908,7 @@ class Client extends MatrixApi {
final syncRoomUpdate = entry.value; final syncRoomUpdate = entry.value;
await database?.storeRoomUpdate(id, syncRoomUpdate, this); await database?.storeRoomUpdate(id, syncRoomUpdate, this);
final room = _updateRoomsByRoomUpdate(id, syncRoomUpdate); final room = await _updateRoomsByRoomUpdate(id, syncRoomUpdate);
final timelineUpdateType = direction != null final timelineUpdateType = direction != null
? (direction == Direction.b ? (direction == Direction.b
@ -2132,7 +2148,8 @@ class Client extends MatrixApi {
} }
} }
Room _updateRoomsByRoomUpdate(String roomId, SyncRoomUpdate chatUpdate) { Future<Room> _updateRoomsByRoomUpdate(
String roomId, SyncRoomUpdate chatUpdate) async {
// Update the chat list item. // Update the chat list item.
// Search the room in the rooms // Search the room in the rooms
final roomIndex = rooms.indexWhere((r) => r.id == roomId); final roomIndex = rooms.indexWhere((r) => r.id == roomId);
@ -2175,8 +2192,13 @@ class Client extends MatrixApi {
room.stopStaleCallsChecker(room.id); room.stopStaleCallsChecker(room.id);
rooms.removeAt(roomIndex); rooms.removeAt(roomIndex);
// in order to keep the archive in sync, add left room to archive
if (chatUpdate is LeftRoomUpdate) {
await _storeArchivedRoom(room.id, chatUpdate, leftRoom: room);
}
} }
// Update notification, highlight count and/or additional informations // Update notification, highlight count and/or additional information
else if (found && else if (found &&
chatUpdate is JoinedRoomUpdate && chatUpdate is JoinedRoomUpdate &&
(rooms[roomIndex].membership != membership || (rooms[roomIndex].membership != membership ||
@ -2206,7 +2228,7 @@ class Client extends MatrixApi {
requestHistoryOnLimitedTimeline) { requestHistoryOnLimitedTimeline) {
Logs().v( Logs().v(
'Limited timeline for ${rooms[roomIndex].id} request history now'); 'Limited timeline for ${rooms[roomIndex].id} request history now');
runInRoot(rooms[roomIndex].requestHistory); unawaited(runInRoot(rooms[roomIndex].requestHistory));
} }
} }
return room; return room;

View File

@ -1187,6 +1187,12 @@ class Room {
Future<void> forget() async { Future<void> forget() async {
await client.database?.forgetRoom(id); await client.database?.forgetRoom(id);
await client.forgetRoom(id); await client.forgetRoom(id);
// Update archived rooms, otherwise an archived room may still be in the
// list after a forget room call
final roomIndex = client.archivedRooms.indexWhere((r) => r.room.id == id);
if (roomIndex != -1) {
client.archivedRooms.removeAt(roomIndex);
}
return; return;
} }