Skip to content
Draft
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
162 changes: 49 additions & 113 deletions lib/src/client.dart
Original file line number Diff line number Diff line change
Expand Up @@ -374,12 +374,6 @@ class Client extends MatrixApi {
List<Room> get rooms => _rooms;
List<Room> _rooms = [];

/// Get a list of the archived rooms
///
/// Attention! Archived rooms are only returned if [loadArchive()] was called
/// beforehand! The state refers to the last retrieval via [loadArchive()]!
List<ArchivedRoom> get archivedRooms => _archivedRooms;

bool enableDehydratedDevices = false;

final String dehydratedDeviceDisplayName;
Expand Down Expand Up @@ -449,7 +443,7 @@ class Client extends MatrixApi {
/// found. If you have loaded the [loadArchive()] before, it can also return
/// archived rooms.
Room? getRoomById(String id) {
for (final room in <Room>[...rooms, ..._archivedRooms.map((e) => e.room)]) {
for (final room in rooms) {
if (room.id == id) return room;
}

Expand Down Expand Up @@ -1189,25 +1183,6 @@ class Client extends MatrixApi {
);
}

final List<ArchivedRoom> _archivedRooms = [];

/// Return an archive room containing the room and the timeline for a specific archived room.
ArchivedRoom? getArchiveRoomFromCache(String roomId) {
for (var i = 0; i < _archivedRooms.length; i++) {
final archive = _archivedRooms[i];
if (archive.room.id == roomId) return archive;
}
return null;
}

/// Remove all the archives stored in cache.
void clearArchivesFromCache() {
_archivedRooms.clear();
}

@Deprecated('Use [loadArchive()] instead.')
Future<List<Room>> get archive => loadArchive();

/// Fetch all the archived rooms from the server and return the list of the
/// room. If you want to have the Timelines bundled with it, use
/// loadArchiveWithTimeline instead.
Expand All @@ -1227,8 +1202,6 @@ class Client extends MatrixApi {
/// Fetch the archived rooms from the server and return them as a list of
/// [ArchivedRoom] objects containing the [Room] and the associated [Timeline].
Future<List<ArchivedRoom>> loadArchiveWithTimeline() async {
_archivedRooms.clear();

final filter = jsonEncode(
Filter(
room: RoomFilter(
Expand All @@ -1248,92 +1221,57 @@ class Client extends MatrixApi {
_archiveCacheBusterTimeout = (_archiveCacheBusterTimeout + 1) % 30;

final leave = syncResp.rooms?.leave;
final archivedRooms = <ArchivedRoom>[];
if (leave != null) {
for (final entry in leave.entries) {
await _storeArchivedRoom(entry.key, entry.value);
final room = Room(
id: entry.key,
prev_batch: entry.value.timeline?.prevBatch,
membership: Membership.leave,
client: this,
roomAccountData: entry.value.accountData
?.asMap()
.map((k, v) => MapEntry(v.type, v)) ??
<String, BasicEvent>{},
);
entry.value.state?.forEach(room.setState);
final timeline = Timeline(
room: room,
chunk: TimelineChunk(
events: entry.value.timeline?.events?.reversed
.toList() // we display the event in the other sence
.map((e) => Event.fromMatrixEvent(e, room))
.toList() ??
[],
),
);
for (var i = 0; i < timeline.events.length; i++) {
// Try to decrypt encrypted events but don't update the database.
if (room.encrypted && room.client.encryptionEnabled) {
if (timeline.events[i].type == EventTypes.Encrypted) {
await room.client.encryption!
.decryptRoomEvent(timeline.events[i])
.then(
(decrypted) => timeline.events[i] = decrypted,
);
}
}
}

archivedRooms.add(ArchivedRoom(room: room, timeline: timeline));
}
}

// Sort the archived rooms by last event originServerTs as this is the
// best indicator we have to sort them. For archived rooms where we don't
// have any, we move them to the bottom.
final beginningOfTime = DateTime.fromMillisecondsSinceEpoch(0);
_archivedRooms.sort(
archivedRooms.sort(
(b, a) => (a.room.lastEvent?.originServerTs ?? beginningOfTime)
.compareTo(b.room.lastEvent?.originServerTs ?? beginningOfTime),
);

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, BasicEvent>{},
);
// 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 seence
.map((e) => Event.fromMatrixEvent(e, archivedRoom))
.toList() ??
[],
),
);

archivedRoom.prev_batch = update.timeline?.prevBatch;

final stateEvents = roomUpdate.state;
if (stateEvents != null) {
await _handleRoomEvents(
archivedRoom,
stateEvents,
EventUpdateType.state,
store: false,
);
}

final timelineEvents = roomUpdate.timeline?.events;
if (timelineEvents != null) {
await _handleRoomEvents(
archivedRoom,
timelineEvents.toList(),
EventUpdateType.timeline,
store: false,
);
}

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(timeline.events[i])
.then(
(decrypted) => timeline.events[i] = decrypted,
);
}
}
}

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

@override
Expand Down Expand Up @@ -2799,12 +2737,15 @@ class Client extends MatrixApi {
room,
timelineEvents,
timelineUpdateType,
store: false,
store: syncFilter.room?.includeLeave == true,
);
}
final accountData = syncRoomUpdate.accountData;
if (accountData != null && accountData.isNotEmpty) {
for (final event in accountData) {
if (syncFilter.room?.includeLeave == true) {
await database.storeRoomAccountData(room.id, event);
}
room.roomAccountData[event.type] = event;
}
}
Expand All @@ -2814,7 +2755,7 @@ class Client extends MatrixApi {
room,
state,
EventUpdateType.state,
store: false,
store: syncFilter.room?.includeLeave == true,
);
}
}
Expand Down Expand Up @@ -3059,21 +3000,16 @@ class Client extends MatrixApi {

// Does the chat already exist in the list rooms?
if (!found && membership != Membership.leave) {
// Check if the room is not in the rooms in the invited list
if (_archivedRooms.isNotEmpty) {
_archivedRooms.removeWhere((archive) => archive.room.id == roomId);
}
final position = membership == Membership.invite ? 0 : rooms.length;
// Add the new chat to the list
rooms.insert(position, room);
}
// If the membership is "leave" then remove the item and stop here
else if (found && membership == Membership.leave) {
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);
else if (membership == Membership.leave) {
if (syncFilter.room?.includeLeave == true && !found) {
rooms.add(room);
} else if (found) {
rooms.removeAt(roomIndex);
}
}
// Update notification, highlight count and/or additional information
Expand Down
3 changes: 2 additions & 1 deletion lib/src/database/matrix_sdk_database.dart
Original file line number Diff line number Diff line change
Expand Up @@ -1341,7 +1341,8 @@ class MatrixSdkDatabase extends DatabaseApi with DatabaseFileStorage {
Client client,
) async {
// Leave room if membership is leave
if (roomUpdate is LeftRoomUpdate) {
if (roomUpdate is LeftRoomUpdate &&
client.syncFilter.room?.includeLeave != true) {
await forgetRoom(roomId);
return;
}
Expand Down
17 changes: 0 additions & 17 deletions lib/src/room.dart
Original file line number Diff line number Diff line change
Expand Up @@ -1397,12 +1397,6 @@ 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 Expand Up @@ -1697,17 +1691,6 @@ class Room {
limit: limit,
);
});
} else {
final archive = client.getArchiveRoomFromCache(id);
events = archive?.timeline.events.toList() ?? [];
for (var i = 0; i < events.length; i++) {
// Try to decrypt encrypted events but don't update the database.
if (encrypted && client.encryptionEnabled) {
if (events[i].type == EventTypes.Encrypted) {
events[i] = await client.encryption!.decryptRoomEvent(events[i]);
}
}
}
}

var chunk = TimelineChunk(events: events);
Expand Down
27 changes: 0 additions & 27 deletions test/client_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -1754,11 +1754,6 @@ void main() {
reason:
'Count of invited+joined before loadArchive() rooms does not match',
);
expect(
client.archivedRooms.length,
0,
reason: 'Count of archived rooms before loadArchive() does not match',
);

await client.loadArchive();

Expand All @@ -1767,28 +1762,6 @@ void main() {
3,
reason: 'Count of invited+joined rooms does not match',
);
expect(
client.archivedRooms.length,
2,
reason: 'Count of archived rooms does not match',
);

expect(
client.archivedRooms.firstWhereOrNull(
(r) => r.room.id == '!5345234234:example.com',
) !=
null,
true,
reason: '!5345234234:example.com not found as archived room',
);
expect(
client.archivedRooms.firstWhereOrNull(
(r) => r.room.id == '!5345234235:example.com',
) !=
null,
true,
reason: '!5345234235:example.com not found as archived room',
);

await client.dispose();
});
Expand Down
Loading
Loading