React Native Video Calling App – Part 4

Welcome to React Native Video Calling App Tutorial part 4. In the previous tutorial we add login and disconnect feature. When any user login, other users were getting notified about new user. Similarly. when any user got disconnected, other users were getting notified about user leaving the chat.

In this part of tutorial, we will add feature of calling. So now, one user will be able to call another user in chat room. Also will put a check, if a user is busy or available for call. So let get going.

First we will change our web client code and our new code will look something like this :

<!DOCTYPE html>
<html>
    <head>
        <title>Web Client</title>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    </head>
    <body>
    <div id="loginContainer">
     <input id="login" value="userA">
     <button onclick="user_login();">Enter Username</button>
   </div>
     <div id="callerIDContainer">
          <input id="callerID" value="userB">
          <button onclick="call_user();">Call User</button>
     </div>
    </body>
    <script src="/socket.io/socket.io.js"></script>
    <script>
      var socket = io();
        let username;
        let busy = false;
        var incallwith = "";

    function user_login(){
            var login = document.getElementById('login').value;
            username = login;
      socket.send({
                     type: "login",
                     name: username
                 })
    }
        function call_user(){
            var callerID = document.getElementById('callerID').value;
          if (callerID == "") {
            alert('Please enter caller ID');
          } else {    
           
var callerIDContainer = document.getElementById('callerIDContainer');
            callerIDContainer.parentElement.removeChild(callerIDContainer);
                busy = true;
                incallwith = callerID
                socket.send({
                 type: "call_user",
                 name: callerID,
                         callername: username
              })
          }
        }
        function onAnswer(data){
        if(busy == false){
            busy = true
            incallwith = data.callername
            var res = confirm(data.callername+" is calling you");
            if(res == true){
                console.log("call accepted");
                // code

                    }else{
                   console.log("call rejected");

                     busy = false
                     incallwith = ""
                 }
             }else{
                 console.log("call busy");

             }
            }

    socket.on('connect', function(data) {
          console.log('connect');
        });
        //when a user logs in
        function onLogin(data) {

             if (data.success === false) {
                    alert("oops...try a different username");
             } else {
                 var loginContainer = document.getElementById('loginContainer');
                 loginContainer.parentElement.removeChild(loginContainer);
                 username = data.username;
                 console.log("Login Successfull");
                 console.log("logged in as :"+username);
                 console.log(data.userlist);
             }
        }
        socket.on('roommessage', function(message){
            var data = message;

            switch(data.type) {
                 case "login":
                        console.log("New user : "+data.username);
                        break;
                 case "disconnect":
                   console.log("User disconnected : "+data.username);
                 break;
                default:
                    break;
            }
        })
    socket.on('message', function(message){
            var data = message;

            switch(data.type) {
                 case "login":
                        onLogin(data);
                        break;
                case "answer":
                      console.log("getting called");
                        onAnswer(data);
                        break;
                default:
                    break;
            }
    })
  </script>
  </html>

In the above code we have added another text box and a button named ‘Call User’. So, when the user will enter any other user’s username and click the button beside it, then ‘call_user’ function will be called. In the call user function we check if user is not clicking the button with blank text box. Then we are setting busy variable is true so that if another user tries to call, they get notification user busy. Next, we are saving the username of user to whom call is being made in ‘incallwith’ variable. Finally, we are sending ‘call_user’ type message to the server so that server can pass it to the user we are calling.

Once the server passes the ‘call_user’ message to another user, control comes to the switch statement ‘answer’ case and ‘onAnswer’ function is called. In onAnswer function the calling users info is passed. In onAnswer function we first check if user is not busy with another user. Then we notify the user that user with username ‘data.callername’ is calling. Now, user can accept or reject the call.

Now lets see what new stuffs are going on in the server side. Following is the updated server side code :

var express = require('express');
var app = express();
var open = require('open');
var serverPort = (4443);
var http = require('http');
var server = http.createServer(app);
var io = require('socket.io')(server);
var sockets = {};
var users = {};
function sendTo(connection, message) {
   connection.send(message);
}

app.get('/', function(req, res){
  console.log('get /');
  res.sendFile(__dirname + '/index.html');
});

io.on('connection', function(socket){
  console.log("user connected");

  socket.on('disconnect', function () {
    console.log("user disconnected");
    if(socket.name){
      socket.broadcast.to("chatroom").emit('roommessage',{ type: "disconnect", username: socket.name})
      delete sockets[socket.name];
      delete users[socket.name];
    }

  })

  socket.on('message', function(message){

    var data = message;

    switch (data.type) {

    case "login":
      console.log("User logged", data.name);

      //if anyone is logged in with this username then refuse
      if(sockets[data.name]) {
         sendTo(socket, {
            type: "login",
            success: false
         });
      } else {
         //save user connection on the server
         var templist = users;
         sockets[data.name] = socket;
         socket.name = data.name;
         sendTo(socket, {
            type: "login",
            success: true,
            username: data.name,
            userlist: templist
         });
         socket.broadcast.to("chatroom").emit('roommessage',{ type: "login", username: data.name})
         socket.join("chatroom");
         users[data.name] = socket.id
      }

      break;
      case "call_user":
      // chek if user exist
        if(sockets[data.name]){
          console.log("user called");
          console.log(data.name);
          console.log(data.callername);
        sendTo(sockets[data.name], {
           type: "answer",
           callername: data.callername
        });
      }else{
        sendTo(socket, {
           type: "call_response",
           response: "offline"
        });
      }
      break;
      default:
      sendTo(socket, {
         type: "error",
         message: "Command not found: " + data.type
      });
      break;
}

  })
})

server.listen(serverPort, function(){
   console.log('server up and running at %s port', serverPort);
 });

In the above code we have added ‘call_user’ case. In this new case we are first checking if the user being called exist in chat room. If the user exist, then we simply pass the ‘answer’ type message to the user being called. If user is not in chat room, then we simple notify the calling user that user being called is offline.

So, in this way we have implemented the calling feature. In next part we will implement user receiving the call and rejecting the call (,  definitely not both at the same time 😉 ). Subscribe to our news-letter to stay tuned for the latest happenings about React Native.

Video Tutorial 

Demo