refactor: Make database null safe
This commit is contained in:
parent
5eb2d22207
commit
1fd40dd186
|
|
@ -29,7 +29,7 @@ import '../../matrix.dart';
|
||||||
abstract class DatabaseApi {
|
abstract class DatabaseApi {
|
||||||
int get maxFileSize => 1 * 1024 * 1024;
|
int get maxFileSize => 1 * 1024 * 1024;
|
||||||
bool get supportsFileStoring => false;
|
bool get supportsFileStoring => false;
|
||||||
Future<Map<String, dynamic>> getClient(String name);
|
Future<Map<String, dynamic>?> getClient(String name);
|
||||||
|
|
||||||
Future updateClient(
|
Future updateClient(
|
||||||
String homeserverUrl,
|
String homeserverUrl,
|
||||||
|
|
@ -66,7 +66,7 @@ abstract class DatabaseApi {
|
||||||
/// [transaction].
|
/// [transaction].
|
||||||
Future<void> storeEventUpdate(int clientId, EventUpdate eventUpdate);
|
Future<void> storeEventUpdate(int clientId, EventUpdate eventUpdate);
|
||||||
|
|
||||||
Future<Event> getEventById(int clientId, String eventId, Room room);
|
Future<Event?> getEventById(int clientId, String eventId, Room room);
|
||||||
|
|
||||||
Future<void> forgetRoom(int clientId, String roomId);
|
Future<void> forgetRoom(int clientId, String roomId);
|
||||||
|
|
||||||
|
|
@ -74,13 +74,13 @@ abstract class DatabaseApi {
|
||||||
|
|
||||||
Future<void> clear(int clientId);
|
Future<void> clear(int clientId);
|
||||||
|
|
||||||
Future<User> getUser(int clientId, String userId, Room room);
|
Future<User?> getUser(int clientId, String userId, Room room);
|
||||||
|
|
||||||
Future<List<User>> getUsers(int clientId, Room room);
|
Future<List<User>> getUsers(int clientId, Room room);
|
||||||
|
|
||||||
Future<List<Event>> getEventList(int clientId, Room room);
|
Future<List<Event>> getEventList(int clientId, Room room);
|
||||||
|
|
||||||
Future<Uint8List> getFile(Uri mxcUri);
|
Future<Uint8List?> getFile(String mxcUri);
|
||||||
|
|
||||||
Future storeFile(Uri mxcUri, Uint8List bytes, int time);
|
Future storeFile(Uri mxcUri, Uint8List bytes, int time);
|
||||||
|
|
||||||
|
|
@ -90,9 +90,9 @@ abstract class DatabaseApi {
|
||||||
|
|
||||||
Future<Map<String, DeviceKeysList>> getUserDeviceKeys(Client client);
|
Future<Map<String, DeviceKeysList>> getUserDeviceKeys(Client client);
|
||||||
|
|
||||||
Future<SSSSCache> getSSSSCache(int clientId, String type);
|
Future<SSSSCache?> getSSSSCache(int clientId, String type);
|
||||||
|
|
||||||
Future<OutboundGroupSession> getOutboundGroupSession(
|
Future<OutboundGroupSession?> getOutboundGroupSession(
|
||||||
int clientId,
|
int clientId,
|
||||||
String roomId,
|
String roomId,
|
||||||
String userId,
|
String userId,
|
||||||
|
|
@ -102,7 +102,7 @@ abstract class DatabaseApi {
|
||||||
int clientId,
|
int clientId,
|
||||||
);
|
);
|
||||||
|
|
||||||
Future<StoredInboundGroupSession> getInboundGroupSession(
|
Future<StoredInboundGroupSession?> getInboundGroupSession(
|
||||||
int clientId,
|
int clientId,
|
||||||
String roomId,
|
String roomId,
|
||||||
String sessionId,
|
String sessionId,
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
// @dart=2.9
|
|
||||||
/*
|
/*
|
||||||
* Famedly Matrix SDK
|
* Famedly Matrix SDK
|
||||||
* Copyright (C) 2019, 2020, 2021 Famedly GmbH
|
* Copyright (C) 2019, 2020, 2021 Famedly GmbH
|
||||||
|
|
@ -39,41 +38,41 @@ import 'package:hive/hive.dart';
|
||||||
class FamedlySdkHiveDatabase extends DatabaseApi {
|
class FamedlySdkHiveDatabase extends DatabaseApi {
|
||||||
static const int version = 3;
|
static const int version = 3;
|
||||||
final String name;
|
final String name;
|
||||||
Box _clientBox;
|
late Box _clientBox;
|
||||||
Box _accountDataBox;
|
late Box _accountDataBox;
|
||||||
Box _roomsBox;
|
late Box _roomsBox;
|
||||||
Box _toDeviceQueueBox;
|
late Box _toDeviceQueueBox;
|
||||||
|
|
||||||
/// Key is a tuple as MultiKey(roomId, type) where stateKey can be
|
/// Key is a tuple as MultiKey(roomId, type) where stateKey can be
|
||||||
/// an empty string.
|
/// an empty string.
|
||||||
LazyBox _roomStateBox;
|
late LazyBox _roomStateBox;
|
||||||
|
|
||||||
/// Key is a tuple as MultiKey(roomId, userId)
|
/// Key is a tuple as MultiKey(roomId, userId)
|
||||||
LazyBox _roomMembersBox;
|
late LazyBox _roomMembersBox;
|
||||||
|
|
||||||
/// Key is a tuple as MultiKey(roomId, type)
|
/// Key is a tuple as MultiKey(roomId, type)
|
||||||
LazyBox _roomAccountDataBox;
|
late LazyBox _roomAccountDataBox;
|
||||||
LazyBox _inboundGroupSessionsBox;
|
late LazyBox _inboundGroupSessionsBox;
|
||||||
LazyBox _outboundGroupSessionsBox;
|
late LazyBox _outboundGroupSessionsBox;
|
||||||
LazyBox _olmSessionsBox;
|
late LazyBox _olmSessionsBox;
|
||||||
|
|
||||||
/// Key is a tuple as MultiKey(userId, deviceId)
|
/// Key is a tuple as MultiKey(userId, deviceId)
|
||||||
LazyBox _userDeviceKeysBox;
|
late LazyBox _userDeviceKeysBox;
|
||||||
|
|
||||||
/// Key is the user ID as a String
|
/// Key is the user ID as a String
|
||||||
LazyBox _userDeviceKeysOutdatedBox;
|
late LazyBox _userDeviceKeysOutdatedBox;
|
||||||
|
|
||||||
/// Key is a tuple as MultiKey(userId, publicKey)
|
/// Key is a tuple as MultiKey(userId, publicKey)
|
||||||
LazyBox _userCrossSigningKeysBox;
|
late LazyBox _userCrossSigningKeysBox;
|
||||||
LazyBox _ssssCacheBox;
|
late LazyBox _ssssCacheBox;
|
||||||
LazyBox _presencesBox;
|
late LazyBox _presencesBox;
|
||||||
|
|
||||||
/// Key is a tuple as Multikey(roomId, fragmentId) while the default
|
/// Key is a tuple as Multikey(roomId, fragmentId) while the default
|
||||||
/// fragmentId is an empty String
|
/// fragmentId is an empty String
|
||||||
LazyBox _timelineFragmentsBox;
|
late LazyBox _timelineFragmentsBox;
|
||||||
|
|
||||||
/// Key is a tuple as MultiKey(roomId, eventId)
|
/// Key is a tuple as MultiKey(roomId, eventId)
|
||||||
LazyBox _eventsBox;
|
late LazyBox _eventsBox;
|
||||||
|
|
||||||
String get _clientBoxName => '$name.box.client';
|
String get _clientBoxName => '$name.box.client';
|
||||||
String get _accountDataBoxName => '$name.box.account_data';
|
String get _accountDataBoxName => '$name.box.account_data';
|
||||||
|
|
@ -95,7 +94,7 @@ class FamedlySdkHiveDatabase extends DatabaseApi {
|
||||||
String get _timelineFragmentsBoxName => '$name.box.timeline_fragments';
|
String get _timelineFragmentsBoxName => '$name.box.timeline_fragments';
|
||||||
String get _eventsBoxName => '$name.box.events';
|
String get _eventsBoxName => '$name.box.events';
|
||||||
|
|
||||||
final HiveCipher encryptionCipher;
|
final HiveCipher? encryptionCipher;
|
||||||
|
|
||||||
FamedlySdkHiveDatabase(this.name, {this.encryptionCipher});
|
FamedlySdkHiveDatabase(this.name, {this.encryptionCipher});
|
||||||
|
|
||||||
|
|
@ -194,7 +193,7 @@ class FamedlySdkHiveDatabase extends DatabaseApi {
|
||||||
);
|
);
|
||||||
|
|
||||||
// Check version and check if we need a migration
|
// Check version and check if we need a migration
|
||||||
final currentVersion = (await _clientBox.get('version') as int);
|
final currentVersion = (await _clientBox.get('version') as int?);
|
||||||
if (currentVersion == null) {
|
if (currentVersion == null) {
|
||||||
await _clientBox.put('version', version);
|
await _clientBox.put('version', version);
|
||||||
} else if (currentVersion != version) {
|
} else if (currentVersion != version) {
|
||||||
|
|
@ -292,7 +291,7 @@ class FamedlySdkHiveDatabase extends DatabaseApi {
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<Map<String, dynamic>> getClient(String name) async {
|
Future<Map<String, dynamic>?> getClient(String name) async {
|
||||||
final map = <String, dynamic>{};
|
final map = <String, dynamic>{};
|
||||||
for (final key in _clientBox.keys) {
|
for (final key in _clientBox.keys) {
|
||||||
if (key == 'version') continue;
|
if (key == 'version') continue;
|
||||||
|
|
@ -303,7 +302,7 @@ class FamedlySdkHiveDatabase extends DatabaseApi {
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<Event> getEventById(int clientId, String eventId, Room room) async {
|
Future<Event?> getEventById(int clientId, String eventId, Room room) async {
|
||||||
final raw = await _eventsBox.get(MultiKey(room.id, eventId).toString());
|
final raw = await _eventsBox.get(MultiKey(room.id, eventId).toString());
|
||||||
if (raw == null) return null;
|
if (raw == null) return null;
|
||||||
return Event.fromJson(convertToJson(raw), room);
|
return Event.fromJson(convertToJson(raw), room);
|
||||||
|
|
@ -329,12 +328,12 @@ class FamedlySdkHiveDatabase extends DatabaseApi {
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<Uint8List> getFile(Uri mxcUri) async {
|
Future<Uint8List?> getFile(String mxcUri) async {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<StoredInboundGroupSession> getInboundGroupSession(
|
Future<StoredInboundGroupSession?> getInboundGroupSession(
|
||||||
int clientId,
|
int clientId,
|
||||||
String roomId,
|
String roomId,
|
||||||
String sessionId,
|
String sessionId,
|
||||||
|
|
@ -374,7 +373,7 @@ class FamedlySdkHiveDatabase extends DatabaseApi {
|
||||||
Future<void> storeOlmSession(int clientId, String identityKey,
|
Future<void> storeOlmSession(int clientId, String identityKey,
|
||||||
String sessionId, String pickle, int lastReceived) async {
|
String sessionId, String pickle, int lastReceived) async {
|
||||||
final rawSessions =
|
final rawSessions =
|
||||||
(await _olmSessionsBox.get(identityKey.toHiveKey) as Map) ?? {};
|
(await _olmSessionsBox.get(identityKey.toHiveKey) as Map?) ?? {};
|
||||||
rawSessions[sessionId] = <String, dynamic>{
|
rawSessions[sessionId] = <String, dynamic>{
|
||||||
'identity_key': identityKey,
|
'identity_key': identityKey,
|
||||||
'pickle': pickle,
|
'pickle': pickle,
|
||||||
|
|
@ -388,8 +387,9 @@ class FamedlySdkHiveDatabase extends DatabaseApi {
|
||||||
@override
|
@override
|
||||||
Future<List<OlmSession>> getOlmSessions(
|
Future<List<OlmSession>> getOlmSessions(
|
||||||
int clientId, String identityKey, String userId) async {
|
int clientId, String identityKey, String userId) async {
|
||||||
final rawSessions = await _olmSessionsBox.get(identityKey.toHiveKey) as Map;
|
final rawSessions =
|
||||||
if (rawSessions?.isEmpty ?? true) return <OlmSession>[];
|
await _olmSessionsBox.get(identityKey.toHiveKey) as Map?;
|
||||||
|
if (rawSessions == null || rawSessions.isEmpty) return <OlmSession>[];
|
||||||
return rawSessions.values
|
return rawSessions.values
|
||||||
.map((json) => OlmSession.fromJson(convertToJson(json), userId))
|
.map((json) => OlmSession.fromJson(convertToJson(json), userId))
|
||||||
.toList();
|
.toList();
|
||||||
|
|
@ -404,7 +404,7 @@ class FamedlySdkHiveDatabase extends DatabaseApi {
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<OutboundGroupSession> getOutboundGroupSession(
|
Future<OutboundGroupSession?> getOutboundGroupSession(
|
||||||
int clientId, String roomId, String userId) async {
|
int clientId, String roomId, String userId) async {
|
||||||
final raw = await _outboundGroupSessionsBox.get(roomId.toHiveKey);
|
final raw = await _outboundGroupSessionsBox.get(roomId.toHiveKey);
|
||||||
if (raw == null) return null;
|
if (raw == null) return null;
|
||||||
|
|
@ -451,8 +451,8 @@ class FamedlySdkHiveDatabase extends DatabaseApi {
|
||||||
// Get the "important" room states. All other states will be loaded once
|
// Get the "important" room states. All other states will be loaded once
|
||||||
// `getUnimportantRoomStates()` is called.
|
// `getUnimportantRoomStates()` is called.
|
||||||
for (final type in importantRoomStates) {
|
for (final type in importantRoomStates) {
|
||||||
final Map states =
|
final states =
|
||||||
await _roomStateBox.get(MultiKey(room.id, type).toString());
|
await _roomStateBox.get(MultiKey(room.id, type).toString()) as Map?;
|
||||||
if (states == null) continue;
|
if (states == null) continue;
|
||||||
final stateEvents = states.values
|
final stateEvents = states.values
|
||||||
.map((raw) => Event.fromJson(convertToJson(raw), room))
|
.map((raw) => Event.fromJson(convertToJson(raw), room))
|
||||||
|
|
@ -474,7 +474,7 @@ class FamedlySdkHiveDatabase extends DatabaseApi {
|
||||||
final basicRoomEvent = BasicRoomEvent.fromJson(
|
final basicRoomEvent = BasicRoomEvent.fromJson(
|
||||||
convertToJson(raw),
|
convertToJson(raw),
|
||||||
);
|
);
|
||||||
rooms[roomId].roomAccountData[basicRoomEvent.type] = basicRoomEvent;
|
rooms[roomId]!.roomAccountData[basicRoomEvent.type] = basicRoomEvent;
|
||||||
} else {
|
} else {
|
||||||
Logs().w('Found account data for unknown room $roomId. Delete now...');
|
Logs().w('Found account data for unknown room $roomId. Delete now...');
|
||||||
await _roomAccountDataBox.delete(key);
|
await _roomAccountDataBox.delete(key);
|
||||||
|
|
@ -485,7 +485,7 @@ class FamedlySdkHiveDatabase extends DatabaseApi {
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<SSSSCache> getSSSSCache(int clientId, String type) async {
|
Future<SSSSCache?> getSSSSCache(int clientId, String type) async {
|
||||||
final raw = await _ssssCacheBox.get(type);
|
final raw = await _ssssCacheBox.get(type);
|
||||||
if (raw == null) return null;
|
if (raw == null) return null;
|
||||||
return SSSSCache.fromJson(convertToJson(raw));
|
return SSSSCache.fromJson(convertToJson(raw));
|
||||||
|
|
@ -517,7 +517,7 @@ class FamedlySdkHiveDatabase extends DatabaseApi {
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<User> getUser(int clientId, String userId, Room room) async {
|
Future<User?> getUser(int clientId, String userId, Room room) async {
|
||||||
final state =
|
final state =
|
||||||
await _roomMembersBox.get(MultiKey(room.id, userId).toString());
|
await _roomMembersBox.get(MultiKey(room.id, userId).toString());
|
||||||
if (state == null) return null;
|
if (state == null) return null;
|
||||||
|
|
@ -734,7 +734,7 @@ class FamedlySdkHiveDatabase extends DatabaseApi {
|
||||||
Future<void> setVerifiedUserCrossSigningKey(
|
Future<void> setVerifiedUserCrossSigningKey(
|
||||||
bool verified, int clientId, String userId, String publicKey) async {
|
bool verified, int clientId, String userId, String publicKey) async {
|
||||||
final raw = (await _userCrossSigningKeysBox
|
final raw = (await _userCrossSigningKeysBox
|
||||||
.get(MultiKey(userId, publicKey).toString()) as Map) ??
|
.get(MultiKey(userId, publicKey).toString()) as Map?) ??
|
||||||
{};
|
{};
|
||||||
raw['verified'] = verified;
|
raw['verified'] = verified;
|
||||||
await _userCrossSigningKeysBox.put(
|
await _userCrossSigningKeysBox.put(
|
||||||
|
|
@ -803,9 +803,10 @@ class FamedlySdkHiveDatabase extends DatabaseApi {
|
||||||
?.tryGet<int>(messageSendingStatusKey) ??
|
?.tryGet<int>(messageSendingStatusKey) ??
|
||||||
2;
|
2;
|
||||||
|
|
||||||
final status = newStatus == -1 || prevEvent?.status == null
|
final status =
|
||||||
? newStatus
|
newStatus == -1 || prevEvent == null || prevEvent.status == null
|
||||||
: max(prevEvent.status, newStatus);
|
? newStatus
|
||||||
|
: max(prevEvent.status, newStatus);
|
||||||
|
|
||||||
// Add the status and the sort order to the content so it get stored
|
// Add the status and the sort order to the content so it get stored
|
||||||
eventUpdate.content['unsigned'] ??= <String, dynamic>{};
|
eventUpdate.content['unsigned'] ??= <String, dynamic>{};
|
||||||
|
|
@ -931,7 +932,7 @@ class FamedlySdkHiveDatabase extends DatabaseApi {
|
||||||
'pickle': pickle,
|
'pickle': pickle,
|
||||||
'device_ids': deviceIds,
|
'device_ids': deviceIds,
|
||||||
'creation_time': creationTime,
|
'creation_time': creationTime,
|
||||||
'sent_messages': sentMessages ?? 0,
|
'sent_messages': sentMessages,
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -944,7 +945,8 @@ class FamedlySdkHiveDatabase extends DatabaseApi {
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> storeRoomUpdate(int clientId, RoomUpdate roomUpdate, [_]) async {
|
Future<void> storeRoomUpdate(int clientId, RoomUpdate roomUpdate,
|
||||||
|
[dynamic _]) async {
|
||||||
// Leave room if membership is leave
|
// Leave room if membership is leave
|
||||||
if ({Membership.leave, Membership.ban}.contains(roomUpdate.membership)) {
|
if ({Membership.leave, Membership.ban}.contains(roomUpdate.membership)) {
|
||||||
await forgetRoom(clientId, roomUpdate.id);
|
await forgetRoom(clientId, roomUpdate.id);
|
||||||
|
|
@ -957,8 +959,8 @@ class FamedlySdkHiveDatabase extends DatabaseApi {
|
||||||
Room(
|
Room(
|
||||||
id: roomUpdate.id,
|
id: roomUpdate.id,
|
||||||
membership: roomUpdate.membership,
|
membership: roomUpdate.membership,
|
||||||
highlightCount: roomUpdate.highlight_count,
|
highlightCount: roomUpdate.highlight_count?.toInt(),
|
||||||
notificationCount: roomUpdate.notification_count,
|
notificationCount: roomUpdate.notification_count?.toInt(),
|
||||||
prev_batch: roomUpdate.prev_batch,
|
prev_batch: roomUpdate.prev_batch,
|
||||||
summary: roomUpdate.summary,
|
summary: roomUpdate.summary,
|
||||||
).toJson());
|
).toJson());
|
||||||
|
|
@ -970,10 +972,10 @@ class FamedlySdkHiveDatabase extends DatabaseApi {
|
||||||
Room(
|
Room(
|
||||||
id: roomUpdate.id,
|
id: roomUpdate.id,
|
||||||
membership: roomUpdate.membership ?? currentRoom.membership,
|
membership: roomUpdate.membership ?? currentRoom.membership,
|
||||||
highlightCount:
|
highlightCount: roomUpdate.highlight_count?.toInt() ??
|
||||||
roomUpdate.highlight_count ?? currentRoom.highlightCount,
|
currentRoom.highlightCount,
|
||||||
notificationCount:
|
notificationCount: roomUpdate.notification_count?.toInt() ??
|
||||||
roomUpdate.notification_count ?? currentRoom.notificationCount,
|
currentRoom.notificationCount,
|
||||||
prev_batch: roomUpdate.prev_batch ?? currentRoom.prev_batch,
|
prev_batch: roomUpdate.prev_batch ?? currentRoom.prev_batch,
|
||||||
summary: RoomSummary.fromJson(currentRoom.summary.toJson()
|
summary: RoomSummary.fromJson(currentRoom.summary.toJson()
|
||||||
..addAll(roomUpdate.summary?.toJson() ?? {})),
|
..addAll(roomUpdate.summary?.toJson() ?? {})),
|
||||||
|
|
@ -1148,7 +1150,7 @@ Map<String, dynamic> convertToJson(Map map) {
|
||||||
|
|
||||||
class MultiKey {
|
class MultiKey {
|
||||||
final List<String> parts;
|
final List<String> parts;
|
||||||
MultiKey(String key1, [String key2, String key3])
|
MultiKey(String key1, [String? key2, String? key3])
|
||||||
: parts = [
|
: parts = [
|
||||||
key1,
|
key1,
|
||||||
if (key2 != null) key2,
|
if (key2 != null) key2,
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue