0

I am trying to build an app using FireStore and React JS (Web)

My Firestore database basically has:

  • A collection of ChatRooms ChatRooms
  • Every chat-room has many messages which is a subcollection, for example:

this.db.collection("ChatRooms").doc(phone-number-here).collection("messages")

Also, every chat-room has some client info like first-name, last-name etc, and one that's very important:

lastVisited which is a timestamp (or firestamp whatever)

I figured I would put a React Hook that updates every second the lastVisited field, which means to try to record as accurately as possible on Firestore the last time I left a chat-room.

Based on that, I want to retrieve all the messages for every customer (chat-room) that came in after the last visit,

=> lastVisited field. :)

And show a notification.

I have tried from .onSnapshot listener on the messages subcollection, and a combination of Firestore Transactions but I haven't been lucky. My app is buggy and it keeps showing two, then one, then nothing, back to two, etc, and I am suffering much.

Here's my code!

Please I appreciate ANY help!!!

unread_messages = currentUser => {
    const chatRoomsQuery = this.db.collection("ChatRooms");
    // const messagesQuery = this.db.collection("ChatRooms");

    return chatRoomsQuery.get().then(snapshot => {
      return snapshot.forEach(chatRoom => {
        const mess = chatRoomsQuery
          .doc(chatRoom.id)
          .collection("messages")
          .where("from", "==", chatRoom.id)
          .orderBy("firestamp", "desc")
          .limit(5);
        // the limit of the messages could change to 10 on production
        return mess.onSnapshot(snapshot => {
          console.log("snapshot SIZE: ", snapshot.size);
          return snapshot.forEach(message => {
            // console.log(message.data());
            const chatRef = this.db
              .collection("ChatRooms")
              .doc(message.data().from);

            // run transaction
            return this.db
              .runTransaction(transaction => {
                return transaction.get(chatRef).then(doc => {
                  // console.log("currentUser: ", currentUser);
                  // console.log("doc: ", doc.data());
                  if (!doc.exists) return;

                  if (
                    currentUser !== null &&
                    message.data().from === currentUser.phone
                  ) {
                    // the update it
                    transaction.update(chatRef, {
                      unread_messages: []
                    });
                  }
                  // else
                  else if (
                    new Date(message.data().timestamp).getTime() >
                    new Date(doc.data().lastVisited).getTime()
                  ) {
                    console.log("THIS IS/ARE THE ONES:", message.data());
                    // newMessages.push(message.data().customer_response);

                    // the update it
                    transaction.update(chatRef, {
                      unread_messages: Array.from(
                        new Set([
                          ...doc.data().unread_messages,
                          message.data().customer_response
                        ])
                      )
                    });
                  }
                });
              })
              .then(function() {
                console.log("Transaction successfully committed!");
              })
              .catch(function(error) {
                console.log("Transaction failed: ", error);
              });
          });
        });
      });
    });
  };
try_catch
  • 169
  • 3
  • 12

1 Answers1

2

Searching about it, it seems that the best option for you to achieve that comparison, would be to convert your timestamps in milliseconds, using the method toMillis(). This way, you should be able to compare the results better and easier - more information on the method can be found in the official documentation here - of the timestamps of last message and last access.

I believe this would be your best option as it's mentioned in this Community post here, that this would be the only solution for comparing timestamps on Firestore - there is a method called isEqual(), but it doesn't make sense for your use case.

I would recommend you to give it a try using this to compare the timestamps for your application. Besides that, there is another question from the Community - accessible here: How to compare firebase timestamps? - where the user has a similar use cases and purpose as yours, that I believe might help you with some ideas and thoughts as well.

Let me know if the information helped you!

gso_gabriel
  • 4,199
  • 1
  • 10
  • 22
  • Hi @gso_gabriel, thank you for your answer, sorry it took me so long to respond. I agree in that with you, but my problem is that I haven't find a reliable way to know for how long I'm on a specific chatRoom, and when do I leave a chatRoom – try_catch Mar 30 '20 at 02:10
  • 1
    Hi @waldothedeveloper you will need to create a variable to get the `timestamp` once the `chatRoom` is called or modified, so you can get the time when the room was entered. After that, you will need a method that will log the `timestamp` of when a "logout" occured. You will probably need to have a logout method just for this time registration, so you can calculate the time difference, between the entrance and leave of the chat room. – gso_gabriel Mar 30 '20 at 07:33
  • 1
    Rather than trying to remember when the user logs out, you could also keep track of the last timestamp retrieved from your messages anytime you query your messages, and then set any future queries to retrieve values where `timestamp`, `>`, `lastTimestampRetrieved`. – Todd Kerpelman Mar 31 '20 at 01:20