Node Webkit, Firebase and Ionic Framework – A one to one chat client

This post is part 6 of 7 in the series Node Webkit Apps
Tweet about this on TwitterShare on LinkedIn7Share on Google+0Share on Reddit0Buffer this pageFlattr the authorEmail this to someonePrint this page

A few days ago Pooja Pasupu reached out to me after reading one of my articles on Node webkit named Building a Chat App with node-webkit, Firebase, and AngularJS. In the above article I have shown how to create a desktop based group chat client using Node webkit and Firebase. She wanted to know if we can build a desktop application for one to one chatting like Google talk or Yahoo messenger using node webkit. And this post is a response to that query.

In this post, we are going to build a desktop application that is like your typical one to one chat client. Where, a user logs in, sees a list of other users. And can chat with any of them. This app is called Chatter.

Below is a quick demo of the completed app.

PS : I have opened 2 clients on the same machine to demo the application.

As you can see from the above demo, we have used Firebase as our data store to manage the user’s presence and their chat messages. And also, if you did notice, when User B sent a new message to User A, a new chat window opened automatically, like a typical chat app.

We will take a look at how all the above can be achieved. So, let us get started on building Chatter.

You can find the completed code here.

Prerequisites

We are going to use Node webkit to build the client app, Ionic Framework/Angularjs as the UI framework and Firebase as our data store.

If you are new to Node webkit, check out

If you are new to Angularjs, checkout

If you are new to Firebase, checkout

To get an idea on Node Webkit Firebase Authentication, checkout

To get an Idea on Ionic Framework and Firebase, checkout

Architecture

Our chat client that we are going to build will use Node webkit to build the desktop application, Ionic Framework for the look & feel and Angularjs for the functionality. We will be using Firebase as our real time data store that manages users and their chats.

In a typical chat service, there are 2 major parts.

  • Part I is the user presence
  • Part II is the actual chats

So as soon as a user logs in, a presence server is updated about the User’s status i.e. Online. And the same server is responsible for maintaining the user’s status, say when he goes Away or Idle or Offline. This is the only job of the user presence server.

And when a user in your list of user is online, and you wish to chat with him/her, you will invoke a new chat with the help of the chat server. The chat server keeps a tab on all the users who are in the system and how to reach out to them. Kind of like an address for each client. And when a new chat message comes from user A to user B, it indicates User B to open a new chat window on User B and then start watching for messages on User A.

We are going to implement a similar approach, with one server or rather one data store. Firebase is a super awesome service when it comes to real time messaging. The events and hooks on the data store collections are very real time and we will be taking advantage of this feature to achieve our Chatter app.

To keep things simple, we will be having 2 collections in our data store

  1. Online Users – This will act like the presence server
  2. Chats – This will hold a collection of chats between users

chatterArch

As you can see from the above diagram, as soon as the user logs in, we update the Online user’s list and log him in. And when a new chat is triggered, we will update the chat collection and this trigger the chat on the other client.

This is where it gets tricky. As a desktop client, how do I know when to spawn a new chat window and how do I know with which of the online users I need to establish the connection with.

To solve the above issue, we are using a single collection named chats. And on the desktop client, we will be listening for changes on this collection and whenever there is a sub collection/new chat gets added, we get the name of the sub collection/chat and check if the current desktop client is the target audience and we spawn a new chat window.

This may sound complicated, but when you see the actual implementation it will look a lot easier.

Setup the project

Now that we have an understanding on how the app is going to work, let us get started on implementing it. To scaffold the base for the node webkit app, we will be using a slush generator named slush-wean.

Create a new folder named chatter and open a new terminal/prompt here. First, we will install wean generator globally. Run

npm install --save gulp slush slush-wean

Next, we will scaffold a new node webkit app here. Run

slush wean

Name the project as ChatterThis will take a couple of minutes to setup the app and download its dependencies. Once the dependencies are downloaded, we will run the app.

For the first time when we run the app, it will download the OS specific libs. Execute

gulp run

This process may take up to 5mins depending on your internet connection. Once the download is completed, the app will automatically launch and you should see the below screen.

Screen Shot 2014-11-15 at 4.39.04 pm

Click on the X button on the top right hand corner to close the app.

Below is a quick look at the project structure.

  • app.js : Express server configuration
  • gulpFile.js : Task runner
  • index.html : Application main page/splash screen
  • public folder : static resources (client side – our app will be developed here)
  • routes : Express routes
  • view : Initial view for our Angularjs application, served by Express

We will modify this project to suit our needs. First, we will update the package.json with the dimensions of the App window. The updated packaged.json would look like

The scaffolded project does not have a bower dependency management integrated. We will add that now. Before going further make sure that bower is installed globally ( npm install bower -g ).

