{"id":1186,"date":"2014-05-22T14:29:40","date_gmt":"2014-05-22T14:29:40","guid":{"rendered":"http:\/\/www.osd.net\/blog\/?p=1186"},"modified":"2014-05-22T14:29:40","modified_gmt":"2014-05-22T14:29:40","slug":"node-js-and-sencha-touch-chat","status":"publish","type":"post","link":"https:\/\/www.osd.net\/blog\/mobile-development\/node-js-and-sencha-touch-chat\/","title":{"rendered":"Node.js and Sencha Touch Chat"},"content":{"rendered":"<p>In this article we will implement a <strong>chat application<\/strong> for mobile devices that will work on both <strong>Android<\/strong> and <strong>iOS<\/strong>. In order to do so, we will need\u00a0knowledge of <a title=\"Sencha Touch articles\" href=\"https:\/\/www.osd.net\/blog\/tag\/sencha-touch\/\">Sencha Touch<\/a> for the mobile application, <a title=\"Node.js\" href=\"http:\/\/nodejs.org\/\" target=\"_blank\">Node.js<\/a> for server-side and <a title=\"MySQL\" href=\"http:\/\/www.mysql.com\/\" target=\"_blank\">MySQL<\/a> for the database. We can use this kind of application to communicate with other people needing only a smartphone and an internet connection.<\/p>\n<h3>What we want from this application?<\/h3>\n<p>We want an application that allows us to communicate in real time with other users, with a login, so we can have our own account. We also want the messages to be saved somewhere, so we can view them anytime we want.<\/p>\n<h3>How we structure the data?<\/h3>\n<p>In order achieve these objectives , first of all we need to think about how we structure the data For our sample there are going to be two data types, for users and messages.<\/p>\n<p>For the user data type, we will need 3 fields: a user id, that will be unique and will help us identify a specific user, a username used for display and a password that is required in order to authenticate the user.<\/p>\n<p>For the message data type we will need a message id, unique for each message, similar to the user id. Also we need the id of the user that sent the message and the id of the user that received it, the message content, and the message status that will mark if the message was read or not.<\/p>\n<h3>The database<\/h3>\n<p>In order to save the data that we described earlier, we will create these two tables in <strong>MySQL<\/strong>:<\/p>\n<p>The users table:<\/p>\n<pre class=\"brush: sql; title: ; notranslate\" title=\"\">\r\nCREATE TABLE IF NOT EXISTS `bc_users` (\r\n    `user_id` int(10) unsigned NOT NULL AUTO_INCREMENT,\r\n    `user_username` varchar(100) NOT NULL,\r\n    `user_password` varchar(37) NOT NULL,\r\n    PRIMARY KEY (`user_id`)\r\n);\r\n<\/pre>\n<p>The messages table:<\/p>\n<pre class=\"brush: sql; title: ; notranslate\" title=\"\">\r\nCREATE TABLE IF NOT EXISTS `bc_messages` (\r\n    `message_id` int(10) unsigned NOT NULL AUTO_INCREMENT,\r\n    `message_from` int(10) unsigned NOT NULL,\r\n    `message_to` int(10) unsigned NOT NULL,\r\n    `message_content` text NOT NULL,\r\n    `message_read` tinyint(3) unsigned NOT NULL DEFAULT '0',\r\n    PRIMARY KEY (`message_id`)\r\n);\r\n\r\n<\/pre>\n<h3>The server-side<\/h3>\n<p>This part will be developed using <strong>Node.js<\/strong>. Assuming that you have some\u00a0knowledge about this, we will start with the implementation. \u00a0First we are going to write some helpers that will provide the functions that we need in order to interact with the database.<\/p>\n<p>We will use a <strong>Node.js<\/strong> driver for database, named <a title=\"Node.js My Sql\" href=\"http:\/\/nodejsdb.org\/db-mysql\/\" target=\"_blank\">db-mysql<\/a>. Now, create a file named <strong>db.js<\/strong>, where we will require the driver, create the sql connection and connect to the sql server. This will look like this:<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\nvar mysql = require('db-mysql');\r\nvar config = require('.\/..\/config');\r\n\r\n\/\/create a new connection object\r\nvar sql_connection = new mysql.Database({\r\n    hostname: config.dbConfig.host,\r\n    user: config.dbConfig.user,\r\n    password: config.dbConfig.password,\r\n    database: config.dbConfig.database\r\n});\r\n\r\n\/\/connect to db\r\nsql_connection.connect(function(error) {\r\n    if (error) {\r\n        console.log('An error ocurred when connecting to database ' + error);\r\n        process.exit();\r\n    }\r\n});\r\n\r\nexports.connection = sql_connection;\r\n<\/pre>\n<p>Here we create the connection object, with the database credentials. After that we call the connect method of this object, with a callback function. If there is any error, we display it and stop the process. In the end, we add to the <strong>MySQL<\/strong> object the connection property, which is the database connection.<\/p>\n<p>Also we will need a helper for working with user passwords. For safety reasons we won&#8217;t save them exactly how the user writes them. For this, we choose the following algorithm: we generate a random string, five letters long. We add this string at the end of the user password, we call the <a title=\"MD5\" href=\"http:\/\/en.wikipedia.org\/wiki\/MD5\" target=\"_blank\">MD5<\/a> hash function over this string, and finally, add the same random string at the beginning of the result. Please note that this approach is used for a mix of security but also simplicity since this is a tutorial. In &#8220;real world&#8221; applications you might want to use more advanced hashing algorithms and strategies.\u00a0 Assuming that randomString(5) is a function call that returns a 5 chars random string, the function described will look like this:<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n\/\/crypt the password with the specified salt or a new one\r\nvar cryptPassword = function(password, salt) {\r\n    var randString = salt || randomString(config.saltLength);\r\n\r\n    return randString + crypto.createHash('md5').update(password + randString).digest('hex');\r\n};\r\n<\/pre>\n<p>After we create all helper functions that we need, we include all helpers in the main server file. Here we will create the HTTP server, like this:<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n\/\/create the server\r\nvar server = http.createServer(function(request, response) {\r\n    request.on('end', function() {\r\n        response.writeHead(200, {'Content-Type': 'text\/html'});\r\n        response.end();\r\n    });\r\n}).listen(8081);\r\n\r\nvar conn = io.listen(server);\r\n<\/pre>\n<p>We will also need to keep track of connected users. So we will create two objects: clients and sockets. In clients objects we will store the connected user info, at the socket id key. In the sockets object, we will store the socket object at the user id key. After that, we will need to handle the following events: <strong>register<\/strong> for user register, <strong>login<\/strong> and <strong>auto_login<\/strong> for user authentication, <strong>get_users<\/strong> to get a full list of online users, <strong>message_sent<\/strong> triggered when sending a message, <strong>message_read<\/strong> for marking messages as read, <strong>get_conv_messages<\/strong> to load older messages, <strong>disconnect<\/strong> and <strong>logout<\/strong> for user disconnect event.<\/p>\n<p>We will see for example, the <strong>message_sent<\/strong> event handler:<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n\/\/message sent event\r\nsocket.on('message_sent', function(message_to, message_content) {\r\n    \/\/get user id of sender\r\n    message_from = clients[socket.id].user_id;\r\n    \/\/save the message to db and get the id\r\n    var message_id = messages.save_message(message_from, message_to, message_content);\r\n\r\n    \/\/if there is a socket to send to\r\n    if (sockets[message_to]) {\r\n        \/\/send the message\r\n        sockets[message_to].emit('message_receive', message_from, message_content, message_id);\r\n    }\r\n});\r\n<\/pre>\n<p>In this handler, first, we get the user id from clients object, based on the id of the clients socket. We save the message to database and receive the new message id. Finally, if the recipient is connected (if the user id key exists in sockets object), we emit the new message to recipient socket.<\/p>\n<p>In the end, our <strong>Node.js<\/strong> application will have the following file structure:<\/p>\n<p style=\"text-align: center;\"><a href=\"https:\/\/www.osd.net\/blog\/wp-content\/uploads\/2014\/03\/server-structure.png\"><img loading=\"lazy\" class=\"size-medium wp-image-1240 aligncenter\" title=\"Server Structure\" src=\"https:\/\/www.osd.net\/blog\/wp-content\/uploads\/2014\/03\/server-structure-300x117.png\" alt=\"server structure\" width=\"300\" height=\"117\" srcset=\"https:\/\/www.osd.net\/blog\/wp-content\/uploads\/2014\/03\/server-structure-300x117.png 300w, https:\/\/www.osd.net\/blog\/wp-content\/uploads\/2014\/03\/server-structure.png 351w\" sizes=\"(max-width: 300px) 100vw, 300px\" \/><\/a><\/p>\n<h3>The client-side<\/h3>\n<p>For the client side we will use the <a title=\"Sencha Touch articles\" href=\"https:\/\/www.osd.net\/blog\/tag\/sencha-touch\/\">Sencha Touch<\/a> framework. Assuming that you already have base\u00a0knowledge about <strong>Sencha Touch<\/strong> and <strong>MVC<\/strong>, we will present only some aspects of the application.<\/p>\n<p>As we already know, we have two data types: the user and the message. In the client application we will have message and online user. We will create a <a title=\"Sencha Touch Model\" href=\"http:\/\/docs.sencha.com\/touch\/2.3.0\/#!\/api\/Ext.data.Model\" target=\"_blank\">model<\/a> for each one of them, that will look like the following:<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\nExt.define('App.model.Message', {\r\n    extend: 'Ext.data.Model',\r\n\r\n    config: {\r\n        fields: [\r\n             \/\/content of message\r\n \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0\u00a0{name: 'message_content', type: 'string'},\r\n \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0\u00a0\/\/if true, message sent, if false, message received\r\n \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0\u00a0{name: 'sent', type: 'boolean'},\r\n \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0\u00a0\/\/other user of conversation\r\n \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0\u00a0{name: 'message_with', type: 'int'},\r\n \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0\u00a0\/\/date of message\r\n \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0\u00a0{name: 'message_time', type: 'string'},\r\n \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0\u00a0\/\/0 if message unread, 1 if read\r\n \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0\u00a0{name: 'message_read', type: 'int'},\r\n \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0\u00a0\/\/the id from db of the message\r\n \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0\u00a0{name: 'message_id', type: 'int', defaultValue: 0}\r\n        ]\r\n    }\r\n});\r\n<\/pre>\n<p>Here we define the Message model, every message following to be a instance of this class. We define the <strong>message_content<\/strong> field, which will represent the actual message, the <strong>sent<\/strong> boolean, that will be true if the message was <em>sent from<\/em> this device, or false if it was <em>received on<\/em> this device. The <strong>message_with<\/strong> represents the id of the other user that received or sent the message, <strong>message_time<\/strong> is the timestamp of the message. The last are: the <strong>message_read<\/strong>, which will be <em>0<\/em> if the message is not read or <em>1<\/em> if the message is read, and <strong>message_id<\/strong> that represents the id of the message from the database.<\/p>\n<p>For this model, we will also create a <a title=\"Sencha Touch Store\" href=\"http:\/\/docs.sencha.com\/touch\/2.3.0\/#!\/api\/Ext.data.Store\" target=\"_blank\">store<\/a>, where we can have a collection of Message objects. We will name the store Messages, and the definition will look like this:<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\nExt.define('App.store.Messages', {\r\n    extend: 'Ext.data.Store',\r\n\r\n    config: {\r\n        model: 'App.model.Message'\r\n    }\r\n\r\n});\r\n<\/pre>\n<p>Now, we must add <strong>Node.js<\/strong> functionality to our app. First, we include the js file from our server in the HTML header:<\/p>\n<pre class=\"brush: xml; title: ; notranslate\" title=\"\">\r\n&lt;head&gt;\r\n    &lt;title&gt;Chat&lt;\/title&gt;\r\n    &lt;link rel=&quot;stylesheet&quot; type=&quot;text\/css&quot; href=&quot;css\/app.css&quot; \/&gt;\r\n\r\n    &lt;script type=&quot;text\/javascript&quot; charset=&quot;utf-8&quot; src=&quot;js\/lib\/sencha-touch-all.js&quot;&gt;&lt;\/script&gt;\r\n    &lt;script src=&quot;http:\/\/&lt;IP&gt;:&lt;PORT&gt;\/socket.io\/lib\/socket.io.js&quot;&gt;&lt;\/script&gt;\r\n    &lt;script src=&quot;js\/app.js&quot;&gt;&lt;\/script&gt;\r\n&lt;\/head&gt;\r\n<\/pre>\n<p>After that, we try to create the socket object:<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\nif (&quot;undefined&quot; == typeof(io)) {\r\n    alert(&quot;Server not available at this moment. Please retry later&quot;);\r\n} else {\r\n    var socket = io.connect('&lt;IP&gt;:&lt;PORT&gt;');\r\n}\r\n<\/pre>\n<p>We will create a register and login screen, so users can sign up an then authenticate in the application. After login, we will save user id and user name in <strong>local storage<\/strong>, so we can auto login user next time he uses the application. However, this is not a safe procedure and it&#8217;s not recommended to use it in production.<br \/>\nAfter login, we will display a screen with the online users. This is a <a title=\"Sencha Touch List\" href=\"http:\/\/docs.sencha.com\/touch\/2.3.0\/#!\/api\/Ext.dataview.List\" target=\"_blank\">List view<\/a>, that loads its data from <strong>OnlineUsers<\/strong> store created earlier. The controller of this view listens to list refresh, list add and list remove events, so we can keep it up to date in real time. Also, when a new message is received but the user did not see it, the list will update the senders item with the number of unread messages from that user.<\/p>\n<p>Tapping on a user from this list, will open the conversation view. Here we can see the messages from this user, send a new message, or scroll up to load older messages. The display of the messages is also a list that loads the data form Messages store. This list looks like this:<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n\/\/messages list\r\n{\r\n    xtype: 'list',\r\n    disableSelection: true,\r\n    store: 'Messages',\r\n    itemId: 'messageList',\r\n    layout: 'fit',\r\n    cls: 'messageList',\r\n    itemTpl: new Ext.XTemplate(\r\n        '&lt;tpl if=&quot;sent&quot;&gt;',\r\n            '&lt;div class=&quot;x-button x-button-confirm sent message-container&quot; style=&quot;float: right;&quot;&gt;',\r\n                '&lt;p class=&quot;x-button-label message&quot;&gt;{message_content}&lt;\/p&gt;',\r\n            '&lt;\/div&gt;',\r\n        '&lt;tpl else&gt;',\r\n            '&lt;div class=&quot;x-button received message-container&quot; style=&quot;float: left;&quot;&gt;',\r\n                '&lt;p class=&quot;x-button-label message&quot;&gt;{message_content}&lt;\/p&gt;',\r\n            '&lt;\/div&gt;',\r\n        '&lt;\/tpl&gt;'\r\n    )\r\n}\r\n<\/pre>\n<p>In order to load older messages, we must attach a handler for the scroll event of the scroller of list. If it reaches a specified value for Y coordinate, it&#8217;s time to load more older messages.<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\nvar listItem = view.query('#messageList')[0];\r\n\/\/handler for list scroll\r\nlistItem.getScrollable()._scroller.on('scroll', function() {\r\n        \/\/if the scroll reaches a point and there was not another request made\r\n        if (-30 &gt;= arguments[2] &amp;&amp; !that.loadMoreRequest) {\r\n        \/\/request more messages\r\n        that.loadMoreRequest = true;\r\n        socket.emit('get_conv_messages', that.selectedUser, store.getCount(), 10);\r\n    }\r\n});\r\n<\/pre>\n<p>On first line, we get the list element. After that we get the scroller object, and we attach a handler for it&#8217;s scroll event. If the Y coordinate get&#8217;s lower than -30, and a load more request was not already made, we mark the load more request flag as true, and we make the request to get the next 10 elements. The server will respond to this request with the messages, and trigger the <strong>get_conv_message_resp<\/strong> event. In the <strong>init<\/strong> function of the Chat controller, we attach a handler for this event. In this handler we will parse the <strong>JSON<\/strong> received and after that, one by one, we will insert the messages at the beginning of the store, so the older one is always the first. Finally, with a delay of 1 second, we will set as false the load more request flag, so we can make another request if the user wants.<\/p>\n<p>Finally, the file structure of our client application should look like this:<\/p>\n<p style=\"text-align: center;\"><a href=\"https:\/\/www.osd.net\/blog\/wp-content\/uploads\/2014\/03\/client-structure.png\"><img loading=\"lazy\" class=\"size-medium wp-image-1250 aligncenter\" title=\"Client Application File Structure\" src=\"https:\/\/www.osd.net\/blog\/wp-content\/uploads\/2014\/03\/client-structure-211x300.png\" alt=\"client structure\" width=\"211\" height=\"300\" srcset=\"https:\/\/www.osd.net\/blog\/wp-content\/uploads\/2014\/03\/client-structure-211x300.png 211w, https:\/\/www.osd.net\/blog\/wp-content\/uploads\/2014\/03\/client-structure.png 349w\" sizes=\"(max-width: 211px) 100vw, 211px\" \/><\/a><\/p>\n<p style=\"text-align: left;\">Now you are one step away from your <strong>mobile chat app<\/strong>. Last thing you need to do is to make <strong>iOS<\/strong> and <strong>Android<\/strong> builds in order to see it at work. You can <a title=\"Chat application - source samples\" href=\"https:\/\/www.osd.net\/blog\/wp-content\/uploads\/2014\/05\/nodechat.zip\">download the full archive<\/a> and give it a try.<\/p>\n<p style=\"text-align: left;\">I am looking forward for your feedback, let me know if you have any suggestions or questions.<\/p>\n<div id=\"share-and-beer-container\">\t<div id=\"buy_me_a_beer_div\" class=\"single beer\">\n\t \t\n\t\t<div class=\"buy-beer\" onclick=\"document.getElementById('buy_me_a_beer_form').submit();\">\n\t\t\t<form action=\"https:\/\/www.paypal.com\/cgi-bin\/webscr\" id=\"buy_me_a_beer_form\" method=\"post\">\n\t\t\t\t<input type=\"hidden\" name=\"cmd\" value=\"_xclick\" \/>\n\t\t\t\t<input type=\"hidden\" name=\"business\" value=\"info@directaccess.ro\" \/>  \n\t\t\t\t<input type=\"hidden\" name=\"item_name\" value=\"A Beer For Node.js and Sencha Touch Chat\" \/>  \n\t\t\t\t<input type=\"hidden\" name=\"item_number\" value=\"1\" \/>  \n\t\t\t\t<input type=\"hidden\" name=\"return\" value=\"https:\/\/www.osd.net\/blog\/mobile-development\/node-js-and-sencha-touch-chat\/\" \/>  \n\t\t\t\t<input type=\"hidden\" name=\"amount\" value=\"5\" \/>  \n\t\t\t\t<input type=\"hidden\" name=\"undefined_quantity\" value=\"1\" \/>  \n\t\t\t\t<input type=\"hidden\" name=\"currency_code\" value=\"USD\" \/>  \n\t\t\t<\/form>\n\t\t\t<p class=\"buy-beer-text\">If you liked this post <br \/> you can <strong>buy me a beer<\/strong><\/p>\n\t\t<\/div>\n\t<\/div><\/div>","protected":false},"excerpt":{"rendered":"<p>In this article we will implement a chat application for mobile devices that will work on both Android and iOS. In order to do so, we will need\u00a0knowledge of Sencha Touch for the mobile application, Node.js for server-side and MySQL for the database. We can use this kind of application to communicate with other people &hellip;<\/p>\n<div class=\"cta1\"><a href=\"https:\/\/www.osd.net\/blog\/mobile-development\/node-js-and-sencha-touch-chat\/\">Read more<\/a><\/div>\n<div class=\"like-excerpt\"><div\n        class=\"fb-like\"\n        data-href=\"https:\/\/www.osd.net\/blog\/mobile-development\/node-js-and-sencha-touch-chat\/\"\n        data-layout=\"button_count\"\n        data-action=\"like\"\n        data-show-faces=\"false\"\n        data-share=\"false\">\n        <\/div><\/div>","protected":false},"author":10,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[88],"tags":[128,89],"_links":{"self":[{"href":"https:\/\/www.osd.net\/blog\/wp-json\/wp\/v2\/posts\/1186"}],"collection":[{"href":"https:\/\/www.osd.net\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.osd.net\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.osd.net\/blog\/wp-json\/wp\/v2\/users\/10"}],"replies":[{"embeddable":true,"href":"https:\/\/www.osd.net\/blog\/wp-json\/wp\/v2\/comments?post=1186"}],"version-history":[{"count":75,"href":"https:\/\/www.osd.net\/blog\/wp-json\/wp\/v2\/posts\/1186\/revisions"}],"predecessor-version":[{"id":1277,"href":"https:\/\/www.osd.net\/blog\/wp-json\/wp\/v2\/posts\/1186\/revisions\/1277"}],"wp:attachment":[{"href":"https:\/\/www.osd.net\/blog\/wp-json\/wp\/v2\/media?parent=1186"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.osd.net\/blog\/wp-json\/wp\/v2\/categories?post=1186"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.osd.net\/blog\/wp-json\/wp\/v2\/tags?post=1186"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}