SlimLamie
SlimLamie

Reputation: 61

How to send notification for each incoming message in firebase (React js)?

I have a simple chat webapp where two people can talk to each other. I want them to get notifications when they get a new message. So far I managed to get the permission from the user and also got the token:

const messaging = firebase.messaging();
function InitializeFirebaseMessaging(){
  messaging.requestPermission().then(function(){
    console.log("Notification permission");
    return messaging.getToken();
  }).then(function(token){
    console.log("Token: "+token);
  }).catch(function (reason){
    console.log(reason);
  });
}
messaging.onMessage(function (payload){
  console.log(payload);
});
messaging.onTokenRefresh(function () {
  messaging.getToken()
      .then(function (newtoken) {
          console.log("New Token : "+ newtoken);
      })
      .catch(function (reason) {
          console.log(reason);
      })
});

In the Firestore I have a "pairings" collection where I have paired up users (so only pairs can send messages to each other) and there is a collection for each user with their sent and received messages.

When I log into Firebase, go to Engage/Cloud Messaging, I can send a message to that user from Firebase using the token. How can I achieve sending notifications automatically to the other person for each incoming message?

Upvotes: 0

Views: 1223

Answers (1)

Tarik Huber
Tarik Huber

Reputation: 7388

If you want to send messages automatically you would need to setup a cloud function listener for new messages for each chat. When a new messages is written use that cloud function to send an FCM message to the user receiving the message.

Here is an example how I do it in one of my apps using a RTDB listener:

import * as functions from 'firebase-functions'
import admin from 'firebase-admin'

export default functions
  .region('europe-west1')
  .database.ref('/user_chat_messages/{senderUid}/{receiverUid}/{messageUid}')
  .onCreate(async (eventSnapshot, context) => {
    const { timestamp, params } = context
    const { senderUid, receiverUid, messageUid } = params

    if (context.authType === 'ADMIN') {
      return null
    }

    const snapValues = eventSnapshot.val()
    const {
      message = '',
      link,
      image,
      location,
      audio,
      authorUid,
      created,
      authorPhotoUrl,
    } = snapValues
    let lastMessage = message
    const senderRef = admin.database().ref(`/users/${senderUid}`).once('value')

    const senderSnap = await admin
      .database()
      .ref(`/users/${senderUid}`)
      .once('value')

    const receiverSnap = await admin
      .database()
      .ref(`/users/${receiverUid}`)
      .once('value')

    const {
      displayName: senderName = null,
      photoURL: senderPhoto = null,
    } = senderSnap.val()
    const {
      displayName: receiverName = null,
      photoURL: receiverPhoto = null,
    } = receiverSnap.val()

    if (!message) {
      if (link) {
        lastMessage = 'Link'
      }
      if (image) {
        lastMessage = 'Photo'
      }
      if (location) {
        lastMessage = 'Position'
      }
      if (audio) {
        lastMessage = 'Audio'
      }
    }

    // receiver chat message
    await admin
      .database()
      .ref(`/user_chat_messages/${receiverUid}/${senderUid}/${messageUid}`)
      .update(snapValues)

    // sender chat message
    await admin
      .database()
      .ref(`/user_chat_messages/${senderUid}/${receiverUid}/${messageUid}`)
      .update({
        isSend: timestamp,
      })

    // sender chat
    await admin
      .database()
      .ref(`/user_chats/${senderUid}/${receiverUid}`)
      .update({
        unread: 0,
        displayName: receiverName,
        photoURL: receiverPhoto,
        lastMessage: lastMessage,
        authorUid: senderUid,
        lastCreated: created,
        isSend: timestamp,
        isRead: null,
      })

    // receiver chat
    await admin
      .database()
      .ref(`/user_chats/${receiverUid}/${senderUid}`)
      .update({
        displayName: senderName,
        photoURL: senderPhoto,
        authorUid: senderUid,
        lastMessage: lastMessage,
        lastCreated: created,
        isRead: null,
      })

    // update unread
    await admin
      .database()
      .ref(`/user_chats/${receiverUid}/${senderUid}/unread`)
      .transaction((number) => {
        return (number || 0) + 1
      })

    if (authorUid !== receiverUid) {
      const messages = []

      const payload = {
        notification: {
          title: `${snapValues.authorName}`,
          body: lastMessage,
        },
        webpush: {
          notification: {
            title: `${snapValues.authorName}`,
            body: lastMessage,
            icon: authorPhotoUrl ? authorPhotoUrl : '/apple-touch-icon.png',
            image,
            click_action: `https://www.react-most-wanted.com/chats/${senderUid}`,
          },
        },
        data: {
          test: 'test',
        },
      }

      const tokensSnap = await admin
        .database()
        .ref(`notification_tokens/${receiverUid}`)
        .once('value')

      if (tokensSnap.exists()) {
        tokensSnap.forEach((t) => {
          messages.push({ token: t.key, ...payload })
        })
      }

      await admin.messaging().sendAll(messages)
    }
  })

Upvotes: 1

Related Questions