getTimeline method

Future<Timeline> getTimeline({
  1. void onChange(
    1. int index
    )?,
  2. void onRemove(
    1. int index
    )?,
  3. void onInsert(
    1. int insertID
    )?,
  4. void onNewEvent()?,
  5. void onUpdate()?,
  6. String? eventContextId,
})

Creates a timeline from the store. Returns a Timeline object. If you just want to update the whole timeline on every change, use the onUpdate callback. For updating only the parts that have changed, use the onChange, onRemove, onInsert and the onHistoryReceived callbacks. This method can also retrieve the timeline at a specific point by setting the eventContextId

Implementation

Future<Timeline> getTimeline(
    {void Function(int index)? onChange,
    void Function(int index)? onRemove,
    void Function(int insertID)? onInsert,
    void Function()? onNewEvent,
    void Function()? onUpdate,
    String? eventContextId}) async {
  await postLoad();

  List<Event> events;

  if (!isArchived) {
    events = await client.database?.getEventList(
          this,
          limit: defaultHistoryCount,
        ) ??
        <Event>[];
  } else {
    final archive = client.getArchiveRoomFromCache(id);
    events = archive?.timeline.events.toList() ?? [];
    for (var i = 0; i < events.length; i++) {
      // Try to decrypt encrypted events but don't update the database.
      if (encrypted && client.encryptionEnabled) {
        if (events[i].type == EventTypes.Encrypted) {
          events[i] = await client.encryption!.decryptRoomEvent(
            id,
            events[i],
          );
        }
      }
    }
  }

  var chunk = TimelineChunk(events: events);
  // Load the timeline arround eventContextId if set
  if (eventContextId != null) {
    if (!events.any((Event event) => event.eventId == eventContextId)) {
      chunk =
          await getEventContext(eventContextId) ?? TimelineChunk(events: []);
    }
  }

  // Fetch all users from database we have got here.
  if (eventContextId == null) {
    for (final event in events) {
      if (getState(EventTypes.RoomMember, event.senderId) != null) continue;
      final dbUser = await client.database?.getUser(event.senderId, this);
      if (dbUser != null) setState(dbUser);
    }
  }

  // Try again to decrypt encrypted events and update the database.
  if (encrypted && client.encryptionEnabled) {
    // decrypt messages
    for (var i = 0; i < chunk.events.length; i++) {
      if (chunk.events[i].type == EventTypes.Encrypted) {
        if (eventContextId != null) {
          // for the fragmented timeline, we don't cache the decrypted
          //message in the database
          chunk.events[i] = await client.encryption!.decryptRoomEvent(
            id,
            chunk.events[i],
          );
        } else if (client.database != null) {
          // else, we need the database
          await client.database?.transaction(() async {
            for (var i = 0; i < chunk.events.length; i++) {
              if (chunk.events[i].content['can_request_session'] == true) {
                chunk.events[i] = await client.encryption!.decryptRoomEvent(
                  id,
                  chunk.events[i],
                  store: !isArchived,
                  updateType: EventUpdateType.history,
                );
              }
            }
          });
        }
      }
    }
  }

  final timeline = Timeline(
      room: this,
      chunk: chunk,
      onChange: onChange,
      onRemove: onRemove,
      onInsert: onInsert,
      onNewEvent: onNewEvent,
      onUpdate: onUpdate);
  return timeline;
}