From the root of the project run

bower init

Fill in with the default options. Next, create a new file named .bowerrc at the root of the project and update it as below

The above file tells bower where to dump the dependencies. Finally, delete public/lib folder.

To install dependencies, run

bower install --save firebase angularfire ionic firebase-simple-login

When prompted

Select firebase#~2.0.3.

The above step will download a bunch of dependencies and dump it inside the public/libs folder.

Setup Firebase

Next, we need to setup a new Firebase App. Follow the Firebase post mentioned in the prerequisites. Once you have created your Firebase App, we need to enable the Email & Password Authentication so that our users can login via Firebase.

Once you are inside the app’s Forge, click on the Login & Auth tab and Enable the Email & Password Authentication checkbox.

Screen Shot 2014-11-15 at 5.33.44 pm

Continue Development

Now that the base project is setup, we will work on the actual app development.

First, we will update the splash screen. Open index.html present in the root folder and update it as below

Next, we will update the app’s base page. Open views/index.ejs and update it as below

The above file consists of the updated dependencies we have downloaded earlier.

Now, we will update the app.js. The public/js/app.js will consist of the Angular/Ionic init code. Here we will configure a few helper functions and define a few routes. Update app.js as below

Things to notice

Line 1 : We Init a new Angular module, passing in Ionic and Firebase as dependencies.

Line 5 : This is the base Firebase URL for your app. Update it as per your account.

Line 6,7 : Init Firebase simple login

Line 9 :  openchats will consist of the all the chat windows that are open. This will help us when we receive a new incoming message, to check if there is already a conversation window between the incoming user and the current user.

Line 11 : Shows a Modal Dialog

Line 21 : Hides Modal Dialog

Line 25 : Shows a Modal Dialog for 2 seconds and hides it

Line 32 : The logout function. Here we log the user out from the application. And then invoke  offlineUser(). Finally we call the  checkSession() that will take care of redirecting the user.

Line 38 : We Check the state of the User’s auth status and redirect the user appropriately.

Line 62 :  escapeEmailAddress() will be used, when we want to make an Email Address Firebase safe, while naming a sub-collection for our chats.

Line 70 :  getHash() is one of the key functions in our application logic while communicating between users. This function takes in 2 email address, i.e. current logged in user and the user you would like to chat with and return a string that is a constant whenever the above to users are involved. This is the common end point in Firebase chats collection, whenever the above 2 users are involved.

Line 83 : The app routes

Now that the basic app is setup, we will work on our factory. Create a new file named factory.js inside public/js folder. This file will hold 2 factories. Update it as

The GUI service and the Window Service will be used to spawn child windows.

Finally the controllers.js. Create a new file named controllers.js inside public/js folder. This file will consist of the application logic.

Quite a lot of things are happening here.  We have 4 controllers in total. Signup, Login, Home and Chat. As the name suggest, each controller performs one specific task.

Line 1 : Login controller. Responsible for registered user login

Line 36 : Signup controller. Responsible for new user signup

Line 67 : Home controller. Once the user is logged in, s/he will be redirected to the home page where he will see a set of users who are online.

Line 70 : We create a new Firebase instance to the onlineUsers collection.

Line 72  : We sync the data in onlineUsers collection to a local scope variable. This variable will be used to iterate and show a list of users who are online.

Line 75 :  Now, that we have an instance of onlineUsers, we will broadcast our presence so that other users can see us online.

Line 82 :  triggerChat() gets invoked when the current logged in user wants to chat with another user who is online. Here we set the  chatToUser  to be the user, the current logged in user wants to chat to. And then we call the  spawnner()

Line 87 :  spawnner() is responsible for opening a new chat window between the current logged in user and the user you wish to chat with.

Line 88 : Spawn a new child window. The URL of the child window consists of the user you would like to chat with

Line 94 : Once the chat window is successfully loaded, we add the same to the  openchats .

Line 98 : Once the chat window is closed, we need to update   openchats so that if a new chat comes from the same user, we spawn a new chat window again.

Line 110 : When a user logs off, we remove their presence

Line 114 : When a user closes the application window, we remove their presence and close the window. This app does not run in the background

Line 120 : So far we have seen the logic where the current logged in user spawns a new chat. But what if a remote user spawns a chat. How do we update the current user about the intentions of the remote user? – This is how we do it.

We listen to chats collection and watch it for changes.

Line 123 : We watch for 2 events child_added and child_changed. Once we get a notification, we will check if the key variable inside it consists of the logged in user.

Line 124 : If yes, we will get the other user and check if they are already in a conversation with the current user.

Line 128 : If no, we will spawn a new chat window and call the chat controller to take over things.

