refactor: make room nullsafe

This commit is contained in:
Nicolas Werner 2021-10-26 02:25:04 +02:00
parent fb0a84d7b2
commit ebd5bc3d24
No known key found for this signature in database
GPG Key ID: C8D75E610773F2D9
11 changed files with 354 additions and 349 deletions

View File

@ -312,6 +312,7 @@ class Encryption {
roomID: roomId,
type: updateType,
),
client,
);
}
return event;

View File

@ -63,7 +63,8 @@ class KeyManager {
_requestedSessionIds.clear();
for (final room in client.rooms) {
final lastEvent = room.lastEvent;
if (lastEvent.type == EventTypes.Encrypted &&
if (lastEvent != null &&
lastEvent.type == EventTypes.Encrypted &&
lastEvent.content['can_request_session'] == true) {
try {
maybeAutoRequest(room.id, lastEvent.content['session_id'],

View File

@ -316,8 +316,8 @@ class Client extends MatrixApi {
}
for (final room in rooms) {
if (room.membership == Membership.invite &&
room.getState(EventTypes.RoomMember, userID)?.senderId == userId &&
room.getState(EventTypes.RoomMember, userID).content['is_direct'] ==
room.getState(EventTypes.RoomMember, userID!)?.senderId == userId &&
room.getState(EventTypes.RoomMember, userID!)?.content['is_direct'] ==
true) {
return room.id;
}
@ -613,7 +613,7 @@ class Client extends MatrixApi {
if (rooms.isNotEmpty) {
final profileSet = <Profile>{};
for (final room in rooms) {
final user = room.getUserByMXIDSync(userID);
final user = room.getUserByMXIDSync(userID!);
profileSet.add(Profile.fromJson(user.content));
}
if (profileSet.length == 1) return profileSet.first;
@ -1297,7 +1297,7 @@ class Client extends MatrixApi {
final id = entry.key;
final room = entry.value;
await database?.storeRoomUpdate(id, room);
await database?.storeRoomUpdate(id, room, this);
_updateRoomsByRoomUpdate(id, room);
/// Handle now all room events and save them in the database
@ -1377,7 +1377,7 @@ class Client extends MatrixApi {
// there.
if (event['type'] == 'm.receipt') {
var room = getRoomById(id);
room ??= Room(id: id);
room ??= Room(id: id, client: this);
final receiptStateContent =
room.roomAccountData['m.receipt']?.content ?? {};
@ -1455,7 +1455,7 @@ class Client extends MatrixApi {
}
_updateRoomsByEventUpdate(update);
if (type != EventUpdateType.ephemeral) {
await database?.storeEventUpdate(update);
await database?.storeEventUpdate(update, this);
}
if (encryptionEnabled) {
await encryption?.handleEventUpdate(update);
@ -1521,9 +1521,10 @@ class Client extends MatrixApi {
id: roomId,
membership: membership,
prev_batch: chatUpdate.timeline?.prevBatch,
highlightCount: chatUpdate.unreadNotifications?.highlightCount,
highlightCount:
chatUpdate.unreadNotifications?.highlightCount ?? 0,
notificationCount:
chatUpdate.unreadNotifications?.notificationCount,
chatUpdate.unreadNotifications?.notificationCount ?? 0,
summary: chatUpdate.summary,
client: this,
)
@ -1593,10 +1594,10 @@ class Client extends MatrixApi {
} else {
if (stateEvent.type != EventTypes.Message ||
stateEvent.relationshipType != RelationshipTypes.edit ||
stateEvent.relationshipEventId == room.lastEvent.eventId ||
((room.lastEvent.relationshipType == RelationshipTypes.edit &&
stateEvent.relationshipEventId == room.lastEvent?.eventId ||
((room.lastEvent?.relationshipType == RelationshipTypes.edit &&
stateEvent.relationshipEventId ==
room.lastEvent.relationshipEventId))) {
room.lastEvent?.relationshipEventId))) {
room.setState(stateEvent);
}
}

View File

@ -58,11 +58,12 @@ abstract class DatabaseApi {
/// Stores a RoomUpdate object in the database. Must be called inside of
/// [transaction].
Future<void> storeRoomUpdate(String roomId, SyncRoomUpdate roomUpdate);
Future<void> storeRoomUpdate(
String roomId, SyncRoomUpdate roomUpdate, Client client);
/// Stores an EventUpdate object in the database. Must be called inside of
/// [transaction].
Future<void> storeEventUpdate(EventUpdate eventUpdate);
Future<void> storeEventUpdate(EventUpdate eventUpdate, Client client);
Future<Event?> getEventById(String eventId, Room room);
@ -232,6 +233,7 @@ abstract class DatabaseApi {
Future setRoomPrevBatch(
String prevBatch,
String roomId,
Client client,
);
Future resetNotificationCount(String roomId);

View File

@ -518,10 +518,12 @@ class FamedlySdkHiveDatabase extends DatabaseApi {
// We always need the member event for ourself
final membersToPostload = <String>{if (userID != null) userID};
// If the room is a direct chat, those IDs should be there too
if (room.isDirectChat) membersToPostload.add(room.directChatMatrixID);
if (room.isDirectChat)
membersToPostload.add(room.directChatMatrixID!);
// the lastEvent message preview might have an author we need to fetch, if it is a group chat
if (room.getState(EventTypes.Message) != null && !room.isDirectChat) {
membersToPostload.add(room.getState(EventTypes.Message).senderId);
final lastEvent = room.getState(EventTypes.Message);
if (lastEvent != null && !room.isDirectChat) {
membersToPostload.add(lastEvent.senderId);
}
// if the room has no name and no canonical alias, its name is calculated
// based on the heroes of the room
@ -529,7 +531,7 @@ class FamedlySdkHiveDatabase extends DatabaseApi {
room.getState(EventTypes.RoomCanonicalAlias) == null) {
// we don't have a name and no canonical alias, so we'll need to
// post-load the heroes
membersToPostload.addAll(room.summary?.mHeroes ?? []);
membersToPostload.addAll(room.summary.mHeroes ?? []);
}
// Load members
for (final userId in membersToPostload) {
@ -817,10 +819,11 @@ class FamedlySdkHiveDatabase extends DatabaseApi {
}
@override
Future<void> setRoomPrevBatch(String prevBatch, String roomId) async {
Future<void> setRoomPrevBatch(
String prevBatch, String roomId, Client client) async {
final raw = await _roomsBox.get(roomId.toHiveKey);
if (raw == null) return;
final room = Room.fromJson(convertToJson(raw));
final room = Room.fromJson(convertToJson(raw), client);
room.prev_batch = prevBatch;
await _roomsBox.put(roomId.toHiveKey, room.toJson());
return;
@ -861,13 +864,13 @@ class FamedlySdkHiveDatabase extends DatabaseApi {
}
@override
Future<void> storeEventUpdate(EventUpdate eventUpdate) async {
Future<void> storeEventUpdate(EventUpdate eventUpdate, Client client) async {
// Ephemerals should not be stored
if (eventUpdate.type == EventUpdateType.ephemeral) return;
// In case of this is a redaction event
if (eventUpdate.content['type'] == EventTypes.Redaction) {
final tmpRoom = Room(id: eventUpdate.roomID);
final tmpRoom = Room(id: eventUpdate.roomID, client: client);
final event = await getEventById(eventUpdate.content['redacts'], tmpRoom);
if (event != null) {
event.setRedactionEvent(Event.fromJson(eventUpdate.content, tmpRoom));
@ -1077,7 +1080,8 @@ class FamedlySdkHiveDatabase extends DatabaseApi {
}
@override
Future<void> storeRoomUpdate(String roomId, SyncRoomUpdate roomUpdate) async {
Future<void> storeRoomUpdate(
String roomId, SyncRoomUpdate roomUpdate, Client client) async {
// Leave room if membership is leave
if (roomUpdate is LeftRoomUpdate) {
await forgetRoom(roomId);
@ -1094,26 +1098,31 @@ class FamedlySdkHiveDatabase extends DatabaseApi {
roomId.toHiveKey,
roomUpdate is JoinedRoomUpdate
? Room(
client: client,
id: roomId,
membership: membership,
highlightCount:
roomUpdate.unreadNotifications?.highlightCount?.toInt(),
roomUpdate.unreadNotifications?.highlightCount?.toInt() ??
0,
notificationCount: roomUpdate
.unreadNotifications?.notificationCount
?.toInt(),
.unreadNotifications?.notificationCount
?.toInt() ??
0,
prev_batch: roomUpdate.timeline?.prevBatch,
summary: roomUpdate.summary,
).toJson()
: Room(
client: client,
id: roomId,
membership: membership,
).toJson());
} else if (roomUpdate is JoinedRoomUpdate) {
final currentRawRoom = await _roomsBox.get(roomId.toHiveKey);
final currentRoom = Room.fromJson(convertToJson(currentRawRoom));
final currentRoom = Room.fromJson(convertToJson(currentRawRoom), client);
await _roomsBox.put(
roomId.toHiveKey,
Room(
client: client,
id: roomId,
membership: membership,
highlightCount:

View File

@ -74,7 +74,7 @@ class Event extends MatrixEvent {
bool get redacted => redactedBecause != null;
User? get stateKeyUser => room?.getUserByMXIDSync(stateKey);
User? get stateKeyUser => room?.getUserByMXIDSync(stateKey!);
Event({
this.status = defaultStatus,

File diff suppressed because it is too large Load Diff

View File

@ -171,9 +171,10 @@ extension CommandsClientExtension on Client {
});
addCommand('myroomnick', (CommandArgs args) async {
final currentEventJson = args.room
.getState(EventTypes.RoomMember, args.room.client.userID)
.content
.copy();
.getState(EventTypes.RoomMember, args.room.client.userID!)
?.content
.copy() ??
{};
currentEventJson['displayname'] = args.msg;
return await args.room.client.setRoomStateWithKey(
args.room.id,
@ -184,9 +185,10 @@ extension CommandsClientExtension on Client {
});
addCommand('myroomavatar', (CommandArgs args) async {
final currentEventJson = args.room
.getState(EventTypes.RoomMember, args.room.client.userID)
.content
.copy();
.getState(EventTypes.RoomMember, args.room.client.userID!)
?.content
.copy() ??
{};
currentEventJson['avatar_url'] = args.msg;
return await args.room.client.setRoomStateWithKey(
args.room.id,

View File

@ -183,7 +183,7 @@ class PillSyntax extends InlineSyntax {
}
class MentionSyntax extends InlineSyntax {
final String Function(String)? getMention;
final String? Function(String)? getMention;
MentionSyntax(this.getMention) : super(r'(@(?:\[[^\]:]+\]|\w+)(?:#\w+)?)');
@override
@ -206,7 +206,7 @@ class MentionSyntax extends InlineSyntax {
String markdown(
String text, {
Map<String, Map<String, String>> Function()? getEmotePacks,
String Function(String)? getMention,
String? Function(String)? getMention,
}) {
var ret = markdownToHtml(
text,

View File

@ -115,8 +115,9 @@ void testDatabase(
'limited_timeline': false,
'membership': Membership.join,
});
await database.storeRoomUpdate('!testroom', roomUpdate);
final rooms = await database.getRoomList(Client('testclient'));
final client = Client('testclient');
await database.storeRoomUpdate('!testroom', roomUpdate, client);
final rooms = await database.getRoomList(client);
expect(rooms.single.id, '!testroom');
});
test('getRoomList', () async {
@ -124,8 +125,9 @@ void testDatabase(
expect(list.single.id, '!testroom');
});
test('setRoomPrevBatch', () async {
await database.setRoomPrevBatch('1234', '!testroom');
final rooms = await database.getRoomList(Client('testclient'));
final client = Client('testclient');
await database.setRoomPrevBatch('1234', '!testroom', client);
final rooms = await database.getRoomList(client);
expect(rooms.single.prev_batch, '1234');
});
test('forgetRoom', () async {
@ -192,28 +194,28 @@ void testDatabase(
});
test('storeEventUpdate', () async {
await database.storeEventUpdate(
EventUpdate(
roomID: '!testroom:example.com',
type: EventUpdateType.timeline,
content: {
'type': EventTypes.Message,
'content': {
'body': '* edit 3',
'msgtype': 'm.text',
'm.new_content': {
'body': 'edit 3',
EventUpdate(
roomID: '!testroom:example.com',
type: EventUpdateType.timeline,
content: {
'type': EventTypes.Message,
'content': {
'body': '* edit 3',
'msgtype': 'm.text',
'm.new_content': {
'body': 'edit 3',
'msgtype': 'm.text',
},
'm.relates_to': {
'event_id': '\$source',
'rel_type': RelationshipTypes.edit,
},
},
'm.relates_to': {
'event_id': '\$source',
'rel_type': RelationshipTypes.edit,
},
'event_id': '\$event:example.com',
'sender': '@bob:example.org',
},
'event_id': '\$event:example.com',
'sender': '@bob:example.org',
},
),
);
),
Client('testclient'));
});
test('getEventById', () async {
final event = await database.getEventById(

View File

@ -43,7 +43,8 @@ void main() {
});
test('storeEventUpdate', () async {
final database = await getDatabase(null);
final client = Client('testclient');
final database = await getDatabase(client);
// store a simple update
var update = EventUpdate(
type: EventUpdateType.timeline,
@ -56,7 +57,7 @@ void main() {
'sender': '@blah:blubb',
},
);
await database.storeEventUpdate(update);
await database.storeEventUpdate(update, client);
var event = await database.getEventById('\$event-1', room);
expect(event.eventId, '\$event-1');
@ -73,7 +74,7 @@ void main() {
'status': EventStatus.sending.intValue,
},
);
await database.storeEventUpdate(update);
await database.storeEventUpdate(update, client);
event = await database.getEventById('transaction-1', room);
expect(event.eventId, 'transaction-1');
update = EventUpdate(
@ -91,7 +92,7 @@ void main() {
'status': EventStatus.sent.intValue,
},
);
await database.storeEventUpdate(update);
await database.storeEventUpdate(update, client);
event = await database.getEventById('transaction-1', room);
expect(event, null);
event = await database.getEventById('\$event-2', room);
@ -109,7 +110,7 @@ void main() {
'status': EventStatus.sending.intValue,
},
);
await database.storeEventUpdate(update);
await database.storeEventUpdate(update, client);
event = await database.getEventById('\$event-3', room);
expect(event.eventId, '\$event-3');
update = EventUpdate(
@ -127,7 +128,7 @@ void main() {
},
},
);
await database.storeEventUpdate(update);
await database.storeEventUpdate(update, client);
event = await database.getEventById('\$event-3', room);
expect(event.eventId, '\$event-3');
expect(event.status, EventStatus.sent);
@ -147,7 +148,7 @@ void main() {
'status': EventStatus.synced.intValue,
},
);
await database.storeEventUpdate(update);
await database.storeEventUpdate(update, client);
event = await database.getEventById('\$event-4', room);
expect(event.eventId, '\$event-4');
update = EventUpdate(
@ -165,7 +166,7 @@ void main() {
},
},
);
await database.storeEventUpdate(update);
await database.storeEventUpdate(update, client);
event = await database.getEventById('\$event-4', room);
expect(event.eventId, '\$event-4');
expect(event.status, EventStatus.synced);