diff --git a/lib/src/database/database.dart b/lib/src/database/database.dart index 805330f..d339336 100644 --- a/lib/src/database/database.dart +++ b/lib/src/database/database.dart @@ -529,6 +529,15 @@ class Database extends _$Database { return sdk.Event.fromDb(res.first, room).asUser; } + Future> getUsers(int clientId, sdk.Room room) async { + final res = await dbGetUsers(clientId, room.id).get(); + final ret = []; + for (final r in res) { + ret.add(sdk.Event.fromDb(r, room).asUser); + } + return ret; + } + Future> getEventList(int clientId, sdk.Room room) async { final res = await dbGetEventList(clientId, room.id).get(); final eventList = []; diff --git a/lib/src/database/database.g.dart b/lib/src/database/database.g.dart index 453053e..203313f 100644 --- a/lib/src/database/database.g.dart +++ b/lib/src/database/database.g.dart @@ -6197,6 +6197,13 @@ abstract class _$Database extends GeneratedDatabase { }).map(_rowToDbRoomState); } + Selectable dbGetUsers(int client_id, String room_id) { + return customSelect( + 'SELECT * FROM room_states WHERE client_id = :client_id AND type = \'m.room.member\' AND room_id = :room_id', + variables: [Variable.withInt(client_id), Variable.withString(room_id)], + readsFrom: {roomStates}).map(_rowToDbRoomState); + } + DbEvent _rowToDbEvent(QueryRow row) { return DbEvent( clientId: row.readInt('client_id'), diff --git a/lib/src/database/database.moor b/lib/src/database/database.moor index 716bdc6..cade18c 100644 --- a/lib/src/database/database.moor +++ b/lib/src/database/database.moor @@ -216,6 +216,7 @@ storeRoomState: INSERT OR REPLACE INTO room_states (client_id, event_id, room_id getAllRoomAccountData: SELECT * FROM room_account_data WHERE client_id = :client_id; storeRoomAccountData: INSERT OR REPLACE INTO room_account_data (client_id, type, room_id, content) VALUES (:client_id, :type, :room_id, :content); dbGetUser: SELECT * FROM room_states WHERE client_id = :client_id AND type = 'm.room.member' AND state_key = :state_key AND room_id = :room_id; +dbGetUsers: SELECT * FROM room_states WHERE client_id = :client_id AND type = 'm.room.member' AND room_id = :room_id; dbGetEventList: SELECT * FROM events WHERE client_id = :client_id AND room_id = :room_id GROUP BY event_id ORDER BY sort_order DESC; getStates: SELECT * FROM room_states WHERE client_id = :client_id AND room_id = :room_id; resetNotificationCount: UPDATE rooms SET notification_count = 0, highlight_count = 0 WHERE client_id = :client_id AND room_id = :room_id; diff --git a/lib/src/room.dart b/lib/src/room.dart index 93b6398..0113123 100644 --- a/lib/src/room.dart +++ b/lib/src/room.dart @@ -984,10 +984,20 @@ class Room { /// Request the full list of participants from the server. The local list /// from the store is not complete if the client uses lazy loading. Future> requestParticipants() async { + if (!participantListComplete && partial && client.database != null) { + // we aren't fully loaded, maybe the users are in the database + final users = await client.database.getUsers(client.id, this); + for (final user in users) { + setState(user); + } + } if (participantListComplete) return getParticipants(); final matrixEvents = await client.api.requestMembers(id); final users = matrixEvents.map((e) => Event.fromMatrixEvent(e, this).asUser).toList(); + for (final user in users) { + setState(user); // at *least* cache this in-memory + } users.removeWhere( (u) => [Membership.leave, Membership.ban].contains(u.membership)); return users; diff --git a/test/room_test.dart b/test/room_test.dart index 590f0ec..b459db5 100644 --- a/test/room_test.dart +++ b/test/room_test.dart @@ -300,6 +300,9 @@ void main() { }); test('getParticipants', () async { + var userList = room.getParticipants(); + expect(userList.length, 4); + // add new user room.setState(Event( senderId: '@alice:test.abc', type: 'm.room.member', @@ -309,9 +312,9 @@ void main() { originServerTs: DateTime.now(), content: {'displayname': 'alice'}, stateKey: '@alice:test.abc')); - final userList = room.getParticipants(); - expect(userList.length, 4); - expect(userList[3].displayName, 'alice'); + userList = room.getParticipants(); + expect(userList.length, 5); + expect(userList[4].displayName, 'alice'); }); test('addToDirectChat', () async {