Line 134 : Chat controller. This controller works with 2 variables.  chatToUser and  loggedInUser.

Line 137 : We create a new Firebase reference to the chats sub collection between the 2 users

Line 138,139 : We sync the values from server and assign it to a scope variable

Line 141 : When a user sends a message, we push it to the same collection.

If needed, spend some time here to understand how the connection between the 2 users happen.

With this we complete the logic part. We will be creating the required partials now.

First delete the head.html from public/partials folder. Create a new file named login.html and inside public/partials folder and update it as below

Next comes the signup.html. Create and update as below

The main home page. home.html

Finally the chat page – chat.html

To clean up some styles, replace the contents of public/css/app.css with below

Save all the files and run the app by executing

gulp run

And you should see the app launch. If you want you can create 2 instance of the same code, run one on port 2000 and other on 3000 as I have done in the demo to test it out.

Hope this post gave you an understanding on how you can Integrate Node webkit with Ionic Framework as well as Firebase and build a private one to one chat application.


Thanks for reading! Do comment.
@arvindr21

Series Navigation<< Node-Webkit File Player – A File player for your desktopNode-Webkit, WebRTC and Angularjs – A Video Chat Client >>
Tweet about this on TwitterShare on LinkedIn7Share on Google+0Share on Reddit0Buffer this pageFlattr the authorEmail this to someonePrint this page
  • http://salirconhijos.com Abel Caballero Díaz

    Hi!

    Just discovered your tutorial and loved it. I’m wondering how would you manage it if to let a user only chat with his/her friends and not with any other user logged in. And to make it more difficult, if user can sign up with different methods (email and facebook, at least).

    Thanks again!
    Abel

  • Morgan Ikponmwosa

    hi thanks for the tutorial, i want to build something similar like this but i want to do it using ionic framework. Please can you help with that?

  • a7medo778

    mmmm that sound awesome
    if i may ask, where can i find good hybrid + firebase freelancers ? i got a project that uses 80% of the work here but with a twist

  • Sam Benoli

    Hello!

    Thanks a lot for this tutorial it is really useful! I end up here actually by searching for a way to build a “whatsapp” app for mobile (like you are doing in this tutorial) using Ionic and Firebase. Unfortunately I juste started learning and I don’t find a way to adapt this tutorial to my purpose. May I ask you if you would be able to make a tutorial to build a similar chat application for mobile using Ionic and Firebase (so without the node webkit)?

    Thanks!

    • / Arvind Ravulavaru
      • Sam Benoli

        Thanks! I will!

      • Sam Benoli

        Hey Arvind,

        I’ve worked a little bit on the link that you gave me. However, I still have an issue. In the code, you work a lot with the user email but the email is not returned when logging with google! Therefore nothing works from that point on. I have tried to change the code using the user’s id instead of the user’s email but I have some issue because there are some part of the code that are not clear to me (beginner). For example, I do not understand what the getHash() function does.

        If you have some time to explain or some idea to help make the change from email to user, I’ll be glad to hear it.

        Thank you!

  • Darshan Choudhary

    First of all thanks for the tutorial.!

    I have created a new app in firebase and changed the url in app.js as well but for some reason I am not able to see any online users…I am sure user gets logged in as their session is set perfectly.

    please any help will be appreciated

    • / Arvind Ravulavaru

      Can you check the Firebase forge and try logging the required information in the console? See if there are any errors?

  • Saurav Panda

    Thanks a lot for such nice and descriptive tutorial. As there is no end for acquiring knowledge, I have a request for you for a new tutorial. Can a video chat application be created using node webkit and webrtc ? if yes, can I extend this project to achieve what I am planning to do? I have limited knowledge of all the topics used in this project and I need your expert advice before venturing out on such journey.

  • Gurtej SIngh

    Thanks Arvind for posting a useful tutorial,I’m not familiar with anularJs and ionic,Can you guide me another way for chatting in phonegap application in detail.

    • / Arvind Ravulavaru

      Hello Gurtej, Thanks!. What other framework would you like to use to achieve the UI layer?

  • Pooja.P

    Please can you tell me the variable that can handle all the registered users so that i can sepearate registered users from online users on the nwk app.
    Thanks.

    • / Arvind Ravulavaru

      I don’t think so you can. Take a look at this : http://stackoverflow.com/a/14676121/1015046

      But the alternative is to explicitly add the registered users to a collection after they have been successfully registered. Take a look at : https://www.firebase.com/docs/web/guide/user-auth.html#section-storing

      Upon successful registration, you can

      This will add the new users to a collection named users

      Thanks.

    • Pooja.P

      thanks for the idea..

  • Pooja.P

    Thanks a lot for the tutorial 😀

    • / Arvind Ravulavaru

      No problem!

  • Tolga Yaramis

    Very nice tutorial again.
    I also would like to implement similar application using Parse.com + Firebase + Ionic Framework.
    Actually “FireChat” provides already everything to implement a good chat application, however it has a dependecy to JQuery which I don’t want to use in an ionic application.

    Do you think about enhancing your chatter application with the FireChat API methods?

    https://firechat.firebaseapp.com/docs/#api

    • / Arvind Ravulavaru

      Thanks @tolgayaramis:disqus.

      If I understood your question correctly, you want to build a hybrid mobile app using Ionic Framework and Firechat API? And want to manage the same using Parse.com?

      May I ask why parse.com?

      Thanks.

      • Tolga Yaramis

        The application that I built so far is using parse.com as a BaaS and now I would like to implement the chat module using FireBase. That means, the user and the other data will be persisted in parse.com, but the rest (chat) will be done in FireBase.

        Of course, everyhing can be done in FireBase as well but in that case I need to change my existing code and especially queries which are different between those 2 platforms.

        Secondly, since I use on both platforms the free account, it is also good (at least for now) to split the network traffic in 2 services.

        As I understood, it is not possible to use FireChat API (service) without referencing jQuery. I am also using IonicFramework and I do not want to load the heavy Jquery library in an ionic application, because the chat UI will be different I do not want to use FireChat UI in my ionic application.

        On the other hand, the existing FireChat API Methods like InviteUser, accept / decline Invite etc. are the methods that I also need.

        What is your opinion for that case?

        Thanks

        • / Arvind Ravulavaru

          Thanks for sharing your thoughts Tolga. What you have mentioned makes total sense, splitting the traffic does help, because all you chat request go to Firebase directly from your mobile app.

          But having 2 services is my concern, when you start bringing in new features to your app. In that case, you need to make sure all your new features are tagged to parse.com and not split between Firebase and Parse. Otherwise the application will become highly unmanageable.

          It is totally possible to implement the Firechat API using Ionic. If you want I can make a tutorial on that. But it would take a week or so as I have already a few in pipeline.

          Thanks.

          • Tolga Yaramis

            You are right. Using 2 BaaS services can be difficult to manage, if the application is a large size application. Currently, it is not the case for my application and may be only the real dynamic parts will be located in FireBase and the rest stays in parse.

            A tutorial regarding to FireChat API would be great and I think it will also be usefull for the other ionic developers, since I see similar questions in ionic forum. I can wait for that :)

            Thanks again.

          • / Arvind Ravulavaru

            You got it! Will let you know once done.

          • http://conceptoman.blogspot.com/ nilesh

            Hi Arvind,
            Did u finish writing that article about how to use firechat API in ionic app with custom UI?
            can u please profile me the url.

          • / Arvind Ravulavaru

            Hello nilesh, Unfortunately, I did not get enough time to finish this. Not sure when I will be trying this out again.

          • / Arvind Ravulavaru

            @tolgayaramis:disqus There is one small issue here. I can expose the Firechat base API as a service, but the UI layer on top of cannot be made angular generic. That needs to be specific to the platform you are writing your UI on. Like Bootstrap or Ionic or Onsen UI and so on..

            The example I am working on will be Firechat API as an Angular service with some minor tweaks and a UI built with Ionic.

            Does this help?

          • Tolga Yaramis

            This is perfectly fine, since I also use IonicFramework and do not want to FireChat UI layer which is done by JQuery..

          • / Arvind Ravulavaru

            Great! Thanks!

          • Tolga Yaramis

            I thank you for your support and the greate articles that you write..

          • / Arvind Ravulavaru

            Not an issue. Thanks Tolga!

  • jaybaker1968

    Great post/tutorial as always.
    When I select the login button nothing happens. Obviously I have wired up something incorrectly. What is the best way to debug? Is there a way that I can get printf style debugging with console.out or something like that?

    • / Arvind Ravulavaru

      Thanks @jaybaker1968:disqus

      To debug node webkit apps, you can set toolbar property to true in the package.json.

      Now, if you kill the app and restart it again, you will see a toolbar. And next to the toolbar you will find a gear icon, which will open webkit dev tools. You can set breakpoints or throw in debuggers from your code and inspect the code.

      The only reason I can think of why you are not able to login is may be you have not enabled Simple auth from inside the Firebase forge for your Firebase app?

      Thanks!

      • jaybaker1968

        Thank you. My problem was a typo in a file name. I had controller.js instead of controllers.js.
        I might change the line “Finally the controller.js” above, that might have influenced me.
        Thanks again for the wonderful tutorial and the help!

        • / Arvind Ravulavaru

          Sorry my bad. Fixed it. Thanks for pointing it out.
          Glad you enjoyed the tutorial.