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");
}

Saturday, 13 October 2012

Fragment of Intent

I was going to title this a statement of intent but I don't want to go that far. By stopping short of that I am in effect making a different statement.

There are lots of good blogs out there for the professional developer, working full-time on enterprise projects, whose working life is dedicated to writing code. I'm not going to try to write one of those blogs. I don't have the time and that's the point.

With the boom of 'X as a Service's there are now a multitude of options available for those who have to code on the run, or in their lunch-breaks, who don't have time, money or inclination to build and deploy servers. Part-time programmers now have more options for tools and platforms. Bedroom programmers, lunchtime hobbyists and garage start-ups can now draw on a vast field of services to get their ideas and products 'out there'.

I used to be a professional developer. Now I manage developers. I'm also a father and husband. I still have the urge to produce software but I don't have the time I used to have. There are some corners I can safely cut and others that need to be left well alone. I'm searching for tools that can make my life easier and allow me to create working, functional software without giving up the day job.