Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: incrementally add left rooms to archive #1571

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
114 changes: 68 additions & 46 deletions lib/src/client.dart
Original file line number Diff line number Diff line change
Expand Up @@ -261,7 +261,7 @@ class Client extends MatrixApi {

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;

/// Whether this client supports end-to-end encryption using olm.
Expand Down Expand Up @@ -940,58 +940,74 @@ class Client extends MatrixApi {
final leave = syncResp.rooms?.leave;
if (leave != null) {
for (final entry in leave.entries) {
final id = entry.key;
final room = entry.value;
final leftRoom = Room(
await _storeArchivedRoom(entry.key, entry.value);
}
}
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:
room.accountData?.asMap().map((k, v) => MapEntry(v.type, v)) ??
<String, BasicRoomEvent>{},
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,
));
});

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,
));
});
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 (leftRoom.encrypted && leftRoom.client.encryptionEnabled) {
if (timeline.events[i].type == EventTypes.Encrypted) {
timeline.events[i] =
await leftRoom.client.encryption!.decryptRoomEvent(
leftRoom.id,
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: leftRoom, timeline: timeline));
}
}
return _archivedRooms;

_archivedRooms.add(ArchivedRoom(room: archivedRoom, timeline: timeline));
}

/// Uploads a file and automatically caches it in the database, if it is small enough
Expand Down Expand Up @@ -1892,7 +1908,7 @@ class Client extends MatrixApi {
final syncRoomUpdate = entry.value;

await database?.storeRoomUpdate(id, syncRoomUpdate, this);
final room = _updateRoomsByRoomUpdate(id, syncRoomUpdate);
final room = await _updateRoomsByRoomUpdate(id, syncRoomUpdate);

final timelineUpdateType = direction != null
? (direction == Direction.b
Expand Down Expand Up @@ -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.
// Search the room in the rooms
final roomIndex = rooms.indexWhere((r) => r.id == roomId);
Expand Down Expand Up @@ -2175,8 +2192,13 @@ class Client extends MatrixApi {
room.stopStaleCallsChecker(room.id);

rooms.removeAt(roomIndex);

// in order to keep the archive in sync, add left room to archive
if (chatUpdate is LeftRoomUpdate) {
techno-disaster marked this conversation as resolved.
Show resolved Hide resolved
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 &&
chatUpdate is JoinedRoomUpdate &&
(rooms[roomIndex].membership != membership ||
Expand Down Expand Up @@ -2206,7 +2228,7 @@ class Client extends MatrixApi {
requestHistoryOnLimitedTimeline) {
Logs().v(
'Limited timeline for ${rooms[roomIndex].id} request history now');
runInRoot(rooms[roomIndex].requestHistory);
unawaited(runInRoot(rooms[roomIndex].requestHistory));
}
}
return room;
Expand Down
6 changes: 6 additions & 0 deletions lib/src/room.dart
Original file line number Diff line number Diff line change
Expand Up @@ -1187,6 +1187,12 @@ class Room {
Future<void> forget() async {
await client.database?.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;
}

Expand Down