DEV Community

Enoch Chejieh
Enoch Chejieh

Posted on

How to build a Live Chat in your Web Application using Robin Part 1

Happy People

This article is part of a two-part series on “How to build a Live Chat in your Web Application using Robin”.

Now let’s get started.

Instant gratification and fast-paced decision-making have become the main driving factors that draw user's attention to any modern web application. Live chat is one of those features which offers this to users, A user just needs to type a question, and in a few minutes, they have gotten a response.

Over 70% of B2C and B2B companies use live chat services as part of their customer strategy, and research tells us it delivers the highest customer satisfaction levels.

In this two-part series, I will show you how you can integrate Robin into your web application using Robin's Javascript and Vue SDK. Robin is a chat messaging solution that allows users and developers to leverage its chat API and SDK for building in-app messaging without worrying about implementing complex features.

Prerequisites

To follow along with this tutorial, you should have the following:

  • Any frontend framework of your choice
  • Robin API key
  • A backend server to retrieve data from a database (You can use any of your choice)

For demonstration purposes, the demo application used in this article was built with Next.JS, but you can follow along using any frontend framework of your choice.

CryptoDegen

CryptoDegen is a decentralized analytical tool which allows users to keep track of their digital assets.

You can get your Robin API key from your Robin Account. This will give you the authorization to access Robin features.

Initializing Robin Javascript SDK

To initialize Robin Javascript SDK, you first need to install the SDK into your frontend application.

To install, simply copy and paste the following code into your terminal:

npm install robin.io-js --save
Enter fullscreen mode Exit fullscreen mode

Before you initialize Robin, head over to your Robin account to get your API key, It's recommended you store it in a secure location like in your environment variables, for example.

Once you've stored your API key, you can proceed on to initializing Robin in your application.

Create a new page called src/pages/index.tsx:

// index.tsx

import { useState, useEffect } from 'react'
import Message from '../components/Message'
import { Robin } from 'robin.io-js'

const Home: NextPage = () => {
    const [isLoggedIn, setIsLoggedIn] = useState(false)
    const [userData, setUserData] = useState({} as ObjectType)
    const apiKey = 'NT-XmIzEmWUlsrQYypZOFRlogDFvQUsaEuxMfZf'
    const channel = 'private_chat'
    const [robin, setRobin] = useState(null as Robin | null)

    const initiateRobin: () => void = () => {
    const robinInstance = new Robin(apiKey, true)
    setRobin(robinInstance)
    }

    return ( 
      <Message isLoggedIn={isLoggedIn} robin={robin} channel={channel} userData={userData} />
    )
}

export default Home
Enter fullscreen mode Exit fullscreen mode

Place the initiateRobin function in a useEffect() hook to ensure Robin is initiated as soon as the Dom has loaded.

// index.tsx

useEffect(() => {
   initiateRobin()
 }, [])
Enter fullscreen mode Exit fullscreen mode

Creating a Robin user token

This tutorial mocks the user login process from the frontend to simulate what it would be like to authenticate a real user or create a new one and then assign a Robin user token to that user from a backend server.

Creating a Robin user token on CryptoDegen

Create a method called createUserToken() this is where you would create the robin user token:

const createUserToken: (data: ObjectType) => Promise<string> = async (data: ObjectType) => {
    const response: ObjectType = await robin?.createUserToken({
      meta_data: {
        ...data
      },
    });

    return response.data.user_token
}
Enter fullscreen mode Exit fullscreen mode

Next, create a method called mockUserLogin():

// index.tsx

const mockUserLogin: () => Promise<void> = async () => {
    const userPromise: Promise<ObjectType> = new Promise((resolve, _reject): ObjectType => {
      return setTimeout(async () => {
        const data: ObjectType = {
          first_name: 'Enoch',
          last_name: 'Chejieh',
          username: 'Enoch Chejieh',
          email: 'enoch11@gmail.com'
        } as ObjectType

        data.user_token = await createUserToken(data)

        resolve({ data })
      }, 100)
    })

    const response: ObjectType = await userPromise

    setUserData({ ...userData, ...response.data })

    setIsLoggedIn(true)
  }
