getChatsStream method

  1. @override
Stream<List<ChatModel>> getChatsStream()

Retrieves a stream of chat overviews.

Implementation

@override
Stream<List<ChatModel>> getChatsStream() {
  StreamSubscription? chatSubscription;
  // ignore: close_sinks
  late StreamController<List<ChatModel>> controller;
  controller = StreamController(
    onListen: () async {
      var currentUser = await _userService.getCurrentUser();
      var userSnapshot = _db
          .collection(_options.usersCollectionName)
          .doc(currentUser?.id)
          .collection(_options.userChatsCollectionName)
          .snapshots();

      userSnapshot.listen((event) {
        var chatIds = event.docs.map((e) => e.id).toList();
        var chatSnapshot = _db
            .collection(_options.chatsMetaDataCollectionName)
            .where(
              FieldPath.documentId,
              whereIn: chatIds,
            )
            .withConverter(
              fromFirestore: (snapshot, _) => FirebaseChatDocument.fromJson(
                snapshot.data()!,
                snapshot.id,
              ),
              toFirestore: (chat, _) => chat.toJson(),
            )
            .snapshots();
        var chats = <ChatModel>[];
        ChatModel? chatModel;

        chatSubscription = chatSnapshot.listen((event) async {
          for (var element in event.docChanges) {
            var chat = element.doc.data();
            if (chat == null) return;

            var otherUser = await _userService.getUser(
              chat.users.firstWhere(
                (element) => element != currentUser?.id,
              ),
            );

            var unread =
                await _addUnreadChatSubscription(chat.id!, currentUser!.id!);

            if (chat.personal) {
              chatModel = PersonalChatModel(
                id: chat.id,
                user: otherUser!,
                unreadMessages: unread,
                lastUsed: chat.lastUsed == null
                    ? null
                    : DateTime.fromMillisecondsSinceEpoch(
                        chat.lastUsed!.millisecondsSinceEpoch,
                      ),
                lastMessage: chat.lastMessage != null &&
                        chat.lastMessage!.imageUrl != null
                    ? ChatImageMessageModel(
                        sender: otherUser,
                        imageUrl: chat.lastMessage!.imageUrl!,
                        timestamp: DateTime.fromMillisecondsSinceEpoch(
                          chat.lastMessage!.timestamp.millisecondsSinceEpoch,
                        ),
                      )
                    : chat.lastMessage != null
                        ? ChatTextMessageModel(
                            sender: otherUser,
                            text: chat.lastMessage!.text!,
                            timestamp: DateTime.fromMillisecondsSinceEpoch(
                              chat.lastMessage!.timestamp
                                  .millisecondsSinceEpoch,
                            ),
                          )
                        : null,
              );
            } else {
              var users = <ChatUserModel>[];
              for (var userId in chat.users) {
                var user = await _userService.getUser(userId);
                if (user != null) {
                  users.add(user);
                }
              }
              chatModel = GroupChatModel(
                id: chat.id,
                title: chat.title ?? '',
                imageUrl: chat.imageUrl ?? '',
                unreadMessages: unread,
                users: users,
                lastMessage: chat.lastMessage != null
                    ? chat.lastMessage!.imageUrl == null
                        ? ChatTextMessageModel(
                            sender: otherUser!,
                            text: chat.lastMessage!.text!,
                            timestamp: DateTime.fromMillisecondsSinceEpoch(
                              chat.lastMessage!.timestamp
                                  .millisecondsSinceEpoch,
                            ),
                          )
                        : ChatImageMessageModel(
                            sender: otherUser!,
                            imageUrl: chat.lastMessage!.imageUrl!,
                            timestamp: DateTime.fromMillisecondsSinceEpoch(
                              chat.lastMessage!.timestamp
                                  .millisecondsSinceEpoch,
                            ),
                          )
                    : null,
                canBeDeleted: chat.canBeDeleted,
                lastUsed: chat.lastUsed == null
                    ? null
                    : DateTime.fromMillisecondsSinceEpoch(
                        chat.lastUsed!.millisecondsSinceEpoch,
                      ),
              );
            }
            chats.add(chatModel!);
          }
          var uniqueIds = <String>{};
          var uniqueChatModels = <ChatModel>[];

          for (var chatModel in chats) {
            if (uniqueIds.add(chatModel.id!)) {
              uniqueChatModels.add(chatModel);
            } else {
              var index = uniqueChatModels.indexWhere(
                (element) => element.id == chatModel.id,
              );
              if (index != -1) {
                if (chatModel.lastUsed != null &&
                    uniqueChatModels[index].lastUsed != null) {
                  if (chatModel.lastUsed!
                      .isAfter(uniqueChatModels[index].lastUsed!)) {
                    uniqueChatModels[index] = chatModel;
                  }
                }
              }
            }
          }

          uniqueChatModels.sort(
            (a, b) => (b.lastUsed ?? DateTime.now()).compareTo(
              a.lastUsed ?? DateTime.now(),
            ),
          );

          controller.add(uniqueChatModels);
        });
      });
    },
    onCancel: () async {
      await chatSubscription?.cancel();
    },
  );
  return controller.stream;
}