Skip to content

Commit

Permalink
Merge pull request #1992 from famedly/krille/remove-event-update-type
Browse files Browse the repository at this point in the history
refactor: Use Event instead of EventUpdate for storing in db
  • Loading branch information
krille-chan authored Jan 8, 2025
2 parents f2e2ee8 + bc328aa commit b23ad95
Show file tree
Hide file tree
Showing 16 changed files with 594 additions and 578 deletions.
28 changes: 13 additions & 15 deletions lib/encryption/encryption.dart
Original file line number Diff line number Diff line change
Expand Up @@ -154,20 +154,20 @@ class Encryption {
}
}

Future<void> handleEventUpdate(EventUpdate update) async {
if (update.type == EventUpdateType.history) {
Future<void> handleEventUpdate(Event event, EventUpdateType type) async {
if (type == EventUpdateType.history) {
return;
}
if (update.content['type'].startsWith('m.key.verification.') ||
(update.content['type'] == EventTypes.Message &&
(update.content['content']['msgtype'] is String) &&
update.content['content']['msgtype']
.startsWith('m.key.verification.'))) {
if (event.type.startsWith('m.key.verification.') ||
(event.type == EventTypes.Message &&
event.content
.tryGet<String>('msgtype')
?.startsWith('m.key.verification.') ==
true)) {
// "just" key verification, no need to do this in sync
runInRoot(() => keyVerificationManager.handleEventUpdate(update));
runInRoot(() => keyVerificationManager.handleEventUpdate(event));
}
if (update.content['sender'] == client.userID &&
update.content['unsigned']?['transaction_id'] == null) {
if (event.senderId == client.userID && event.status.isSynced) {
// maybe we need to re-try SSSS secrets
runInRoot(() => ssss.periodicallyRequestMissingCache());
}
Expand Down 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,
updateType,
client,
);
}
Expand Down
34 changes: 17 additions & 17 deletions lib/encryption/key_verification_manager.dart
Original file line number Diff line number Diff line change
Expand Up @@ -88,52 +88,52 @@ class KeyVerificationManager {
}
}

Future<void> handleEventUpdate(EventUpdate update) async {
final event = update.content;
final type = event['type'].startsWith('m.key.verification.')
? event['type']
: event['content']['msgtype'];
Future<void> handleEventUpdate(Event update) async {
final type = update.type.startsWith('m.key.verification.')
? update.type
: update.content.tryGet<String>('msgtype');
if (type == null ||
!type.startsWith('m.key.verification.') ||
client.verificationMethods.isEmpty) {
return;
}
if (type == EventTypes.KeyVerificationRequest) {
event['content']['timestamp'] = event['origin_server_ts'];
update.content['timestamp'] =
update.originServerTs.millisecondsSinceEpoch;
}

final transactionId =
KeyVerification.getTransactionId(event['content']) ?? event['event_id'];
KeyVerification.getTransactionId(update.content) ?? update.eventId;

final req = _requests[transactionId];
if (req != null) {
final otherDeviceId = event['content']['from_device'];
if (event['sender'] != client.userID) {
await req.handlePayload(type, event['content'], event['event_id']);
} else if (event['sender'] == client.userID &&
final otherDeviceId = update.content.tryGet<String>('from_device');
if (update.senderId != client.userID) {
await req.handlePayload(type, update.content, update.eventId);
} else if (update.senderId == client.userID &&
otherDeviceId != null &&
otherDeviceId != client.deviceID) {
// okay, another of our devices answered
req.otherDeviceAccepted();
req.dispose();
_requests.remove(transactionId);
}
} else if (event['sender'] != client.userID) {
} else if (update.senderId != client.userID) {
if (!{EventTypes.KeyVerificationRequest, EventTypes.KeyVerificationStart}
.contains(type)) {
return; // we can only start on these
}
final room = client.getRoomById(update.roomID) ??
Room(id: update.roomID, client: client);
final room = client.getRoomById(update.roomId!) ??
Room(id: update.roomId!, client: client);
final newKeyRequest = KeyVerification(
encryption: encryption,
userId: event['sender'],
userId: update.senderId,
room: room,
);
await newKeyRequest.handlePayload(
type,
event['content'],
event['event_id'],
update.content,
update.eventId,
);
if (newKeyRequest.state != KeyVerificationState.askAccept) {
// something went wrong, let's just dispose the request
Expand Down
124 changes: 97 additions & 27 deletions lib/src/client.dart
Original file line number Diff line number Diff line change
Expand Up @@ -1647,8 +1647,28 @@ 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`, `onHistoryEvent` or `onNotification` instead.',
)
final CachedStreamController<EventUpdate> onEvent = CachedStreamController();

/// A stream of all incoming timeline events for all rooms **after**
/// decryption. The events are coming in the same order as they come down from
/// the sync.
final CachedStreamController<Event> onTimelineEvent =
CachedStreamController();

/// A stream for all incoming historical timeline events **after** decryption
/// triggered by a `Room.requestHistory()` call or a method which calls it.
final CachedStreamController<Event> onHistoryEvent = CachedStreamController();

/// A stream of incoming Events **after** decryption which **should** trigger
/// a (local) notification. This includes timeline events but also
/// invite states. Excluded events are those sent by the user themself or
/// not matching the push rules.
final CachedStreamController<Event> onNotification = 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 +1909,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 +2786,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 @@ -2797,23 +2809,70 @@ class Client extends MatrixApi {
room.setState(user);
}
}
_updateRoomsByEventUpdate(room, update);
_updateRoomsByEventUpdate(room, event, type);
if (store) {
await database?.storeEventUpdate(update, this);
await database?.storeEventUpdate(room.id, event, type, this);
}
if (encryptionEnabled) {
await encryption?.handleEventUpdate(update);
if (event is MatrixEvent && encryptionEnabled) {
await encryption?.handleEventUpdate(
Event.fromMatrixEvent(event, room),
type,
);
}

// 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) {
final timelineEvent = Event.fromMatrixEvent(event, room);
switch (type) {
case EventUpdateType.timeline:
onTimelineEvent.add(timelineEvent);
if (prevBatch != null &&
timelineEvent.senderId != userID &&
room.notificationCount > 0 &&
pushruleEvaluator.match(timelineEvent).notify) {
onNotification.add(timelineEvent);
}
break;
case EventUpdateType.history:
onHistoryEvent.add(timelineEvent);
break;
default:
break;
}
}

// Trigger local notification for a new invite:
if (prevBatch != null &&
type == EventUpdateType.inviteState &&
event.type == EventTypes.RoomMember &&
event.stateKey == userID) {
onNotification.add(
Event(
type: event.type,
eventId: 'invite_for_${room.id}',
senderId: event.senderId,
originServerTs: DateTime.now(),
stateKey: event.stateKey,
content: event.content,
room: room,
),
);
}
onEvent.add(update);

if (prevBatch != null &&
(type == EventUpdateType.timeline ||
type == EventUpdateType.decryptedTimelineQueue)) {
if ((update.content
.tryGet<String>('type')
?.startsWith(CallConstants.callEventsRegxp) ??
false)) {
final callEvent = Event.fromJson(update.content, room);
if (event is MatrixEvent &&
(event.type.startsWith(CallConstants.callEventsRegxp))) {
final callEvent = Event.fromMatrixEvent(event, room);
callEvents.add(callEvent);
}
}
Expand Down Expand Up @@ -2913,23 +2972,34 @@ class Client extends MatrixApi {
return room;
}

void _updateRoomsByEventUpdate(Room room, EventUpdate eventUpdate) {
if (eventUpdate.type == EventUpdateType.history) return;
void _updateRoomsByEventUpdate(
Room room,
StrippedStateEvent eventUpdate,
EventUpdateType type,
) {
if (type == EventUpdateType.history) return;

switch (eventUpdate.type) {
switch (type) {
case EventUpdateType.inviteState:
room.setState(StrippedStateEvent.fromJson(eventUpdate.content));
room.setState(eventUpdate);
break;
case EventUpdateType.state:
case EventUpdateType.timeline:
final event = Event.fromJson(eventUpdate.content, room);
if (eventUpdate is! MatrixEvent) {
Logs().wtf(
'Passed in a ${eventUpdate.runtimeType} with $type to _updateRoomsByEventUpdate(). This should never happen!',
);
assert(eventUpdate is! MatrixEvent);
return;
}
final event = Event.fromMatrixEvent(eventUpdate, room);

// Update the room state:
if (event.stateKey != null &&
(!room.partial || importantStateEvents.contains(event.type))) {
room.setState(event);
}
if (eventUpdate.type != EventUpdateType.timeline) break;
if (type != EventUpdateType.timeline) break;

// If last event is null or not a valid room preview event anyway,
// just use this:
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
Loading

0 comments on commit b23ad95

Please sign in to comment.