We're planting a tree for every job application! Click here to learn more

Firebase and Ionic React Chat app (Fire Chat) Part 5: Creating Read receipts

King Somto

5 Nov 2021

•

5 min read

Firebase and Ionic React Chat app (Fire Chat) Part 5:  Creating Read receipts
  • React

Introduction

Chat applications are fun to use they enable us to send messages to other users old and new alike, Our series started at us just building simple react components then progressed to us being able to implement firebase-cloud functions in our application , using firebase-cloud functions we realized that we are able to offload some firebase operations we might have done on the frontend to the backend, this enables to perform some powerful and sensitive operations on the backend examples would be

  • Validate login

  • Validate Signup form

  • Filter friends

  • Perform operations when saving messages

  • Load ChatId

  • Handle payments (if needed)

  • Many more operations

    We set out to build a messaging app using only firebase (as a database) and react, so far we have been able to go from building an app that was similar to a forum app to adding personalized chat messages between individual users to our application, now we would like to add more features to our application to make the application more like WhatsApp, and we are going to start with adding Read receipts just like apps like WhatsApp and Facebook messenger.

Let's get to work

To build this we have to be able to have a flag in every message telling us if the message has been read or not so we can render a tic on the messages sent after they are viewed. Our database would resemble the below image. Screen Shot 2021-10-06 at 1.47.10 AM.png

We have to set the read flag to true whenever a message component has been rendered, ideally, this is meant to be done on the backend, but I think this method is the cleanest considering our current previous implementations also firebase doesn't offer a `onread hook for objects, (so if you're a firebase engineer reading this help a bro out and add that, thanks).

Our approach

