Monday, 19 November 2012

IM prototype with Firebase and Application Craft

I was recently lucky enough to receive a beta invite for Firebase, a Javascript tool that aims to remove or at least reduce the need for a dedicated server. I found their demos pretty convincing and if their claims were true I knew the library would be a great tool for the Part Coder arsenal. One of the demo apps on their site is a simple chat app (https://www.firebase.com/tutorial/#example-chat). I wondered how quickly I could adapt their demo into a prototype Android app. That’s where Application Craft came in. Application Craft is a great tool for creating, testing and deploying mobile applications.

As it turns out it only took a couple of hours; part of that time was learning how to use Firebase. I think if I had to start again from scratch it could probably be done comfortably in under an hour. Not bad for a prototype IM app.

All in all it took under 100 lines of code. The salient points are listed below.

You can check out Application Craft here and Firebase here. I have a handful of beta codes for Firebase. Leave a comment if you're interested in taking one.

Set up

Initialising the Firebase library is dead easy. It just takes one line.

 
var BASE_URL = 'https://*firebasename*.firebaseIO.com';
var baseRef;
 
// when app starts initialise the base reference for all Firebase calls
function handler_application_onAppStarted(){
  baseRef = new Firebase(BASE_URL);
}

Choosing a chat room

Not strictly necessary for the prototype but I decided to allow the user the option to join an existing chatroom or create their own.

// create a room with a given name, return its Firebase 'url'
function _create_room(name){
    return baseRef.push({name:name}).toString();
}

// user has selected a room
// set chatroomRef to the reference of the room, jump to the chatroom page
function _join_room(roomURL){
    chatroomRef = new Firebase(roomURL);
   
    app.pageJump("chatroomPage");
}

// user has opted to add a new chatroom
// show the hidden 'new chatroom' interface
function handler_openAddChatroomButton_onClick(mouseev){
    app.visible("newChatroomContainer", true);
}

// when the choose room page first shows, populate the list of chatrooms
// so the user can choose one
function handler_chooseRoomPage_onPageShow(){
    baseRef.once("value", function(dataSnapshot) {
        // need to use the map function to get from what Firebase returns
        // to what Application Craft needs to populate the list widget
        var rooms_array = jQuery.map(dataSnapshot.val(), 
            function(value, key){
                return { "roomURL" : key, "name" : value.name };
            });

        app.populateWidget("chatroomListContainer", rooms_array, 
            { "chatroomChoiceButton" : "name", 
              "roomURLLabel" : "roomURL" });   
    });      
}

// the user has clicked the add room button
function handler_addChatroomButton_onClick(mouseev){
    var roomName = app.getValue("newChatroomName");
   
    var roomURL = _create_room(roomName);
    _join_room(roomURL);
}
 
// a bit icky this one, there's probably a better way to do it :)
// extract the URL of the selected chatroom from the relevant 
// layer of the UI
function handler_chatroomChoiceButton_onClick(mouseev){
    var index = _widget.parent().rowIndex();
    var rowObj = _widget.parent().parent().getRow(index);
    var roomURL = rowObj.w('roomURLLabel').value();       
   
    _join_room(BASE_URL+"/"+roomURL);
}

Handling chat events

Now that the user is in the right room it's pretty trivial to send and receive messages.

 
// user has clicked send text button
// read the message and push it to Firebase
function handler_sendTextButton_onClick(mouseev){
               var name = app.getValue("usernameText");
    var message = app.getValue("messageText");
   
    chatroomRef.push({ "name":name, "message":message });
   
    app.setValue("messageText", "");
}

// when the page first loads call the Firebase 'on' function
// first param is 'child_added' meaning this will get updated
// every time a child (i.e. message) is added to our room ref
function handler_chatroomPage_onPageShow(){
    chatroomRef.on("child_added", function(dataSnapshot) {
        var val = dataSnapshot.val();
       
        // check there's something in our returned value
        // the first and last values are sometimes empty
        if (val.name) {
            var new_string = app.getValue("chatLabel") + 
                             val.name + ": " + 
                             val.message;

            // chatLabel displays the messages
            app.setValue("chatLabel",  new_string);
        }
    });
}

// a token effort towards making this a proper app
// just to illustrate stopping the flow of data from Firebase
// with the 'off' function
function handler_chatroomPage_onPageLeft(){
               chatroomRef.off("child_added");
}

3 comments:

  1. I'm well impressed with what you've done here :)
    Have to try to find the time to give it a go myself

    Ian

    ReplyDelete
  2. Hi,
    I would like to implement chat capability in my AC app.
    Do you have example of what you've done ?

    Thanks

    Sylvain

    ReplyDelete
  3. Hi,

    You can check out the app that goes with the example code here -- http://acft.ws/mghw.

    HTH,
    A.

    ReplyDelete