From 26261ecd5e9a6c86240ab8f55eeccec536361e34 Mon Sep 17 00:00:00 2001 From: Christian Pauly Date: Tue, 1 Jun 2021 12:54:16 +0200 Subject: [PATCH] feat: Add fromJson method for Room This also included to move the room summary to a dedicated object inside of the Room object because so it is easier to convert this to and from json. --- lib/src/client.dart | 30 ++++------ lib/src/database/database.dart | 19 ++++--- lib/src/room.dart | 79 +++++++++++++++++++-------- test/encryption/key_manager_test.dart | 8 +-- test/room_test.dart | 6 +- 5 files changed, 85 insertions(+), 57 deletions(-) diff --git a/lib/src/client.dart b/lib/src/client.dart index bc70d885..106a7a59 100644 --- a/lib/src/client.dart +++ b/lib/src/client.dart @@ -615,13 +615,13 @@ class Client extends MatrixApi { final id = entry.key; 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)) ?? - {}, - mHeroes: []); + id: id, + membership: Membership.leave, + client: this, + roomAccountData: + room.accountData?.asMap()?.map((k, v) => MapEntry(v.type, v)) ?? + {}, + ); if (room.timeline?.events != null) { for (final event in room.timeline.events) { leftRoom.setState(Event.fromMatrixEvent( @@ -1394,9 +1394,7 @@ class Client extends MatrixApi { prev_batch: chatUpdate.prev_batch, highlightCount: chatUpdate.highlight_count, notificationCount: chatUpdate.notification_count, - mHeroes: chatUpdate.summary?.mHeroes, - mJoinedMemberCount: chatUpdate.summary?.mJoinedMemberCount, - mInvitedMemberCount: chatUpdate.summary?.mInvitedMemberCount, + summary: chatUpdate.summary, roomAccountData: {}, client: this, ); @@ -1420,15 +1418,9 @@ class Client extends MatrixApi { rooms[j].prev_batch = chatUpdate.prev_batch; } if (chatUpdate.summary != null) { - if (chatUpdate.summary.mHeroes != null) { - rooms[j].mHeroes = chatUpdate.summary.mHeroes; - } - if (chatUpdate.summary.mJoinedMemberCount != null) { - rooms[j].mJoinedMemberCount = chatUpdate.summary.mJoinedMemberCount; - } - if (chatUpdate.summary.mInvitedMemberCount != null) { - rooms[j].mInvitedMemberCount = chatUpdate.summary.mInvitedMemberCount; - } + final roomSummaryJson = rooms[j].summary.toJson() + ..addAll(chatUpdate.summary.toJson()); + rooms[j].summary = RoomSummary.fromJson(roomSummaryJson); } if (rooms[j].onUpdate != null) rooms[j].onUpdate.add(rooms[j].id); if (chatUpdate.limitedTimeline && requestHistoryOnLimitedTimeline) { diff --git a/lib/src/database/database.dart b/lib/src/database/database.dart index 471d2850..40d41428 100644 --- a/lib/src/database/database.dart +++ b/lib/src/database/database.dart @@ -311,10 +311,11 @@ class Database extends _$Database implements DatabaseApi { // based on the heroes of the room if (room.getState(api.EventTypes.RoomName) == null && room.getState(api.EventTypes.RoomCanonicalAlias) == null && - room.mHeroes != null) { + room.summary.mHeroes != null) { // we don't have a name and no canonical alias, so we'll need to // post-load the heroes - membersToPostload.addAll(room.mHeroes.where((h) => h.isNotEmpty)); + membersToPostload + .addAll(room.summary.mHeroes.where((h) => h.isNotEmpty)); } // save it for loading later allMembersToPostload[room.id] = membersToPostload; @@ -425,13 +426,13 @@ class Database extends _$Database implements DatabaseApi { oldRoom.membership.toString().split('.').last || (roomUpdate.summary?.mJoinedMemberCount != null && roomUpdate.summary.mJoinedMemberCount != - oldRoom.mInvitedMemberCount) || + oldRoom.summary.mInvitedMemberCount) || (roomUpdate.summary?.mInvitedMemberCount != null && roomUpdate.summary.mJoinedMemberCount != - oldRoom.mJoinedMemberCount) || + oldRoom.summary.mJoinedMemberCount) || (roomUpdate.summary?.mHeroes != null && roomUpdate.summary.mHeroes.join(',') != - oldRoom.mHeroes.join(',')); + oldRoom.summary.mHeroes.join(',')); } if (doUpdate) { @@ -840,9 +841,11 @@ Future getRoomFromTableRow( // TODO: do proper things notificationSettings: 'mention', prev_batch: row.prevBatch, - mInvitedMemberCount: row.invitedMemberCount, - mJoinedMemberCount: row.joinedMemberCount, - mHeroes: row.heroes?.split(',') ?? [], + summary: sdk.RoomSummary.fromJson({ + 'm.heroes': row.heroes?.split(',') ?? [], + 'm.joined_member_count': row.joinedMemberCount, + 'm.invited_member_count': row.invitedMemberCount, + }), client: matrix, roomAccountData: {}, newestSortOrder: row.newestSortOrder, diff --git a/lib/src/room.dart b/lib/src/room.dart index c173c4ea..91bb8941 100644 --- a/lib/src/room.dart +++ b/lib/src/room.dart @@ -71,15 +71,16 @@ class Room { /// A token that can be supplied to the from parameter of the rooms/{roomId}/messages endpoint. String prev_batch; - /// The users which can be used to generate a room name if the room does not have one. - /// Required if the room's m.room.name or m.room.canonical_alias state events are unset or empty. - List mHeroes = []; + RoomSummary summary; - /// The number of users with membership of join, including the client's own user ID. - int mJoinedMemberCount; + @deprecated + List get mHeroes => summary.mHeroes; - /// The number of users with membership of invite. - int mInvitedMemberCount; + @deprecated + int get mJoinedMemberCount => summary.mJoinedMemberCount; + + @deprecated + int get mInvitedMemberCount => summary.mInvitedMemberCount; /// The room states are a key value store of the key (`type`,`state_key`) => State(event). /// In a lot of cases the `state_key` might be an empty string. You **should** use the @@ -95,6 +96,33 @@ class Room { double _newestSortOrder; double _oldestSortOrder; + Map toJson() => { + 'id': id, + 'membership': membership.toString().split('.').last, + 'highlight_count': highlightCount, + 'notification_count': notificationCount, + 'prev_batch': prev_batch, + 'summary': summary.toJson(), + 'newest_sort_order': 0, + 'oldest_sort_order': 0, + }; + + factory Room.fromJson(Map json, [Client client]) => Room( + client: client, + id: json['id'], + membership: Membership.values.singleWhere( + (m) => m.toString() == 'Membership.${json['membership']}', + orElse: () => Membership.join, + ), + notificationCount: json['notification_count'], + highlightCount: json['highlight_count'], + prev_batch: json['prev_batch'], + summary: + RoomSummary.fromJson(Map.from(json['summary'])), + newestSortOrder: json['newest_sort_order'].toDouble(), + oldestSortOrder: json['oldest_sort_order'].toDouble(), + ); + double get newSortOrder { var now = DateTime.now().millisecondsSinceEpoch.toDouble(); if (_newestSortOrder >= now) { @@ -209,7 +237,7 @@ class Room { if ((name?.isEmpty ?? true) && (canonicalAlias?.isEmpty ?? true) && !isDirectChat && - (mHeroes != null && mHeroes.isNotEmpty)) { + (summary.mHeroes != null && summary.mHeroes.isNotEmpty)) { return i18n.groupWith(displayname); } if (displayname?.isNotEmpty ?? false) { @@ -230,10 +258,12 @@ class Room { getState(EventTypes.RoomAvatar).content['url'] is String) { return Uri.tryParse(getState(EventTypes.RoomAvatar).content['url']); } - if (mHeroes != null && - mHeroes.length == 1 && - getState(EventTypes.RoomMember, mHeroes.first) != null) { - return getState(EventTypes.RoomMember, mHeroes.first).asUser.avatarUrl; + if (summary.mHeroes != null && + summary.mHeroes.length == 1 && + getState(EventTypes.RoomMember, summary.mHeroes.first) != null) { + return getState(EventTypes.RoomMember, summary.mHeroes.first) + .asUser + .avatarUrl; } if (membership == Membership.invite && getState(EventTypes.RoomMember, client.userID) != null) { @@ -342,19 +372,22 @@ class Room { String prev_batch, this.client, this.notificationSettings, - this.mHeroes = const [], - int mInvitedMemberCount, - int mJoinedMemberCount, - this.roomAccountData = const {}, + Map roomAccountData, double newestSortOrder = 0.0, double oldestSortOrder = 0.0, + RoomSummary summary, }) : _newestSortOrder = newestSortOrder, _oldestSortOrder = oldestSortOrder, notificationCount = notificationCount ?? 0, highlightCount = highlightCount ?? 0, prev_batch = prev_batch ?? '', - mInvitedMemberCount = mInvitedMemberCount ?? 0, - mJoinedMemberCount = mJoinedMemberCount ?? 0; + roomAccountData = roomAccountData ?? {}, + summary = summary ?? + RoomSummary.fromJson({ + 'm.joined_member_count': 0, + 'm.invited_member_count': 0, + 'm.heroes': [], + }); /// The default count of how much events should be requested when requesting the /// history of this room. @@ -370,10 +403,10 @@ class Room { return canonicalAlias.localpart; } var heroes = []; - if (mHeroes != null && - mHeroes.isNotEmpty && - mHeroes.any((h) => h.isNotEmpty)) { - heroes = mHeroes; + if (summary.mHeroes != null && + summary.mHeroes.isNotEmpty && + summary.mHeroes.any((h) => h.isNotEmpty)) { + heroes = summary.mHeroes; } else { if (states[EventTypes.RoomMember] is Map) { for (final entry in states[EventTypes.RoomMember].entries) { @@ -1163,7 +1196,7 @@ class Room { knownParticipants.removeWhere( (u) => ![Membership.join, Membership.invite].contains(u.membership)); return knownParticipants.length == - (mJoinedMemberCount ?? 0) + (mInvitedMemberCount ?? 0); + (summary.mJoinedMemberCount ?? 0) + (summary.mInvitedMemberCount ?? 0); } /// Returns the [User] object for the given [mxID] or requests it from diff --git a/test/encryption/key_manager_test.dart b/test/encryption/key_manager_test.dart index 96cbc817..b12c5008 100644 --- a/test/encryption/key_manager_test.dart +++ b/test/encryption/key_manager_test.dart @@ -169,13 +169,13 @@ void main() { final room = client.getRoomById(roomId); final member = room.getState('m.room.member', '@alice:example.com'); member.content['membership'] = 'leave'; - room.mJoinedMemberCount--; + room.summary.mJoinedMemberCount--; await client.encryption.keyManager.clearOrUseOutboundGroupSession(roomId); expect( client.encryption.keyManager.getOutboundGroupSession(roomId) != null, false); member.content['membership'] = 'join'; - room.mJoinedMemberCount++; + room.summary.mJoinedMemberCount++; // do not rotate if new device is added sess = @@ -213,11 +213,11 @@ void main() { // do not rotate if new user is added member.content['membership'] = 'leave'; - room.mJoinedMemberCount--; + room.summary.mJoinedMemberCount--; sess = await client.encryption.keyManager.createOutboundGroupSession(roomId); member.content['membership'] = 'join'; - room.mJoinedMemberCount++; + room.summary.mJoinedMemberCount++; await client.encryption.keyManager.clearOrUseOutboundGroupSession(roomId); expect( client.encryption.keyManager.getOutboundGroupSession(roomId) != null, diff --git a/test/room_test.dart b/test/room_test.dart index 92b19796..a946fa54 100644 --- a/test/room_test.dart +++ b/test/room_test.dart @@ -105,9 +105,9 @@ void main() { expect(room.membership, membership); expect(room.notificationCount, notificationCount); expect(room.highlightCount, highlightCount); - expect(room.mJoinedMemberCount, notificationCount); - expect(room.mInvitedMemberCount, notificationCount); - expect(room.mHeroes, heroes); + expect(room.summary.mJoinedMemberCount, notificationCount); + expect(room.summary.mInvitedMemberCount, notificationCount); + expect(room.summary.mHeroes, heroes); expect(room.displayname, 'Alice, Bob, Charley'); expect(room.getState('m.room.join_rules').content['join_rule'], 'public'); expect(room.roomAccountData['com.test.foo'].content['foo'], 'bar');