0

I am working on a chat app using Flutter and Firebase. I am new to Dart and so got stuck when I wanted to create a function which fetches (using await) a particular document from one collection (forums) and use an array property of the forum document to query and return a Stream from another collection (openMessages). The problem with my current solution is that it always returns an empty array. I am sure I am using the keywords or logic incorrectly. Can you please help me refactor my method.

Stream<List<ChatMessage>> getForumChatStream(String forumId) async* {
List<ChatMessage> messages = [];
var docSnap = await firestore.collection('forums').doc(forumId).get();
Forum forum = Forum.fromMap(docSnap.data()!);

firestore
    .collection('openMessages')
    .where('messageId', whereIn: forum.messageIds) 
    .orderBy('timeSent', descending: true)
    .snapshots()
    .map((event) {
        for (var document in event.docs) {
          messages.add(ChatMessage.fromMap(document.data()));
        }
    });
//print('LENGTH:'+messages.length.toString());
yield messages;}
0

1 Answer 1

1

You can use the following method.

  Stream<List<ChatMessage>> getForumChatStream(String forumId) async* {
    final firestore = FirebaseFirestore.instance;
    List<ChatMessage> messages = [];
    var docSnap = await firestore.collection('forums').doc(forumId).get();
    Forum forum = Forum.fromMap(docSnap.data()!);
    final result = firestore
        .collection('openMessages')
        .where('messageId', whereIn: forum.messageIds)
        .orderBy('timeSent', descending: true)
        .snapshots();
    await for (final r in result) {
      final docs = r.docs;
      for (final document in docs) {
        messages.add(ChatMessage.fromMap(document.data()));
        yield messages;
      }
    }
  }

Or

Stream<List<ChatMessage>> getForumChatStream(String forumId) async* {
  final firestore = FirebaseFirestore.instance;
  List<ChatMessage> messages = [];
  var docSnap = await firestore.collection('forums').doc(forumId).get();
  Forum forum = Forum.fromMap(docSnap.data()!);
  yield* firestore
      .collection('openMessages')
      .where('messageId', whereIn: forum.messageIds)
      .orderBy('timeSend', descending: true)
      .snapshots()
      .map((event) =>
          event.docs.map((e) => ChatMessage.fromMap(e.data())).toList());
}
Sign up to request clarification or add additional context in comments.

1 Comment

You also could have taken the output of .snapshots and used the appropriate .map processing to it and returned that as a Stream directly. No need for the async to sync to async round trip.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.