processRoomUpdates function
Cleans up room updates by removing duplicate events and redacted events
Implementation
Room processRoomUpdates({
required Room serverRoom,
required Room stateRoom,
required bool invite,
}) {
// Extract state events, sort and combine them
final List<Message?> allStateEvents = sortEvents(<Message?>[
...?stateRoom.state?.events,
...?serverRoom.state?.events,
]);
final List<Message?> allTimelineEvents = sortEvents(<Message?>[
...?stateRoom.timeline?.events,
...?serverRoom.timeline?.events
]);
// Extract event IDs used to remove duplicates
final Set<String?> stateEventIDs =
allStateEvents.map((Message? e) => e?.eventID).toSet();
final Set<String?> timelineEventIDs =
allTimelineEvents.map((Message? e) => e?.eventID).toSet();
// Remove duplicate events
allStateEvents.retainWhere((Message? m) => stateEventIDs.remove(m?.eventID));
allTimelineEvents
.retainWhere((Message? m) => timelineEventIDs.remove(m?.eventID));
// Apply Redactions
for (final Message? redactedEvent in allTimelineEvents
.where((Message? m) => m?.eventType == EventTypes.redaction)) {
final String? redactedEventId = redactedEvent?.redacts;
final Message? redactedMessage = allTimelineEvents.firstWhere(
(Message? m) => m?.eventID == redactedEventId,
orElse: () => null,
);
if (redactedMessage != null) {
// Replace the redacted message with a redacted placeholder
allTimelineEvents[allTimelineEvents.indexOf(redactedMessage)] =
redactedMessage.copyWith(
eventType: EventTypes.redaction,
content: redactedEvent?.content,
);
}
}
// Remove redacted events
allStateEvents
.removeWhere((Message? m) => m?.redacts != null && m?.redacts != UNKNOWN);
allTimelineEvents
.removeWhere((Message? m) => m?.redacts != null && m?.redacts != UNKNOWN);
final Room processedRoom = stateRoom.copyWith.call(
invite: invite,
timeline: stateRoom.timeline?.copyWith.call(events: allTimelineEvents),
state: stateRoom.state?.copyWith.call(events: allStateEvents),
name: (serverRoom.name?.isNotEmpty ?? false)
? serverRoom.name
: stateRoom.name,
topic: (serverRoom.topic?.isNotEmpty ?? false)
? serverRoom.topic
: stateRoom.topic,
);
return processedRoom;
}