Enter fullscreen mode Exit fullscreen mode

Next, create a function called mockUserSignup():

// index.tsx

const mockUserSignup: () => Promise<void> = async () => {
  const userPromise: Promise<ObjectType> = new Promise((resolve, _reject): ObjectType => {
    return setTimeout(async () => {
      const data = {
        first_name: 'Enoch',
        last_name: 'Chejieh',
        username: 'Enoch Chejieh',
        email: 'enoch11@gmail.com'
      } as ObjectType

      data.user_token = await createUserToken(data)

      resolve({ data })
    }, 100)
  })

  const response : ObjectType = await userPromise

  setUserData({ ...userData, ...response.data })

  setIsLoggedIn(true)
}
Enter fullscreen mode Exit fullscreen mode

Next, create a function called mockUserLogout():


// index.tsx

const mockUserLogout = () => {
  setIsLoggedIn(false)
}
Enter fullscreen mode Exit fullscreen mode

You would need to create these functions to simulate the user authentication processes.

Handling events

Robin dispatches a variety of events you can listen to such as user.connect, user.disconnect, new.conversation, message.forward, message.reaction, message.remove.reaction, remove.group.participant, read.reciept, and group.icon.update.

Before you can listen to a dispatched event, we need to establish a connection to Robin's WebSocket.

Create a component called src/components/message.tsx, copy and paste the following code:

// message.tsx

import { useState, useEffect, useRef } from 'react'
import { Robin } from 'robin.io-js'

type ObjectType = Record<string, any>

interface PropTypes { isLoggedIn: boolean, robin: Robin | null, channel: string, userData: ObjectType }

const Message: React.FC<PropTypes> = ({ isLoggedIn, robin, channel, userData }) => {
    const message: any = useRef(null)
    const [isMessagerOpen, setIsMessagerOpen] = useState(false)
    const [connection, setConnection] = useState(null as any)

    const connect: () => void = () => {
      const connectionInstance = robin?.connect(userData?.user_token)

      setConnection(connectionInstance)

      const WebSocket: WebSocket | undefined = connection

       window.onbeforeunload = function () {
         WebSocket?.close()
       }
   }

   return (...)
}

export default Message
Enter fullscreen mode Exit fullscreen mode

The connect() method is what you use to establish a connection to Robin's WebSocket.
Once we have established your WebSocket connection.

Next, you need to handle events. Copy and paste the following code in your src/components/message.tsx Component:

// message.tsx

useEffect(() => {
     if (isLoggedIn) {

       if (connection) {
         connection.onopen = () => {
           robin?.subscribe(channel, connection as WebSocket)
         }

          connection.onmessage = (event: any) => {
          const message = JSON.parse(event.data)

          if (!message.is_event) {
             if (message.conversation_id === conversation._id) {
               setConversationMessages((messages) => [...messages, message])
              }
           } else {
             handleRobinEvents(message)
           }
           }

         connection.onclosed = () => {
           connect()
         }
       } else {
         connect()
       }
    }

}, [isLoggedIn, connection, conversation])

const handleRobinEvents: (message: ObjectType) => void = (message: ObjectType) => {
    switch (message.name) {
      case 'user.connect':
        // Event dispatched when WebSocket connection is established.
        break
      case 'user.disconnect':
        // Event dispatched when the WebSocket connection has been disconnected.
        break
      case 'new.conversation':
        // Event dispatched when a new conversation is created.
        break
      case 'message.forward':
        // Event dispatched when a message is forwarded.
        break
      case 'message.reaction':
        // Event dispatch when message reaction has been added.
        break
      case 'message.remove.reaction':
        // Event dispatched when a message reaction has been removed.
        break
      case 'remove.group.participant':
        // Event dispatched when a group participant has been removed.
        break
      case 'read.reciept':
        // Event dispatched when a message has been read.
        break
      case 'group.icon.update':
        // Event dispatched when a group icon has been updated.
        break
      default:
        break
    }
  }
