getRoomList method

  1. @override
Future<List<Room>> getRoomList(
  1. Client client
)
override

Implementation

@override
Future<List<Room>> getRoomList(Client client) =>
    runBenchmarked<List<Room>>('Get room list from store', () async {
      final rooms = <String, Room>{};
      final userID = client.userID;

      final rawRooms = await _roomsBox.getAllValues();

      final getRoomStateRequests = <String, Future<List>>{};
      final getRoomMembersRequests = <String, Future<List>>{};

      for (final raw in rawRooms.values) {
        // Get the room
        final room = Room.fromJson(copyMap(raw), client);
        // Get the "important" room states. All other states will be loaded once
        // `getUnimportantRoomStates()` is called.
        final dbKeys = client.importantStateEvents
            .map((state) => TupleKey(room.id, state).toString())
            .toList();
        getRoomStateRequests[room.id] = _roomStateBox.getAll(
          dbKeys,
        );

        // Add to the list and continue.
        rooms[room.id] = room;
      }

      for (final room in rooms.values) {
        // Add states to the room
        final statesList = await getRoomStateRequests[room.id];
        if (statesList != null) {
          for (final states in statesList) {
            if (states == null) continue;
            final stateEvents = states.values
                .map((raw) => room.membership == Membership.invite
                    ? StrippedStateEvent.fromJson(copyMap(raw))
                    : Event.fromJson(copyMap(raw), room))
                .toList();
            for (final state in stateEvents) {
              room.setState(state);
            }
          }

          // now that we have the state we can continue
          final membersToPostload = <String>{if (userID != null) userID};
          // If the room is a direct chat, those IDs should be there too
          if (room.isDirectChat) {
            membersToPostload.add(room.directChatMatrixID!);
          }

          // the lastEvent message preview might have an author we need to fetch, if it is a group chat
          if (room.lastEvent != null && !room.isDirectChat) {
            membersToPostload.add(room.lastEvent!.senderId);
          }

          // if the room has no name and no canonical alias, its name is calculated
          // based on the heroes of the room
          if (room.getState(EventTypes.RoomName) == null &&
              room.getState(EventTypes.RoomCanonicalAlias) == null) {
            // we don't have a name and no canonical alias, so we'll need to
            // post-load the heroes
            final heroes = room.summary.mHeroes;
            if (heroes != null) {
              membersToPostload.addAll(heroes);
            }
          }
          // Load members
          final membersDbKeys = membersToPostload
              .map((member) => TupleKey(room.id, member).toString())
              .toList();
          getRoomMembersRequests[room.id] = _roomMembersBox.getAll(
            membersDbKeys,
          );
        }
      }

      for (final room in rooms.values) {
        // Add members to the room
        final members = await getRoomMembersRequests[room.id];
        if (members != null) {
          for (final member in members) {
            if (member == null) continue;
            room.setState(room.membership == Membership.invite
                ? StrippedStateEvent.fromJson(copyMap(member))
                : Event.fromJson(copyMap(member), room));
          }
        }
      }

      // Get the room account data
      final roomAccountDataRaws = await _roomAccountDataBox.getAllValues();
      for (final entry in roomAccountDataRaws.entries) {
        final keys = TupleKey.fromString(entry.key);
        final basicRoomEvent = BasicRoomEvent.fromJson(
          copyMap(entry.value),
        );
        final roomId = keys.parts.first;
        if (rooms.containsKey(roomId)) {
          rooms[roomId]!.roomAccountData[basicRoomEvent.type] =
              basicRoomEvent;
        } else {
          Logs().w(
              'Found account data for unknown room $roomId. Delete now...');
          await _roomAccountDataBox
              .delete(TupleKey(roomId, basicRoomEvent.type).toString());
        }
      }

      return rooms.values.toList();
    });