How can i create a collection for a chat app for flutter

Viewed 169

I am building a part for an app which is a chat app system, but am kinda lost.

The post request code to firebase

FirebaseFirestore.instance
      .collection('messages')
      .doc(user.uid)
      .collection(widget.receiver)
      .add({
    'message': _textEditingController.text,
    'messageType': "sender",
    'receiver': widget.receiver,
    'sender': user.uid,
    'timestamp': DateTime.now()
        .millisecondsSinceEpoch
        .toString(),
  });

To fetch the messages

FirebaseFirestore.instance
    .collection('messages')
    .doc(user.uid)
    .collection(widget.receiver)
    .where('receiver', isEqualTo: widget.receiver)
    .snapshots(),

The message sends, but if i want to retrieve it for one on one use it doesn't display. Am i doing something wrong?

1 Answers

What you are doing wrong is .doc(user.id). You are creating separate documents with separate collections in them for each user. So to get a message from a user, you will need to listen to every user possibly want to message you. I don't know what widget receiver is, are it is a user ID ?

Well, the easiest way to send messages across the whole app will be:

Sending:

FirebaseFirestore.instance
      .collection('messages')
      .add({
    'sender': user.uid,
    'receiver': reciever.uid, // user ID you want to read message
    'message': _textEditingController.text,
    'messageType': "sender", // i dont know why you need this ?
    'created': FieldValue.serverTimestamp(), // I dont know why you called it just timestamp i changed it on created and passed an function with serverTimestamp()
  });

Getting messages:

FirebaseFirestore.instance
    .collection('messages')
    .where('created' ???) // This need to be first if you want to use orderby() method. Question marks for you to solve what need to be there.
    .where('receiver', isEqualTo: user.uid) // This line is important to get any data out of message collection if you won't have it, rules will kick your request.
    .where('sender', isEqualTo: friend.uid) // If you want to get documents only from specific friend.
    .orderBy('created', 'desc') // ordered from newest to latest message.
    .limit(20) // take just 20 documents. Max limit for one request 100 doc.
    .snapshots(),

You will need to make one more request for your messages that you sent to a user and combine conversation in app.

Every one write in one collection so every one need to listen only one collection. This way is OK if you restrict correct access to documents inside the collection using firestore rules.

Rules:

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    match /{document=**} {
      allow read, write: if false;
    }
    match /messages/{messageId} {
      allow create: if request.auth.uid != null
      allow update: if request.auth.uid == resource.data.sender
      allow read: if request.auth.uid == resource.data.sender || request.auth.uid == resource.data.recaiver
    }
  }
}

If you want to have multiple receivers, just make an array out of receivers field and change rules about read operations.

Related