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.
This commit is contained in:
Christian Pauly 2021-06-01 12:54:16 +02:00
parent 9631cea83a
commit 26261ecd5e
5 changed files with 85 additions and 57 deletions

View File

@ -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)) ??
<String, BasicRoomEvent>{},
mHeroes: []);
id: id,
membership: Membership.leave,
client: this,
roomAccountData:
room.accountData?.asMap()?.map((k, v) => MapEntry(v.type, v)) ??
<String, BasicRoomEvent>{},
);
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) {

View File

@ -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<Room> 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,

View File

@ -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<String> mHeroes = [];
RoomSummary summary;
/// The number of users with membership of join, including the client's own user ID.
int mJoinedMemberCount;
@deprecated
List<String> 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<String, dynamic> 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<String, dynamic> 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<String, dynamic>.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<String, BasicRoomEvent> 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 ?? <String, BasicRoomEvent>{},
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 = <String>[];
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<String, dynamic>) {
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

View File

@ -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,

View File

@ -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');