processRoomUpdates function

Room processRoomUpdates({
  1. required Room serverRoom,
  2. required Room stateRoom,
  3. required bool invite,
})

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;
}