getRoomEvents method

Future<int> getRoomEvents({
  1. int historyCount = Room.defaultHistoryCount,
  2. dynamic direction = Direction.b,
  3. StateFilter? filter,
})

Request more previous events from the server. historyCount defines how much events should be received maximum. When the request is answered, onHistoryReceived will be triggered before the historical events will be published in the onEvent stream. filter allows you to specify a StateFilter object to filter the events, which can include various criteria such as event types (e.g., EventTypes.Message) and other state-related filters. The StateFilter object will have lazyLoadMembers set to true by default, but this can be overridden. Returns the actual count of received timeline events.

Implementation

Future<int> getRoomEvents({
  int historyCount = Room.defaultHistoryCount,
  direction = Direction.b,
  StateFilter? filter,
}) async {
  // Ensure stateFilter is not null and set lazyLoadMembers to true if not already set
  filter ??= StateFilter(lazyLoadMembers: true);
  filter.lazyLoadMembers ??= true;

  final resp = await room.client.getRoomEvents(
    room.id,
    direction,
    from: direction == Direction.b ? chunk.prevBatch : chunk.nextBatch,
    limit: historyCount,
    filter: jsonEncode(filter.toJson()),
  );

  if (resp.end == null) {
    Logs().w('We reached the end of the timeline');
  }

  final newNextBatch = direction == Direction.b ? resp.start : resp.end;
  final newPrevBatch = direction == Direction.b ? resp.end : resp.start;

  final type = direction == Direction.b
      ? EventUpdateType.history
      : EventUpdateType.timeline;

  if ((resp.state?.length ?? 0) == 0 &&
      resp.start != resp.end &&
      newPrevBatch != null &&
      newNextBatch != null) {
    if (type == EventUpdateType.history) {
      Logs().w(
        '[nav] we can still request history prevBatch: $type $newPrevBatch',
      );
    } else {
      Logs().w(
        '[nav] we can still request timeline nextBatch: $type $newNextBatch',
      );
    }
  }

  final newEvents =
      resp.chunk.map((e) => Event.fromMatrixEvent(e, room)).toList();

  if (!allowNewEvent) {
    if (resp.start == resp.end ||
        (resp.end == null && direction == Direction.f)) {
      allowNewEvent = true;
    }

    if (allowNewEvent) {
      Logs().d('We now allow sync update into the timeline.');
      newEvents.addAll(
        await room.client.database.getEventList(room, onlySending: true),
      );
    }
  }

  // Try to decrypt encrypted events but don't update the database.
  if (room.encrypted && room.client.encryptionEnabled) {
    for (var i = 0; i < newEvents.length; i++) {
      if (newEvents[i].type == EventTypes.Encrypted) {
        newEvents[i] = await room.client.encryption!.decryptRoomEvent(
          newEvents[i],
        );
      }
    }
  }

  // update chunk anchors
  if (type == EventUpdateType.history) {
    chunk.prevBatch = newPrevBatch ?? '';

    final offset = chunk.events.length;

    chunk.events.addAll(newEvents);

    for (var i = 0; i < newEvents.length; i++) {
      onInsert?.call(i + offset);
    }
  } else {
    chunk.nextBatch = newNextBatch ?? '';
    chunk.events.insertAll(0, newEvents.reversed);

    for (var i = 0; i < newEvents.length; i++) {
      onInsert?.call(i);
    }
  }

  await Future.wait(
    newEvents.where((event) => event.type == PollEventContent.startType).map(
          (event) => fetchAggregatedEvents(
            event.eventId,
            RelationshipTypes.reference,
          ),
        ),
  );

  if (onUpdate != null) {
    onUpdate!();
  }
  return resp.chunk.length;
}