Enter fullscreen mode Exit fullscreen mode

The Robin method subscribe() is used for subscribing your Robin connection to a channel name. You need to do this to send messages.

Creating a conversation

Once you have established a connection with Robin's WebSocket, you can now proceed to create a conversation.

Creating a conversation on CryptoDegen

Create a function called createConversation() in your src/components/message.tsx component:

// message.tsx

const createConversation: () => Promise<void> = async () => {
    setIsMessagesLoading(true)

    const response = await robin?.createConversation({
      sender_name: userData.username,
      sender_token: userData.user_token,
      receiver_token: receiverToken,
      receiver_name: receiverName
    })

    if (response && !response.error) {
      setConversation({ ...conversation, ...response.data })
    }
}
Enter fullscreen mode Exit fullscreen mode

The Robin method createConversation() takes in an object as a parameter which must contain a sender_name, sender_token, receiver_token, and receiver_name key and value.

Getting conversation messages

To handle retrieving messages from a conversation, create a function called getMessages() in your src/components/message.tsx Component:

// message.tsx

const getMessages: () => Promise<void> = async () => {
    setIsMessagesLoading(true)
    const response = await robin?.getConversationMessages(conversation._id, userData.user_token)
    if (response && !response.error) {
      setIsMessagesLoading(false)
      if (response.data) setConversationMessages((messages) => [...messages, ...response.data])
    }
}
Enter fullscreen mode Exit fullscreen mode

This function is called as soon as the src/components/message.tsx Component is mounted on the Dom and retrieves the messages from the given conversation_id provided.

The Robin method getConversationMessages() takes in two parameters the conversation_id and user_token.

Sending a message to a conversation

Sending a message to a conversation on CryptoDegen

Next, handling sending messages, you need to create a function called sendMessage in your src/components/message.tsx Component:

// message.tsx


const sendMessage: () => Promise<void> = async () => {
    const messageObject: ObjectType = {
      msg: message.current.value,
      sender_token: userData.user_token,
      receiver_token: receiverToken,
      timestamp: new Date()
    }

    await robin?.sendMessageToConversation(
      {
        ...messageObject
      },
      connection,
      channel,
      conversation._id,
      userData.user_token,
      userData.username
    )

    message.current.value = ''
}
Enter fullscreen mode Exit fullscreen mode

The Robin method sendMessageToConversation takes in couple of parameters, which includes message_object, connection, channel, connection_id, user_token, and username.

Sending a message with an attachment to a conversation

Sending a message with an attachment to a conversation on CryptoDegen

Next, handling sending message attachments, you would need to create a function called sendMessageAttachment() in your src/components/message.tsx Component:

// message.tsx

const sendMessageAttachment: (file: File) => void = async (file: File) => {
    await robin?.sendMessageAttachment(userData.user_token, conversation._id, file, userData.username, '')

    message.current.value = ''
}
Enter fullscreen mode Exit fullscreen mode

The Robin method sendMessageAttachment takes in a few parameters, which include user_token, conversation_id, username, and message.

Conclusion

In this part, you’ve learned how to initialize Robin, create conversations, user tokens, get messages, send messages and more.

Robin was instrumental in creating this Live Chat feature on the CryptoDegen application used in this article, as it is integrated easily and helps with customer support.

Robin also provides other APIs which the Javascript SDK utilizes. To view more, check them here.

Robin has a variety of SDK for different frameworks and languages such as Javascript, Vue, Flutter, Go and Python to support the developer’s various needs.

You can get the source code in this repository and view the demo in action.

In the next part, we’ll look at how we can utilize Robin’s Vue SDK to interact with the user messages from the customer's support end.

Top comments (0)