Our approach would be to look create a function that is able to find our message object in the chat collection and append a read flag as `true, this can only be done by the user receiving the message, once done it would be rendered by our application, thanks to the way firebase libraries handles database updates

Step 1

Add the Tick component to our project folder To do that download any Tick SVG of your choice and store it in the assets folder, then create an index.js file in that folder to help export the SVG element as a React component.

Paste​​

import {ReactComponent as Tic} from './tic.svg';
 
export {Tic}

Step 2

Edit our messagesBox.jsx component to render the Tick component. Let's start by adding some styling and adding the Tick Component

import React from 'react';
import style from 'styled-components';
import { Tic } from '../assets';
import { db } from '../config/firebase'; 
 
export default function Message({ data, name, chatId }) {
 const { message, id, sender, ...rest } = data;
 
 
 const Message = style.div`
   min-height: 21px;
   max-width: 90%;
   min-width: 50%;
   position: relative;
   width: max-content;
   background: ${sender !== name ? 'pink' : 'blue'};;
   text-align: left;
   padding: 10px;
   border-radius: 10px;
   color: white;
   margin: 15px 0;
   float: ${sender !== name ? 'left' : 'right'};
 
   div {
 
   }
 
   svg{
     height: 15px;
     width: 15px;
     position: absolute;
     color: pink;
     bottom: -7px;
     right: 10px;
     background: white;
     border-radius: 50%;
     padding: 3px;
   }
 
 
   `;
 return <Message><div>
   <p>
   {message}
   </p>
   { seen &&  sender === name &&  <Tic/>}
   </div></Message>;
}
   { seen &&  sender === name &&  <Tic/>}

Here the Tick SVG does not render except if the message has been marked as seen.

Step 3

We pass more logic data into the component so it can make a database call to mark a message as seen. We need to edit the messages.jsx to pass in the chatId into the messageBox component.

export default function Messages({ name }) {
const Messages = style.div`
  padding: 20px;
  height: calc(100% - 64px);
  overflow-y: scroll;
  `;


const [messages, setMessages] = React.useState([]);
const [chatId, setchatId] = React.useState(false);
React.useEffect(() => {
  const receiver = window.location.href.split('/')[4]

  try {
    allFunctions.getChatID({
      userName: receiver
    }).then(({ data }) => {
      const { chatId = '' } = data;
      setchatId(chatId)
      db.ref('chats').child(chatId).on('value', (snapShot) => {
        let chats = [];
        snapShot.forEach((snap) => {


       const dataToShoww =  {
          ...snap.val(),
          id:snap.key
        }
          chats.push(dataToShoww);
        });


        setMessages(chats);
        var element = document.getElementById('messages');
        element.scrollTop = element.scrollHeight - element.clientHeight;
      });

    }).catch((error) => {
      console.log(error)
    })

  } catch (error) {
    console.log(error)
  }

}, []);

return (
  <Messages id='messages' >
    {messages.map((data) => {
      return <Message name={name} data={data} chatId={chatId} />;
    })}
  </Messages>
);
}

Breaking it down

 const { chatId = '' } = data;
       setchatId(chatId)

Here we set the chatId variable to be passed on to the message components after we run the getChatID function. Now we are able to pass all the data to the messageBox.jsx component and perform a function call to mark the message as read.

Step 4

Our approach for this implementation is to mark a message object as seen when we render it on the app, we have only 2 conditions that perform an indication that a message should be marked as seen.

  • This message hasn't been marked as seen
  • And you are the receiver of the message
const [seen, setSeen] = React.useState(rest.seen)
 React.useEffect(() => {
   console.log({data,sender,name})
   if (seen || sender === name) {///sen this guys or am the sender meaning i need a read receipt
      
     return
   }
 
   markAsSeen(id, chatId)
   ///check if seen?
 }, [])
 
 
const markAsSeen = (messageId, chatId) => {
 try {
   console.log({
     messageId,chatId
   })
   //mark the message as read
   const messageeRef = db
     .ref('chats').child(chatId).child(messageId)
 
     console.log({
       messageeRef
     })
 
   messageeRef.update({///update the message using the referece
     seen: true///updates the
   })
 
 } catch (error) {
   console.log(error)
   console.log('Can not update the state of the object');
 }
}

Let's break it down

 React.useEffect(() => {
   console.log({data,sender,name})
   if (seen || sender === name) {///sen this guys or am the sender meaning i need a read receipt
      
     return
   }
 
   markAsSeen(id, chatId)
   ///check if seen?
 }, [])

The markAsSeen function is run in the useEffect function, it checks if the message is marked as seen or if am the sender if any of the conditions are met it calls the return function.

  //mark the message as read
   const messageeRef = db
     .ref('chats').child(chatId).child(messageId)
 
     console.log({
       messageeRef
     })
 
   messageeRef.update({///update the message using the referece
     seen: true///updates the
   })

The code above uses the information passed in the component to create a message ref messageeRef using this reference we are able to update our database by adding a read flag and setting the value of the object to true.

Now we can run our codebase for our frontend and backend if you are not able to remember the commands for the application(frontend or backend) I suggest you check out my previous articles on firebase functions and just set up the frontend app

Now let's look at our output to see what we have.

![Screen Shot 2021-10-29 at 5.11.49 AM.png](https://functionalworks\-backend\-\-prod.s3.amazonaws.com/logos/27e160536cbd5ff908a425ad05be2c8f)
![Screen Shot 2021-10-29 at 5.11.36 AM.png](https://functionalworks\-backend\-\-prod.s3.amazonaws.com/logos/8674c786ef6d31657db67477c460bfa9)
### Conclusion Side by side we can see that we can now see a `Tic` component rendered if our message has been viewed by our recipient.

We do this by updating the message object whenever a message has been rendered on a user's device by passing the chatID and the messageId in our component and making it call firebase to update the chat object.

Moving further, this series has been a steady progression of implementing simple firebase features to be able to achieve or simulate activities we can find on a chat application, the next tutorial would focus on sending other users images and 30-sec videos, and also possibly audio notes. Stay tuned

Did you like this article?

King Somto

Dev

See other articles by King

Related jobs

See all

Title

The company

  • Remote

Title

The company

  • Remote

Title

The company

  • Remote

Title

The company

  • Remote

Related articles

JavaScript Functional Style Made Simple

JavaScript Functional Style Made Simple

Daniel Boros

•

12 Sep 2021

JavaScript Functional Style Made Simple

JavaScript Functional Style Made Simple

Daniel Boros

•

12 Sep 2021

WorksHub

CareersCompaniesSitemapFunctional WorksBlockchain WorksJavaScript WorksAI WorksGolang WorksJava WorksPython WorksRemote Works
hello@works-hub.com

Ground Floor, Verse Building, 18 Brunswick Place, London, N1 6DZ

108 E 16th Street, New York, NY 10003

Subscribe to our newsletter

Join over 111,000 others and get access to exclusive content, job opportunities and more!

© 2024 WorksHub

Privacy PolicyDeveloped by WorksHub