Skip to content

Commit

Permalink
refactor: Use Event instead of EventUpdate for storing in db
Browse files Browse the repository at this point in the history
  • Loading branch information
krille-chan committed Jan 2, 2025
1 parent 7fac151 commit d4091cf
Show file tree
Hide file tree
Showing 14 changed files with 489 additions and 527 deletions.
8 changes: 3 additions & 5 deletions lib/encryption/encryption.dart
Original file line number Diff line number Diff line change
Expand Up @@ -348,11 +348,9 @@ class Encryption {
event.room.setState(event);
}
await client.database?.storeEventUpdate(
EventUpdate(
content: event.toJson(),
roomID: event.room.id,
type: updateType,
),
event.room.id,
event,
EventUpdateType.state,
client,
);
}
Expand Down
42 changes: 29 additions & 13 deletions lib/src/client.dart
Original file line number Diff line number Diff line change
Expand Up @@ -1647,8 +1647,15 @@ class Client extends MatrixApi {
/// the app receives a new synchronization, this event is called for every signal
/// to update the GUI. For example, for a new message, it is called:
/// onRoomEvent( "m.room.message", "!chat_id:server.com", "timeline", {sender: "@bob:server.com", body: "Hello world"} )
// ignore: deprecated_member_use_from_same_package
@Deprecated('Use `onTimelineEvent()` or `onHistoryEvent()` instead.')
final CachedStreamController<EventUpdate> onEvent = CachedStreamController();

final CachedStreamController<Event> onTimelineEvent =
CachedStreamController();

final CachedStreamController<Event> onHistoryEvent = CachedStreamController();

/// The onToDeviceEvent is called when there comes a new to device event. It is
/// already decrypted if necessary.
final CachedStreamController<ToDeviceEvent> onToDeviceEvent =
Expand Down Expand Up @@ -1889,11 +1896,9 @@ class Client extends MatrixApi {
if (storeInDatabase) {
await database?.transaction(() async {
await database.storeEventUpdate(
EventUpdate(
roomID: roomId,
type: EventUpdateType.timeline,
content: event.toJson(),
),
roomId,
event,
EventUpdateType.timeline,
this,
);
});
Expand Down Expand Up @@ -2768,12 +2773,6 @@ class Client extends MatrixApi {
}
}

final update = EventUpdate(
roomID: room.id,
type: type,
content: event.toJson(),
);

// Any kind of member change? We should invalidate the profile then:
if (event.type == EventTypes.RoomMember) {
final userId = event.stateKey;
Expand All @@ -2799,15 +2798,32 @@ class Client extends MatrixApi {
}
_updateRoomsByEventUpdate(room, event, type);
if (store) {
await database?.storeEventUpdate(update, this);
await database?.storeEventUpdate(room.id, event, type, this);
}
if (event is MatrixEvent && encryptionEnabled) {
await encryption?.handleEventUpdate(
Event.fromMatrixEvent(event, room),
type,
);
}
onEvent.add(update);

// ignore: deprecated_member_use_from_same_package
onEvent.add(
// ignore: deprecated_member_use_from_same_package
EventUpdate(
roomID: room.id,
type: type,
content: event.toJson(),
),
);
if (event is MatrixEvent) {
if (type == EventUpdateType.timeline) {
onTimelineEvent.add(Event.fromMatrixEvent(event, room));
}
if (type == EventUpdateType.history) {
onHistoryEvent.add(Event.fromMatrixEvent(event, room));
}
}

if (prevBatch != null &&
(type == EventUpdateType.timeline ||
Expand Down
7 changes: 6 additions & 1 deletion lib/src/database/database_api.dart
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,12 @@ abstract class DatabaseApi {

/// Stores an EventUpdate object in the database. Must be called inside of
/// [transaction].
Future<void> storeEventUpdate(EventUpdate eventUpdate, Client client);
Future<void> storeEventUpdate(
String roomId,
StrippedStateEvent event,
EventUpdateType type,
Client client,
);

Future<Event?> getEventById(String eventId, Room room);

Expand Down
12 changes: 11 additions & 1 deletion lib/src/database/hive_collections_database.dart
Original file line number Diff line number Diff line change
Expand Up @@ -1105,7 +1105,17 @@ class HiveCollectionsDatabase extends DatabaseApi {
}

@override
Future<void> storeEventUpdate(EventUpdate eventUpdate, Client client) async {
Future<void> storeEventUpdate(
String roomId,
StrippedStateEvent event,
EventUpdateType type,
Client client,
) async {
final eventUpdate = EventUpdate(
roomID: roomId,
content: event.toJson(),
type: type,
);
final tmpRoom = client.getRoomById(eventUpdate.roomID) ??
Room(id: eventUpdate.roomID, client: client);

Expand Down
109 changes: 45 additions & 64 deletions lib/src/database/matrix_sdk_database.dart
Original file line number Diff line number Diff line change
Expand Up @@ -1068,45 +1068,37 @@ class MatrixSdkDatabase extends DatabaseApi with DatabaseFileStorage {
}

@override
Future<void> storeEventUpdate(EventUpdate eventUpdate, Client client) async {
final tmpRoom = client.getRoomById(eventUpdate.roomID) ??
Room(id: eventUpdate.roomID, client: client);
Future<void> storeEventUpdate(
String roomId,
StrippedStateEvent event,
EventUpdateType type,
Client client,
) async {
final tmpRoom =
client.getRoomById(roomId) ?? Room(id: roomId, client: client);

// In case of this is a redaction event
if (eventUpdate.content['type'] == EventTypes.Redaction) {
final eventId = eventUpdate.content.tryGet<String>('redacts');
final event =
if (event.type == EventTypes.Redaction && event is MatrixEvent) {
final redactionEvent = Event.fromMatrixEvent(event, tmpRoom);
final eventId = redactionEvent.redacts;
final redactedEvent =
eventId != null ? await getEventById(eventId, tmpRoom) : null;
if (event != null) {
event.setRedactionEvent(Event.fromJson(eventUpdate.content, tmpRoom));
if (redactedEvent != null) {
redactedEvent.setRedactionEvent(redactionEvent);
await _eventsBox.put(
TupleKey(eventUpdate.roomID, event.eventId).toString(),
event.toJson(),
TupleKey(roomId, redactedEvent.eventId).toString(),
redactedEvent.toJson(),
);

if (tmpRoom.lastEvent?.eventId == event.eventId) {
if (client.importantStateEvents.contains(event.type)) {
await _preloadRoomStateBox.put(
TupleKey(eventUpdate.roomID, event.type, '').toString(),
event.toJson(),
);
} else {
await _nonPreloadRoomStateBox.put(
TupleKey(eventUpdate.roomID, event.type, '').toString(),
event.toJson(),
);
}
}
}
}

// Store a common message event
if ({EventUpdateType.timeline, EventUpdateType.history}
.contains(eventUpdate.type)) {
final eventId = eventUpdate.content['event_id'];
if ({EventUpdateType.timeline, EventUpdateType.history}.contains(type) &&
event is MatrixEvent) {
final timelineEvent = Event.fromMatrixEvent(event, tmpRoom);
// Is this ID already in the store?
final prevEvent = await _eventsBox
.get(TupleKey(eventUpdate.roomID, eventId).toString());
final prevEvent =
await _eventsBox.get(TupleKey(roomId, event.eventId).toString());
final prevStatus = prevEvent == null
? null
: () {
Expand All @@ -1119,13 +1111,7 @@ class MatrixSdkDatabase extends DatabaseApi with DatabaseFileStorage {
}();

// calculate the status
final newStatus = eventStatusFromInt(
eventUpdate.content.tryGet<int>('status') ??
eventUpdate.content
.tryGetMap<String, dynamic>('unsigned')
?.tryGet<int>(messageSendingStatusKey) ??
EventStatus.synced.intValue,
);
final newStatus = timelineEvent.status;

// Is this the response to a sending event which is already synced? Then
// there is nothing to do here.
Expand All @@ -1140,29 +1126,25 @@ class MatrixSdkDatabase extends DatabaseApi with DatabaseFileStorage {
newStatus,
);

// Add the status and the sort order to the content so it get stored
eventUpdate.content['unsigned'] ??= <String, dynamic>{};
eventUpdate.content['unsigned'][messageSendingStatusKey] =
eventUpdate.content['status'] = status.intValue;
timelineEvent.status = status;

final eventId = timelineEvent.eventId;
// In case this event has sent from this account we have a transaction ID
final transactionId = eventUpdate.content
.tryGetMap<String, dynamic>('unsigned')
?.tryGet<String>('transaction_id');
final transactionId =
timelineEvent.unsigned?.tryGet<String>('transaction_id');
await _eventsBox.put(
TupleKey(eventUpdate.roomID, eventId).toString(),
eventUpdate.content,
TupleKey(roomId, eventId).toString(),
timelineEvent.toJson(),
);

// Update timeline fragments
final key = TupleKey(eventUpdate.roomID, status.isSent ? '' : 'SENDING')
.toString();
final key = TupleKey(roomId, status.isSent ? '' : 'SENDING').toString();

final eventIds =
List<String>.from(await _timelineFragmentsBox.get(key) ?? []);

if (!eventIds.contains(eventId)) {
if (eventUpdate.type == EventUpdateType.history) {
if (type == EventUpdateType.history) {
eventIds.add(eventId);
} else {
eventIds.insert(0, eventId);
Expand All @@ -1171,15 +1153,15 @@ class MatrixSdkDatabase extends DatabaseApi with DatabaseFileStorage {
} else if (status.isSynced &&
prevStatus != null &&
prevStatus.isSent &&
eventUpdate.type != EventUpdateType.history) {
type != EventUpdateType.history) {
// Status changes from 1 -> 2? Make sure event is correctly sorted.
eventIds.remove(eventId);
eventIds.insert(0, eventId);
}

// If event comes from server timeline, remove sending events with this ID
if (status.isSent) {
final key = TupleKey(eventUpdate.roomID, 'SENDING').toString();
final key = TupleKey(roomId, 'SENDING').toString();
final eventIds =
List<String>.from(await _timelineFragmentsBox.get(key) ?? []);
final i = eventIds.indexWhere((id) => id == eventId);
Expand All @@ -1190,37 +1172,36 @@ class MatrixSdkDatabase extends DatabaseApi with DatabaseFileStorage {

// Is there a transaction id? Then delete the event with this id.
if (!status.isError && !status.isSending && transactionId != null) {
await removeEvent(transactionId, eventUpdate.roomID);
await removeEvent(transactionId, roomId);
}
}

final stateKey = eventUpdate.content['state_key'];
final stateKey = event.stateKey;
// Store a common state event
if (stateKey != null &&
// Don't store events as state updates when paginating backwards.
(eventUpdate.type == EventUpdateType.timeline ||
eventUpdate.type == EventUpdateType.state ||
eventUpdate.type == EventUpdateType.inviteState)) {
if (eventUpdate.content['type'] == EventTypes.RoomMember) {
(type == EventUpdateType.timeline ||
type == EventUpdateType.state ||
type == EventUpdateType.inviteState)) {
if (event.type == EventTypes.RoomMember) {
await _roomMembersBox.put(
TupleKey(
eventUpdate.roomID,
eventUpdate.content['state_key'],
roomId,
stateKey,
).toString(),
eventUpdate.content,
event.toJson(),
);
} else {
final type = eventUpdate.content['type'] as String;
final roomStateBox = client.importantStateEvents.contains(type)
final roomStateBox = client.importantStateEvents.contains(event.type)
? _preloadRoomStateBox
: _nonPreloadRoomStateBox;
final key = TupleKey(
eventUpdate.roomID,
type,
roomId,
event.type,
stateKey,
).toString();

await roomStateBox.put(key, eventUpdate.content);
await roomStateBox.put(key, event.toJson());
}
}
}
Expand Down
2 changes: 2 additions & 0 deletions lib/src/event.dart
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ class Event extends MatrixEvent {
Map<String, dynamic>? unsigned,
Map<String, dynamic>? prevContent,
String? stateKey,
super.redacts,
required this.room,
MatrixEvent? originalSource,
}) : _originalSource = originalSource,
Expand Down Expand Up @@ -212,6 +213,7 @@ class Event extends MatrixEvent {
),
unsigned: unsigned,
room: room,
redacts: jsonPayload['redacts'],
originalSource:
originalSource.isEmpty ? null : MatrixEvent.fromJson(originalSource),
);
Expand Down
16 changes: 6 additions & 10 deletions lib/src/room.dart
Original file line number Diff line number Diff line change
Expand Up @@ -1673,11 +1673,9 @@ class Room {
for (final user in users) {
setState(user); // at *least* cache this in-memory
await client.database?.storeEventUpdate(
EventUpdate(
roomID: id,
type: EventUpdateType.state,
content: user.toJson(),
),
id,
user,
EventUpdateType.state,
client,
);
}
Expand Down Expand Up @@ -1754,11 +1752,9 @@ class Room {
// Store user in database:
await client.database?.transaction(() async {
await client.database?.storeEventUpdate(
EventUpdate(
content: foundUser.toJson(),
roomID: id,
type: EventUpdateType.state,
),
id,
foundUser,
EventUpdateType.state,
client,
);
});
Expand Down
Loading

0 comments on commit d4091cf

Please sign in to comment.