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