Hi I am creating a chat app with Firestore. I saw a lot of information about creating a badge notification with cloud messaging but not a lot of information with creating a badge notification without cloud message. Does anyone know how to do this? I am trying to show a dot on an icon when a user receives a message that they have not read. It would be even better if I could could the total number of messages that they have not read too.
Firestore Structure
users | ---- chatList (subcollection) ---- chatFrom: user1_Id ---- chatWith: user2_Id ---- chatRoomId: smallerUserID_biggerUserID chatRooms | ---- smallerUserID_biggerUserID (subcollection) ---- content: "Hello" ---- id: 1613422354427 ---- idFrom: user1_Id ---- timestamp: 1613422354427
Getting and Sending a messages in chatRooms Collection
getMessages() { this.listMessage = []; db.collection('chatRooms').doc(this.chatRoomId).collection(this.chatRoomId) .onSnapshot((snapshot) => { snapshot.docChanges().forEach((change) => { if (change.type === 'added') { this.listMessage.push(change.doc.data()); } }); }); }, async sendMessage(content) { if (content.trim() === '') { return } const timestamp = moment().valueOf().toString(); const idFrom = this.authUser.userId; const idTo = this.currentPeerUser.userId; const message = { id: timestamp, idFrom, idTo, timestamp, content }; const chatRoomRef = db.collection('chatRooms').doc(this.chatRoomId) .collection(this.chatRoomId).doc(timestamp); await chatRoomRef.set(message); this.inputValue = ''; },
Advertisement
Answer
As mentioned by @John, a better option would be to have an extra field in your objects that tells if the message has been read or not and it can be done with some simple changes like this to you getMessages()
:
getMessages() { this.listMessage = []; db.collection('chatRooms').doc(this.chatRoomId).collection(this.chatRoomId) .onSnapshot((snapshot) => { snapshot.docChanges().forEach((change) => { if (change.type === 'added') { this.listMessage.push({ isNew: true, message: change.doc.data() }); } }); }); }
You can use isNew to show or not show a newMessage icon and to change it’s value when the message is read you can use Intersection Observer by adding the following to your code:
//options to your observer let options = { root: document.querySelector('#YOUR_ROOT_ELEMENT_HERE'), rootMargin: '0px', threshold: 1.0 } let observer = new IntersectionObserver(callback, options); let target = document.querySelector('#YOUR_TARGET_ELEMENT_HERE'); observer.observe(target); let callback = (entries, observer) => { this.listMessage.forEach(function(messageItem) { messageItem.isNew = false; }); };
In this example YOUR_ROOT_ELEMENT_HERE
will be the parent of your element, I assume in this case it could be a Scroll and YOUR_TARGET_ELEMENT_HERE
will be the unread message. When the intersection happened all messages will be marked as read, but you can refine that logic as you see fit.