Merge branch 'winston' of https://github.com/M2Ys4U/KiwiIRC into winston
authorDarren <darren@darrenwhitlen.com>
Fri, 28 Mar 2014 16:09:59 +0000 (16:09 +0000)
committerDarren <darren@darrenwhitlen.com>
Fri, 28 Mar 2014 16:09:59 +0000 (16:09 +0000)
40 files changed:
client/assets/css/style.css
client/assets/themes/basic/style.css
client/assets/themes/cli/style.css
client/assets/themes/mini/style.css
client/assets/themes/relaxed/style.css
client/build.js
client/src/app.js
client/src/applets/chanlist.js
client/src/applets/settings.js
client/src/applets/startup.js [new file with mode: 0644]
client/src/index.html.tmpl
client/src/models/applet.js
client/src/models/application.js
client/src/models/channel.js
client/src/models/gateway.js
client/src/models/network.js
client/src/models/newconnection.js
client/src/models/panel.js
client/src/models/query.js
client/src/models/server.js
client/src/translations/en-gb.po
client/src/views/apptoolbar.js
client/src/views/channel.js
client/src/views/channeltools.js
client/src/views/mediamessage.js
client/src/views/panel.js
client/src/views/serverselect.js
client/src/views/tabs.js
client/src/views/topicbar.js
client/src/views/userbox.js
config.example.js
server/.jshintrc [new file with mode: 0644]
server/irc/channel.js
server/irc/commands.js
server/irc/connection.js
server/irc/server.js
server/irc/user.js
server/proxy.js
server/server.js
server/settingsgenerator.js

index 7c69af3e3e7b9fcb3ce27be25faafa09a2f22b62..00de4618087a2fbf343259a93f52447d48a7db98 100644 (file)
@@ -474,3 +474,10 @@ html, body { height:100%; }
     padding: 5px; border-top:1px solid #e9e9e9; background:#ddd; overflow:hidden;
 }
 #kiwi .ui_menu .ui_menu_foot .close { }
+
+#kiwi .applet .applet_chanlist .icon-sort-down:before, #kiwi .applet .applet_chanlist .icon-sort-up:before {
+    padding-left: 1em;
+}
+#kiwi .applet .applet_chanlist td {
+    min-width: 120px;
+}
index e0aae246c40008001a5a19ae18d505aa9e976aa0..2ca440bfaef277b64d8a22844092c4764e3b5967 100644 (file)
@@ -62,6 +62,7 @@
 #kiwi .toolbar .panellist li span  { line-height:20px; vertical-align:middle; display:inline-block; }
 
 #kiwi .toolbar .panellist li .activity { display:inline; margin-left:0.5em; font-style:italic; font-size:0.8em; }
+#kiwi .toolbar .panellist.applets li .activity { display: none; }
 #kiwi .toolbar .panellist li .activity:before { content:"("; }
 #kiwi .toolbar .panellist li .activity:after { content:")"; }
 
     border:1px solid #A33F3F; background-color:#D28A8A;
     padding:0.5em; margin-top:1em; margin-bottom:1em; margin-right:2em;
 }
+#kiwi .server_select .show_server { margin-left: 1em; font-size:0.9em; color: #555555; }
 
 
 #kiwi .server_select .kiwi_logo { margin-top:30px; text-align:center; display:block; }
     border-bottom-right-radius:0;
     border-top-right-radius:0;
 }
+#kiwi .applet_chanlist {
+    margin: 0.5em 1em;
+}
+#kiwi .applet_chanlist table {
+    border-collapse: collapse;
+    width: 100%;
+}
+#kiwi .applet_chanlist thead {
+    text-align: center;
+}
+#kiwi .applet_chanlist tbody td {
+    border: 1px solid #C4C4C4;
+    padding: 0.3em 1em;
+}
+#kiwi .applet_chanlist .chanlist_name, #kiwi .applet_chanlist .chanlist_num_users {
+    border-width: 0 1px 0 0;
+}
+#kiwi .applet_chanlist .chanlist_topic {
+    border-width: 0;
+}
+#kiwi .applet_chanlist tr:nth-child(even) {
+    background: none repeat scroll 0 0 #DBDBDB;
+}
 
 
 #kiwi .ui_menu .ui_menu_foot .close { float:right; font-size:0.9em; margin-right:1em; color: #999; }
index a800c3c0784074cb0682edabfe11bca9d77aa4b6..f321a04e4ff1df7a01bf57668c27ffa0a14b9f96 100644 (file)
@@ -87,6 +87,7 @@
 #kiwi .toolbar .panellist li span  { line-height:20px; vertical-align:middle; display:inline-block; }
 
 #kiwi .toolbar .panellist li .activity { display:inline; margin-left:0.5em; font-style:italic; font-size:0.8em; }
+#kiwi .toolbar .panellist.applets li .activity { display: none; }
 #kiwi .toolbar .panellist li .activity:before { content:"("; }
 #kiwi .toolbar .panellist li .activity:after { content:")"; }
 #kiwi .toolbar .panellist li.alert_highlight .activity {
     border:1px solid #A33F3F; background-color:#D28A8A;
     padding:0.5em; margin-top:1em; margin-bottom:1em; margin-right:2em;
 }
+#kiwi .server_select .show_server { margin-left: 1em; font-size:0.9em; color: #eeeeee; }
 
 #kiwi .server_select .basic tr.channel .icon-key { color:#555; }
 
 #kiwi.chanlist_treeview .tabs ul li { display:block; float:none; }
 #kiwi.chanlist_treeview .tabs ul li .activity { float:right; }
 #kiwi.chanlist_treeview .tabs ul li.active { padding-left:1em; }
+#kiwi .applet_chanlist {
+    margin: 0.5em 1em;
+}
+#kiwi .applet_chanlist table {
+    border-collapse: collapse;
+    width: 100%;
+}
+#kiwi .applet_chanlist thead {
+    text-align: center;
+}
+#kiwi .applet_chanlist tbody td {
+    border: 1px solid #454545;
+    padding: 0.3em 1em;
+}
+#kiwi .applet_chanlist .chanlist_name, #kiwi .applet_chanlist .chanlist_num_users {
+    border-width: 0 1px 0 0;
+}
+#kiwi .applet_chanlist .chanlist_topic {
+    border-width: 0;
+}
+#kiwi .applet_chanlist tr:nth-child(even) {
+    background: none repeat scroll 0 0 #2B2929;
+}
 
 
 #kiwi .ui_menu {
index 24f8ab6eef8e3b0972d59864ce5b3b8be48044fc..71b6411f10f0a380a3ba15fa66cb1c076e049f53 100644 (file)
@@ -60,6 +60,7 @@
 #kiwi .toolbar .panellist li span  { line-height:20px; vertical-align:middle; display:inline-block; }
 
 #kiwi .toolbar .panellist li .activity { display:inline; margin-left:0.5em; font-style:italic; font-size:0.8em; }
+#kiwi .toolbar .panellist.applets li .activity { display: none; }
 #kiwi .toolbar .panellist li .activity:before { content:"("; }
 #kiwi .toolbar .panellist li .activity:after { content:")"; }
 
 #kiwi.chanlist_treeview .tabs ul li { display:block; float:none; }
 #kiwi.chanlist_treeview .tabs ul li .activity { float:right; }
 #kiwi.chanlist_treeview .tabs ul li.active { padding-left:1em; }
+#kiwi #chanlist {
+    margin: 0.5em 1em;
+}
+#kiwi .applet_chanlist table {
+    border-collapse: collapse;
+    width: 100%;
+}
+#kiwi .applet_chanlist thead {
+    text-align: center;
+}
+#kiwi .applet_chanlist tbody td {
+    border: 1px solid #C4C4C4;
+    padding: 0.3em 1em;
+}
+#kiwi .applet_chanlist .chanlist_name, #kiwi .applet_chanlist .chanlist_num_users {
+    border-width: 0 1px 0 0;
+}
+#kiwi .applet_chanlist .chanlist_topic {
+    border-width: 0;
+}
+#kiwi .applet_chanlist tr:nth-child(even) {
+    background: none repeat scroll 0 0 #DBDBDB;
+}
 
 
 
     border:1px solid #A33F3F; background-color:#D28A8A;
     padding:0.5em; margin-top:1em; margin-bottom:1em; margin-right:2em;
 }
+#kiwi .server_select .show_server { margin-left: 1em; font-size:0.9em; color: #555555; }
 
 #kiwi .server_select .kiwi_logo h1 span {
     font-size:14px;
index a9d73676098cd45951a41d8266a98ce591cccacf..783abc614201cf61cd7f6be560aa028e9adb67cc 100644 (file)
 #kiwi .messages a { text-decoration:none; }
 
 #kiwi .messages .msg { border-bottom: 1px solid #DEDEDE; padding: 1px; font-family:arial; font-size:0.9em; }
-#kiwi .messages .msg .time { width:5em; float:left; color:#777; padding:5px; display:none; }
+#kiwi .messages .msg .time { width:6em; float:left; color:#777; padding:5px; display:none; }
 #kiwi .messages .msg .nick { width:11em; float:left; font-size:12px; font-family:Arial; text-align:right; padding: 5px; overflow:hidden; }
 #kiwi .messages .msg .text { display:block; margin-left:12em; border-left: 1px solid #DEDEDE; white-space:pre-wrap; word-wrap:break-word; font-family:arial; padding:5px; }
 
 }
 
 #kiwi.timestamps .messages .msg .time { display:block; }
-#kiwi.timestamps .messages .msg .text { margin-left:17em; }
+#kiwi.timestamps .messages .msg .text { margin-left:18em; }
 
 #kiwi .messages .msg.global_nick_highlight,
 #kiwi .messages .msg.highlight { transition: background 0.3s; background:#D9D9D9; }
     border:1px solid #A33F3F; background-color:#D28A8A;
     padding:0.5em; margin-top:1em; margin-bottom:1em; margin-right:2em;
 }
+#kiwi .server_select .show_server { margin-left: 1em; font-size:0.9em; color: #555555; }
 
 
 #kiwi .server_select .kiwi_logo { margin-top:30px; }
     border-bottom-right-radius:0;
     border-top-right-radius:0;
 }
+#kiwi .applet_chanlist {
+    margin: 0.5em 1em;
+}
+#kiwi .applet_chanlist table {
+    border-collapse: collapse;
+    width: 100%;
+}
+#kiwi .applet_chanlist thead {
+    text-align: center;
+}
+#kiwi .applet_chanlist tbody td {
+    border: 1px solid #C4C4C4;
+    padding: 0.3em 1em;
+}
+#kiwi .applet_chanlist .chanlist_name, #kiwi .applet_chanlist .chanlist_num_users {
+    border-width: 0 1px 0 0;
+}
+#kiwi .applet_chanlist .chanlist_topic {
+    border-width: 0;
+}
+#kiwi .applet_chanlist tr:nth-child(even) {
+    background: none repeat scroll 0 0 #DBDBDB;
+}
 
 
 #kiwi .applet > div.settings button.save {
index da317859baf9c8fb2081daf505c2700e5d61b8b0..3e55739f37d385be2a7d4eb18e6e7a7bcb8995e7 100644 (file)
@@ -57,10 +57,6 @@ var source_files = [
     __dirname + '/src/models/datastore.js',\r
     __dirname + '/src/models/channelinfo.js',\r
 \r
-    __dirname + '/src/applets/settings.js',\r
-    __dirname + '/src/applets/chanlist.js',\r
-    __dirname + '/src/applets/scripteditor.js',\r
-\r
     __dirname + '/src/helpers/utils.js',\r
 \r
     __dirname + '/src/views/panel.js',\r
@@ -83,7 +79,12 @@ var source_files = [
     __dirname + '/src/views/topicbar.js',\r
     __dirname + '/src/views/userbox.js',\r
     __dirname + '/src/views/channeltools.js',\r
-    __dirname + '/src/views/channelinfo.js'\r
+    __dirname + '/src/views/channelinfo.js',\r
+\r
+    __dirname + '/src/applets/settings.js',\r
+    __dirname + '/src/applets/chanlist.js',\r
+    __dirname + '/src/applets/scripteditor.js',\r
+    __dirname + '/src/applets/startup.js'\r
 ];\r
 \r
 \r
index c15b76937c240240515f0dd2470d329e3f71f83a..8349f697aa7be36f603d6eb05ff7650522bc2061 100644 (file)
@@ -24,15 +24,19 @@ _kiwi.global = {
     // TODO: think of a better term for this as it will also refer to queries\r
     channels: undefined, // TODO: Limited access to panels list\r
 \r
+    addMediaMessageType: function(match, buildHtml) {\r
+        _kiwi.view.MediaMessage.addType(match, buildHtml);\r
+    },\r
+\r
     // Event managers for plugins\r
     components: {\r
         EventComponent: function(event_source, proxy_event_name) {\r
             function proxyEvent(event_name, event_data) {\r
                 if (proxy_event_name !== 'all') {\r
                     event_data = event_name.event_data;\r
-                    event_name = event_name.event_name\r
+                    event_name = event_name.event_name;\r
                 }\r
-//console.log(proxy_event_name, event_name, event_data);\r
+\r
                 this.trigger(event_name, event_data);\r
             }\r
 \r
index 2e909c014fbe8ae2bf61e9bba6c238e0866dd631..8c286fdf7c598584ec26e8dc4a44555aa5e4bfff 100644 (file)
@@ -3,6 +3,8 @@
     var View = Backbone.View.extend({\r
         events: {\r
             "click .chan": "chanClick",\r
+            "click .channel_name_title": "sortChannelsByNameClick",\r
+            "click .users_title": "sortChannelsByUsersClick"\r
         },\r
 \r
 \r
 \r
             this.channels = [];\r
 \r
-            // Sort the table by num. users?\r
-            this.ordered = true;\r
+            // Sort the table\r
+            this.order = '';\r
 \r
             // Waiting to add the table back into the DOM?\r
             this.waiting = false;\r
         },\r
 \r
-\r
         render: function () {\r
             var table = $('table', this.$el),\r
                 tbody = table.children('tbody:first').detach(),\r
                 that = this,\r
-                channels_length = this.channels.length,\r
                 i;\r
 \r
-            tbody.children().each(function (idx, child) {\r
-                if (that.channels[idx].channel === $(child.querySelector('.chan')).data('channel')) {\r
-                    that.channels[idx].dom = tbody[0].removeChild(child);\r
-                }\r
-            });\r
+            // Create the sort icon container and clean previous any previous ones\r
+            if($('.applet_chanlist .users_title').find('span.chanlist_sort_users').length == 0) {\r
+                this.$('.users_title').append('<span class="chanlist_sort_users">&nbsp;&nbsp;</span>');\r
+            } else {\r
+                this.$('.users_title span.chanlist_sort_users').removeClass('icon-sort-up');\r
+                this.$('.users_title span.chanlist_sort_users').removeClass('icon-sort-down');\r
+            }\r
+            if ($('.applet_chanlist .channel_name_title').find('span.chanlist_sort_names').length == 0) {\r
+                this.$('.channel_name_title').append('<span class="chanlist_sort_names">&nbsp;&nbsp;</span>');\r
+            } else {\r
+                this.$('.channel_name_title span.chanlist_sort_names').removeClass('icon-sort-up');\r
+                this.$('.channel_name_title span.chanlist_sort_names').removeClass('icon-sort-down');\r
+            }\r
 \r
-            if (this.ordered) {\r
-                this.channels.sort(function (a, b) {\r
-                    return b.num_users - a.num_users;\r
-                });\r
+            // Push the new sort icon\r
+            switch (this.order) {\r
+                case 'user_desc':\r
+                default:\r
+                    this.$('.users_title span.chanlist_sort_users').addClass('icon-sort-down');\r
+                    break;\r
+                case 'user_asc':\r
+                    this.$('.users_title span.chanlist_sort_users').addClass('icon-sort-up');\r
+                    break;\r
+                case 'name_asc':\r
+                    this.$('.channel_name_title span.chanlist_sort_names').addClass('icon-sort-up');\r
+                    break;\r
+                case 'name_desc':\r
+                    this.$('.channel_name_title span.chanlist_sort_names').addClass('icon-sort-down');\r
+                    break;\r
             }\r
 \r
-            for (i = 0; i < channels_length; i++) {\r
+            this.channels = this.sortChannels(this.channels, this.order);\r
+\r
+            // Make sure all the channel DOM nodes are inserted in order\r
+            for (i = 0; i < this.channels.length; i++) {\r
                 tbody[0].appendChild(this.channels[i].dom);\r
             }\r
+\r
             table[0].appendChild(tbody[0]);\r
         },\r
 \r
                 // IE...\r
                 _kiwi.gateway.join(null, $(event.srcElement).data('channel'));\r
             }\r
+        },\r
+\r
+        sortChannelsByNameClick: function (event) {\r
+            // Revert the sorting to switch between orders\r
+            this.order = (this.order == 'name_asc') ? 'name_desc' : 'name_asc';\r
+\r
+            this.sortChannelsClick();\r
+        },\r
+\r
+        sortChannelsByUsersClick: function (event) {\r
+            // Revert the sorting to switch between orders\r
+            this.order = (this.order == 'user_desc' || this.order == '') ? 'user_asc' : 'user_desc';\r
+\r
+            this.sortChannelsClick();\r
+        },\r
+\r
+        sortChannelsClick: function() {\r
+            this.render();\r
+        },\r
+\r
+        sortChannels: function (channels, order) {\r
+            var sort_channels = [],\r
+                new_channels = [];\r
+\r
+\r
+            // First we create a light copy of the channels object to do the sorting\r
+            _.each(channels, function (chan, chan_idx) {\r
+                sort_channels.push({'chan_idx': chan_idx, 'num_users': chan.num_users, 'channel': chan.channel});\r
+            });\r
+\r
+            // Second, we apply the sorting\r
+            sort_channels.sort(function (a, b) {\r
+                switch (order) {\r
+                    case 'user_asc':\r
+                        return a.num_users - b.num_users;\r
+                    case 'user_desc':\r
+                        return b.num_users - a.num_users;\r
+                    case 'name_asc':\r
+                        if (a.channel.toLowerCase() > b.channel.toLowerCase()) return 1;\r
+                        if (a.channel.toLowerCase() < b.channel.toLowerCase()) return -1;\r
+                    case 'name_desc':\r
+                        if (a.channel.toLowerCase() < b.channel.toLowerCase()) return 1;\r
+                        if (a.channel.toLowerCase() > b.channel.toLowerCase()) return -1;\r
+                    default:\r
+                        return b.num_users - a.num_users;\r
+                }\r
+                return 0;\r
+            });\r
+\r
+            // Third, we re-shuffle the chanlist according to the sort order\r
+            _.each(sort_channels, function (chan) {\r
+                new_channels.push(channels[chan.chan_idx]);\r
+            });\r
+\r
+            return new_channels;\r
         }\r
     });\r
 \r
 \r
 \r
-\r
     var Applet = Backbone.Model.extend({\r
         initialize: function () {\r
             this.set('title', _kiwi.global.i18n.translate('client_applets_chanlist_channellist').fetch());\r
             _.each(channels, function (chan) {\r
                 var row;\r
                 row = document.createElement("tr");\r
-                row.innerHTML = '<td><a class="chan" data-channel="' + chan.channel + '">' + _.escape(chan.channel) + '</a></td><td class="num_users" style="text-align: center;">' + chan.num_users + '</td><td style="padding-left: 2em;">' + formatIRCMsg(_.escape(chan.topic)) + '</td>';\r
+                row.innerHTML = '<td class="chanlist_name"><a class="chan" data-channel="' + chan.channel + '">' + _.escape(chan.channel) + '</a></td><td class="chanlist_num_users" style="text-align: center;">' + chan.num_users + '</td><td style="padding-left: 2em;" class="chanlist_topic">' + formatIRCMsg(_.escape(chan.topic)) + '</td>';\r
                 chan.dom = row;\r
                 that.view.channels.push(chan);\r
             });\r
index e88ce10d7c2745bbc0753178fbbe75715aefe392..f041ab196506c6ba4efe2fcbed8ceb52707540e2 100644 (file)
@@ -15,6 +15,7 @@
                 join_part: _kiwi.global.i18n.translate('client_applets_settings_notification_joinpart').fetch(),\r
                 count_all_activity: _kiwi.global.i18n.translate('client_applets_settings_notification_count_all_activity').fetch(),\r
                 timestamps: _kiwi.global.i18n.translate('client_applets_settings_timestamp').fetch(),\r
+                timestamp_24: _kiwi.global.i18n.translate('client_applets_settings_timestamp_24_hour').fetch(),\r
                 mute: _kiwi.global.i18n.translate('client_applets_settings_notification_sound').fetch(),\r
                 emoticons: _kiwi.global.i18n.translate('client_applets_settings_emoticons').fetch(),\r
                 scroll_history: _kiwi.global.i18n.translate('client_applets_settings_history_length').fetch(),\r
diff --git a/client/src/applets/startup.js b/client/src/applets/startup.js
new file mode 100644 (file)
index 0000000..54d7eef
--- /dev/null
@@ -0,0 +1,49 @@
+(function () {
+    var view = Backbone.View.extend({
+        events: {},
+
+
+        initialize: function (options) {
+            this.showConnectionDialog();
+        },
+
+
+        showConnectionDialog: function() {
+            var connection_dialog = this.connection_dialog = new _kiwi.model.NewConnection();
+            connection_dialog.populateDefaultServerSettings();
+
+            connection_dialog.view.$el.addClass('initial');
+            this.$el.append(connection_dialog.view.$el);
+
+            var $info = $($('#tmpl_new_connection_info').html().trim());
+
+            if ($info.html()) {
+                connection_dialog.view.infoBoxSet($info);
+                connection_dialog.view.infoBoxShow();
+            }
+
+            this.listenTo(connection_dialog, 'connected', this.newConnectionConnected);
+
+            _.defer(function(){
+                connection_dialog.view.$el.find('.nick').select();
+            });
+        },
+
+
+        newConnectionConnected: function(network) {
+            // Once connected, reset the connection form to be used again in future
+            this.connection_dialog.view.reset();
+        }
+    });
+
+
+
+    var applet = Backbone.Model.extend({
+        initialize: function () {
+            this.view = new view({model: this});
+        }
+    });
+
+
+    _kiwi.model.Applet.register('kiwi_startup', applet);
+})();
\ No newline at end of file
index 3baaf5b91ae072b9a445bbcce484d134040bc961..cb8d6b5811d18adee5cf58446b0f4b41eccf2094 100644 (file)
@@ -23,6 +23,7 @@
                 <div class="app_tools">\r
                     <ul class="main">\r
                         <li class="settings"><i class="icon-cogs" title="Settings"></i></li>\r
+                        <li class="startup"><i class="icon-home" title="Home"></i></li>\r
                         <li><a href="https://kiwiirc.com/" target="_blank"><img src="<%base_path%>/assets/img/ico.png" alt="KiwiIRC" title="KiwiIRC" /></a></li>\r
                     </ul>\r
                 </div>\r
@@ -45,7 +46,7 @@
             <div class="right_bar disabled">\r
                 <div class="channel_tools">\r
                     <i class="icon-info-sign channel_info" title="Channel Info"></i>\r
-                    <i class="icon-signout channel_part" ttle="Leave Channel"></i>\r
+                    <i class="icon-signout channel_part" title="Leave Channel"></i>\r
                 </div>\r
                 <div class="memberlists"></div>\r
             </div>\r
                                 <%= timestamps %>\r
                             </label>\r
                         </div>\r
+                        <div class="checkbox">\r
+                            <label>\r
+                                <input data-setting="use_24_hour_timestamps" type="checkbox">\r
+                                <%= timestamp_24 %>\r
+                            </label>\r
+                        </div>\r
                         <div class="checkbox">\r
                             <label>\r
                                 <input data-setting="mute_sounds" type="checkbox">\r
                     <h6>Language</h6>\r
                     <div class="control-group">\r
                         <select data-setting="locale">\r
+                            <option value=""></li>\r
                             <% _.forEach(languages, function(lang) { %>\r
                                 <option value="<%= lang.tag %>"><%= lang.language %></li>\r
                             <% }); %>\r
 \r
 \r
     <script type="text/html" id="tmpl_channel_list">\r
-        <div>\r
-            <table style="margin:1em 2em;">\r
+        <div class="applet_chanlist">\r
+            <table>\r
                 <thead style="font-weight: bold;">\r
                     <tr>\r
-                        <td><%= channel_name %></td>\r
-                        <td><%= users %></td>\r
+                        <td><a class="channel_name_title"><%= channel_name %></a></td>\r
+                        <td><a class="users_title"><%= users %></a></td>\r
                         <td style="padding-left: 2em;"><%= topic %></td>\r
                     </tr>\r
                 </thead>\r
index b9692822ff6e016addcfca7ce3b0a88417414512..0175791acf9c43a901cbfdbf59fb823c5149ea3d 100644 (file)
@@ -1,9 +1,4 @@
 _kiwi.model.Applet = _kiwi.model.Panel.extend({\r
-    // Used to determine if this is an applet panel. Applet panel tabs are treated\r
-    // differently than others\r
-    applet: true,\r
-\r
-\r
     initialize: function (attributes) {\r
         // Temporary name\r
         var name = "applet_"+(new Date().getTime().toString()) + Math.ceil(Math.random()*100).toString();\r
@@ -73,7 +68,7 @@ _kiwi.model.Applet = _kiwi.model.Panel.extend({
     close: function () {\r
         this.view.$el.remove();\r
         this.destroy();\r
-        \r
+\r
         this.view = undefined;\r
 \r
         // Call the applets dispose method if it has one\r
@@ -82,6 +77,10 @@ _kiwi.model.Applet = _kiwi.model.Panel.extend({
         }\r
 \r
         this.closePanel();\r
+    },\r
+\r
+    isApplet: function () {\r
+        return true;\r
     }\r
 },\r
 \r
@@ -111,24 +110,34 @@ _kiwi.model.Applet = _kiwi.model.Panel.extend({
     },\r
 \r
 \r
-    load: function (applet_name) {\r
-        var applet;\r
+    load: function (applet_name, options) {\r
+        var applet, applet_obj;\r
 \r
-        // Find the applet within the registered applets\r
-        if (!_kiwi.applets[applet_name]) return;\r
+        options = options || {};\r
+\r
+        applet_obj = this.getApplet(applet_name);\r
+\r
+        if (!applet_obj)\r
+            return;\r
 \r
         // Create the applet and load the content\r
         applet = new _kiwi.model.Applet();\r
-        applet.load(new _kiwi.applets[applet_name]({_applet_name: applet_name}));\r
+        applet.load(new applet_obj({_applet_name: applet_name}));\r
 \r
-        // Add it into the tab list\r
-        _kiwi.app.applet_panels.add(applet);\r
+        // Add it into the tab list if needed (default)\r
+        if (!options.no_tab)\r
+            _kiwi.app.applet_panels.add(applet);\r
 \r
 \r
         return applet;\r
     },\r
 \r
 \r
+    getApplet: function (applet_name) {\r
+        return _kiwi.applets[applet_name] || null;\r
+    },\r
+\r
+\r
     register: function (applet_name, applet) {\r
         _kiwi.applets[applet_name] = applet;\r
     }\r
index 704587cc5cd96c1440b3259828dea252288ca091..ecd5279a897ada76c163a3dbe500dacaf9bf7cc4 100644 (file)
@@ -32,6 +32,9 @@
             // Best guess at where the kiwi server is if not already specified\r
             this.kiwi_server = options.kiwi_server || this.detectKiwiServer();\r
 \r
+            // The applet to initially load\r
+            this.startup_applet_name = options.startup || 'kiwi_startup';\r
+\r
             // Set any default settings before anything else is applied\r
             if (this.server_settings && this.server_settings.client && this.server_settings.client.settings) {\r
                 this.applyDefaultClientSettings(this.server_settings.client.settings);\r
@@ -49,7 +52,7 @@
 \r
             this.view.barsHide(true);\r
 \r
-            this.showIntialConenctionDialog();\r
+            this.showStartup();\r
         },\r
 \r
 \r
         },\r
 \r
 \r
-        showIntialConenctionDialog: function() {\r
-            var connection_dialog = new _kiwi.model.NewConnection();\r
-            this.populateDefaultServerSettings(connection_dialog);\r
-\r
-            connection_dialog.view.$el.addClass('initial');\r
-            this.view.$el.find('.panel_container:first').append(connection_dialog.view.$el);\r
-\r
-            var $info = $($('#tmpl_new_connection_info').html().trim());\r
-\r
-            if ($info.html()) {\r
-                connection_dialog.view.infoBoxSet($info);\r
-                connection_dialog.view.infoBoxShow();\r
-            }\r
-\r
-            // TODO: Shouldn't really be here but it's not working in the view.. :/\r
-            // Hack for firefox browers: Focus is not given on this event loop iteration\r
-            setTimeout(function(){\r
-                connection_dialog.view.$el.find('.nick').select();\r
-            }, 0);\r
-\r
-            // Once connected, close this dialog and remove its own event\r
-            var fn = function() {\r
-                connection_dialog.view.$el.slideUp(function() {\r
-                    connection_dialog.view.dispose();\r
-                    connection_dialog = null;\r
-\r
-                    _kiwi.gateway.off('onconnect', fn);\r
-                });\r
-\r
-            };\r
-            _kiwi.gateway.on('onconnect', fn);\r
+        showStartup: function() {\r
+            this.startup_applet = _kiwi.model.Applet.load(this.startup_applet_name, {no_tab: true});\r
+            this.startup_applet.tab = this.view.$('.console');\r
+            this.startup_applet.view.show();\r
         },\r
 \r
 \r
         },\r
 \r
 \r
-        populateDefaultServerSettings: function (new_connection_dialog) {\r
-            var parts;\r
-            var defaults = {\r
-                nick: '',\r
-                server: '',\r
-                port: 6667,\r
-                ssl: false,\r
-                channel: '#chat',\r
-                channel_key: ''\r
-            };\r
-            var uricheck;\r
-\r
-\r
-            /**\r
-             * Get any settings set by the server\r
-             * These settings may be changed in the server selection dialog or via URL parameters\r
-             */\r
-            if (this.server_settings.client) {\r
-                if (this.server_settings.client.nick)\r
-                    defaults.nick = this.server_settings.client.nick;\r
-\r
-                if (this.server_settings.client.server)\r
-                    defaults.server = this.server_settings.client.server;\r
-\r
-                if (this.server_settings.client.port)\r
-                    defaults.port = this.server_settings.client.port;\r
-\r
-                if (this.server_settings.client.ssl)\r
-                    defaults.ssl = this.server_settings.client.ssl;\r
-\r
-                if (this.server_settings.client.channel)\r
-                    defaults.channel = this.server_settings.client.channel;\r
-\r
-                if (this.server_settings.client.channel_key)\r
-                    defaults.channel_key = this.server_settings.client.channel_key;\r
-            }\r
-\r
-\r
-\r
-            /**\r
-             * Get any settings passed in the URL\r
-             * These settings may be changed in the server selection dialog\r
-             */\r
-\r
-            // Any query parameters first\r
-            if (getQueryVariable('nick'))\r
-                defaults.nick = getQueryVariable('nick');\r
-\r
-            if (window.location.hash)\r
-                defaults.channel = window.location.hash;\r
-\r
-\r
-            // Process the URL part by part, extracting as we go\r
-            parts = window.location.pathname.toString().replace(this.get('base_path'), '').split('/');\r
-\r
-            if (parts.length > 0) {\r
-                parts.shift();\r
-\r
-                if (parts.length > 0 && parts[0]) {\r
-                    // Check to see if we're dealing with an irc: uri, or whether we need to extract the server/channel info from the HTTP URL path.\r
-                    uricheck = parts[0].substr(0, 7).toLowerCase();\r
-                    if ((uricheck === 'ircs%3a') || (uricheck.substr(0,6) === 'irc%3a')) {\r
-                        parts[0] = decodeURIComponent(parts[0]);\r
-                        // irc[s]://<host>[:<port>]/[<channel>[?<password>]]\r
-                        uricheck = /^irc(s)?:(?:\/\/?)?([^:\/]+)(?::([0-9]+))?(?:(?:\/)([^\?]*)(?:(?:\?)(.*))?)?$/.exec(parts[0]);\r
-                        /*\r
-                            uricheck[1] = ssl (optional)\r
-                            uricheck[2] = host\r
-                            uricheck[3] = port (optional)\r
-                            uricheck[4] = channel (optional)\r
-                            uricheck[5] = channel key (optional, channel must also be set)\r
-                        */\r
-                        if (uricheck) {\r
-                            if (typeof uricheck[1] !== 'undefined') {\r
-                                defaults.ssl = true;\r
-                                if (defaults.port === 6667) {\r
-                                    defaults.port = 6697;\r
-                                }\r
-                            }\r
-                            defaults.server = uricheck[2];\r
-                            if (typeof uricheck[3] !== 'undefined') {\r
-                                defaults.port = uricheck[3];\r
-                            }\r
-                            if (typeof uricheck[4] !== 'undefined') {\r
-                                defaults.channel = '#' + uricheck[4];\r
-                                if (typeof uricheck[5] !== 'undefined') {\r
-                                    defaults.channel_key = uricheck[5];\r
-                                }\r
-                            }\r
-                        }\r
-                        parts = [];\r
-                    } else {\r
-                        // Extract the port+ssl if we find one\r
-                        if (parts[0].search(/:/) > 0) {\r
-                            defaults.port = parts[0].substring(parts[0].search(/:/) + 1);\r
-                            defaults.server = parts[0].substring(0, parts[0].search(/:/));\r
-                            if (defaults.port[0] === '+') {\r
-                                defaults.port = parseInt(defaults.port.substring(1), 10);\r
-                                defaults.ssl = true;\r
-                            } else {\r
-                                defaults.ssl = false;\r
-                            }\r
-\r
-                        } else {\r
-                            defaults.server = parts[0];\r
-                        }\r
-\r
-                        parts.shift();\r
-                    }\r
-                }\r
-\r
-                if (parts.length > 0 && parts[0]) {\r
-                    defaults.channel = '#' + parts[0];\r
-                    parts.shift();\r
-                }\r
-            }\r
-\r
-            // If any settings have been given by the server.. override any auto detected settings\r
-            /**\r
-             * Get any server restrictions as set in the server config\r
-             * These settings can not be changed in the server selection dialog\r
-             */\r
-            if (this.server_settings && this.server_settings.connection) {\r
-                if (this.server_settings.connection.server) {\r
-                    defaults.server = this.server_settings.connection.server;\r
-                }\r
-\r
-                if (this.server_settings.connection.port) {\r
-                    defaults.port = this.server_settings.connection.port;\r
-                }\r
-\r
-                if (this.server_settings.connection.ssl) {\r
-                    defaults.ssl = this.server_settings.connection.ssl;\r
-                }\r
-\r
-                if (this.server_settings.connection.channel) {\r
-                    defaults.channel = this.server_settings.connection.channel;\r
-                }\r
-\r
-                if (this.server_settings.connection.channel_key) {\r
-                    defaults.channel_key = this.server_settings.connection.channel_key;\r
-                }\r
-\r
-                if (this.server_settings.connection.nick) {\r
-                    defaults.nick = this.server_settings.connection.nick;\r
-                }\r
-            }\r
-\r
-            // Set any random numbers if needed\r
-            defaults.nick = defaults.nick.replace('?', Math.floor(Math.random() * 100000).toString());\r
-\r
-            if (getQueryVariable('encoding'))\r
-                defaults.encoding = getQueryVariable('encoding');\r
-\r
-            // Populate the server select box with defaults\r
-            new_connection_dialog.view.populateFields(defaults);\r
-        },\r
-\r
-\r
         panels: (function() {\r
+            var active_panel;\r
+\r
             var fn = function(panel_type) {\r
                 var panels;\r
 \r
                 }\r
 \r
                 // Active panels / server\r
-                panels.active = this.connections.active_panel;\r
+                panels.active = active_panel;\r
                 panels.server = this.connections.active_connection ?\r
                     this.connections.active_connection.panels.server :\r
                     null;\r
 \r
             _.extend(fn, Backbone.Events);\r
 \r
+            // Keep track of the active panel. Channel/query/server or applet\r
+            fn.bind('active', function (new_active_panel) {\r
+                active_panel = new_active_panel;\r
+            });\r
+\r
             return fn;\r
         })(),\r
 \r
 \r
 \r
             fn_to_bind['command:ignore'] = function (ev) {\r
-                var list = _kiwi.gateway.get('ignore_list');\r
+                var list = this.connections.active_connection.get('ignore_list');\r
 \r
                 // No parameters passed so list them\r
                 if (!ev.params[0]) {\r
 \r
                 // We have a parameter, so add it\r
                 list.push(ev.params[0]);\r
-                _kiwi.gateway.set('ignore_list', list);\r
+                this.connections.active_connection.set('ignore_list', list);\r
                 _kiwi.app.panels().active.addMsg(' ', _kiwi.global.i18n.translate('client_models_application_ignore_nick').fetch(ev.params[0]));\r
             };\r
 \r
 \r
             fn_to_bind['command:unignore'] = function (ev) {\r
-                var list = _kiwi.gateway.get('ignore_list');\r
+                var list = this.connections.active_connection.get('ignore_list');\r
 \r
                 if (!ev.params[0]) {\r
                     _kiwi.app.panels().active.addMsg(' ', _kiwi.global.i18n.translate('client_models_application_ignore_stop_notice').fetch());\r
                     return pattern === ev.params[0];\r
                 });\r
 \r
-                _kiwi.gateway.set('ignore_list', list);\r
+                this.connections.active_connection.set('ignore_list', list);\r
 \r
                 _kiwi.app.panels().active.addMsg(' ', _kiwi.global.i18n.translate('client_models_application_ignore_stopped').fetch(ev.params[0]));\r
             };\r
     function unknownCommand (ev) {\r
         var raw_cmd = ev.command + ' ' + ev.params.join(' ');\r
         console.log('RAW: ' + raw_cmd);\r
-        _kiwi.gateway.raw(null, raw_cmd);\r
+        this.connections.active_connection.gateway.raw(raw_cmd);\r
     }\r
 \r
     function allCommands (ev) {}\r
         message = formatToIrcMsg(ev.params.join(' '));\r
 \r
         panel.addMsg(_kiwi.app.connections.active_connection.get('nick'), message);\r
-        _kiwi.gateway.privmsg(null, destination, message);\r
+        this.connections.active_connection.gateway.msg(destination, message);\r
     }\r
 \r
     function actionCommand (ev) {\r
 \r
         var panel = _kiwi.app.panels().active;\r
         panel.addMsg('', '* ' + _kiwi.app.connections.active_connection.get('nick') + ' ' + ev.params.join(' '), 'action');\r
-        _kiwi.gateway.action(null, panel.get('name'), ev.params.join(' '));\r
+        this.connections.active_connection.gateway.action(panel.get('name'), ev.params.join(' '));\r
     }\r
 \r
     function partCommand (ev) {\r
+        var that = this;\r
+\r
         if (ev.params.length === 0) {\r
-            _kiwi.gateway.part(null, _kiwi.app.panels().active.get('name'));\r
+            this.connections.active_connection.gateway.part(_kiwi.app.panels().active.get('name'));\r
         } else {\r
             _.each(ev.params, function (channel) {\r
-                _kiwi.gateway.part(null, channel);\r
+                that.connections.active_connection.gateway.part(channel);\r
             });\r
         }\r
     }\r
 \r
     function nickCommand (ev) {\r
-        _kiwi.gateway.changeNick(null, ev.params[0]);\r
+        this.connections.active_connection.gateway.changeNick(ev.params[0]);\r
     }\r
 \r
     function topicCommand (ev) {\r
             channel_name = _kiwi.app.panels().active.get('name');\r
         }\r
 \r
-        _kiwi.gateway.topic(null, channel_name, ev.params.join(' '));\r
+        this.connections.active_connection.gateway.topic(channel_name, ev.params.join(' '));\r
     }\r
 \r
     function noticeCommand (ev) {\r
         destination = ev.params[0];\r
         ev.params.shift();\r
 \r
-        _kiwi.gateway.notice(null, destination, ev.params.join(' '));\r
+        this.connections.active_connection.gateway.notice(destination, ev.params.join(' '));\r
     }\r
 \r
     function quoteCommand (ev) {\r
         var raw = ev.params.join(' ');\r
-        _kiwi.gateway.raw(null, raw);\r
+        this.connections.active_connection.gateway.raw(raw);\r
     }\r
 \r
     function kickCommand (ev) {\r
         nick = ev.params[0];\r
         ev.params.shift();\r
 \r
-        _kiwi.gateway.kick(null, panel.get('name'), nick, ev.params.join(' '));\r
+        this.connections.active_connection.gateway.kick(panel.get('name'), nick, ev.params.join(' '));\r
     }\r
 \r
     function clearCommand (ev) {\r
         type = ev.params[0];\r
         ev.params.shift();\r
 \r
-        _kiwi.gateway.ctcp(null, true, type, target, ev.params.join(' '));\r
+        this.connections.active_connection.gateway.ctcp(true, type, target, ev.params.join(' '));\r
     }\r
 \r
     function settingsCommand (ev) {\r
index 18d0538f97445511baae4d775ce06484c1d3e663..899c450999ea61ae2928b67e9a8e7254accb17dc 100644 (file)
@@ -110,5 +110,9 @@ _kiwi.model.Channel = _kiwi.model.Panel.extend({
 \r
     setMode: function(mode_string) {\r
         this.get('network').gateway.mode(this.get('name'), mode_string);\r
+    },\r
+\r
+    isChannel: function() {\r
+        return true;\r
     }\r
 });\r
index 7ee21fa5bd806a6c185e2d1f76599c540d8b4511..0744803a0677e735b5b736fa65f9d34a4b6746e1 100644 (file)
@@ -3,51 +3,6 @@ _kiwi.model.Gateway = function () {
     // Set to a reference to this object within initialize()\r
     var that = null;\r
 \r
-    this.defaults = {\r
-        /**\r
-        *   The name of the network\r
-        *   @type    String\r
-        */\r
-        name: 'Server',\r
-\r
-        /**\r
-        *   The address (URL) of the network\r
-        *   @type    String\r
-        */\r
-        address: '',\r
-\r
-        /**\r
-        *   The current nickname\r
-        *   @type   String\r
-        */\r
-        nick: '',\r
-\r
-        /**\r
-        *   The channel prefix for this network\r
-        *   @type    String\r
-        */\r
-        channel_prefix: '#',\r
-\r
-        /**\r
-        *   The user prefixes for channel owner/admin/op/voice etc. on this network\r
-        *   @type   Array\r
-        */\r
-        user_prefixes: ['~', '&', '@', '+'],\r
-\r
-        /**\r
-        *   The URL to the Kiwi server\r
-        *   @type   String\r
-        */\r
-        kiwi_server: '//kiwi',\r
-\r
-        /**\r
-        *   List of nicks we are ignoring\r
-        *   @type Array\r
-        */\r
-        ignore_list: []\r
-    };\r
-\r
-\r
     this.initialize = function () {\r
         that = this;\r
 \r
@@ -640,23 +595,6 @@ _kiwi.model.Gateway = function () {
         this.sendData(data, callback);\r
     };\r
 \r
-    // Check a nick alongside our ignore list\r
-    this.isNickIgnored = function (nick) {\r
-        var idx, list = this.get('ignore_list');\r
-        var pattern, regex;\r
-\r
-        for (idx = 0; idx < list.length; idx++) {\r
-            pattern = list[idx].replace(/([.+^$[\]\\(){}|-])/g, "\\$1")\r
-                .replace('*', '.*')\r
-                .replace('?', '.');\r
-\r
-            regex = new RegExp(pattern, 'i');\r
-            if (regex.test(nick)) return true;\r
-        }\r
-\r
-        return false;\r
-    };\r
-\r
 \r
     return new (Backbone.Model.extend(this))(arguments);\r
 };\r
index 3f0fab1240dd0c811a8ee7d72660bf62c1e3f548..0374d068d20aa490fc86b636868769622ba4770b 100644 (file)
             *   The user prefixes for channel owner/admin/op/voice etc. on this network
             *   @type   Array
             */
-            user_prefixes: ['~', '&', '@', '+']
+            user_prefixes: ['~', '&', '@', '+'],
+
+            /**
+            *   List of nicks we are ignoring
+            *   @type Array
+            */
+            ignore_list: []
         },
 
 
                 // Trim any whitespace off the name
                 channel_name = channel_name.trim();
 
-                // If not a valid channel name, display a warning
-                if (!_kiwi.app.isChannelName(channel_name)) {
-                    that.panels.server.addMsg('', _kiwi.global.i18n.translate('client_models_network_channel_invalid_name').fetch(channel_name));
-                    _kiwi.app.message.text(_kiwi.global.i18n.translate('client_models_network_channel_invalid_name').fetch(channel_name), {timeout: 5000});
-                    return;
+                // Add channel_prefix in front of the first channel if missing
+                if (that.get('channel_prefix').indexOf(channel_name[0]) === -1) {
+                    // Could be many prefixes but '#' is highly likely the required one
+                    channel_name = '#' + channel_name;
                 }
 
                 // Check if we have the panel already. If not, create it
 
                 that.gateway.join(panel.get('name'));
             });
+        },
+
+        isChannelName: function (channel_name) {
+            var channel_prefix = this.get('channel_prefix');
+
+            if (!channel_name || !channel_name.length) return false;
+            return (channel_prefix.indexOf(channel_name[0]) > -1);
+        },
+
+        // Check a nick alongside our ignore list
+        isNickIgnored: function (nick) {
+            var idx, list = this.get('ignore_list');
+            var pattern, regex;
+
+            for (idx = 0; idx < list.length; idx++) {
+                pattern = list[idx].replace(/([.+^$[\]\\(){}|-])/g, "\\$1")
+                    .replace('*', '.*')
+                    .replace('?', '.');
+
+                regex = new RegExp(pattern, 'i');
+                if (regex.test(nick)) return true;
+            }
+
+            return false;
         }
     });
 
             is_pm = (event.channel.toLowerCase() == this.get('nick').toLowerCase());
 
         // An ignored user? don't do anything with it
-        if (_kiwi.gateway.isNickIgnored(event.nick)) {
+        if (this.isNickIgnored(event.nick)) {
             return;
         }
 
 
     function onCtcpRequest(event) {
         // An ignored user? don't do anything with it
-        if (_kiwi.gateway.isNickIgnored(event.nick)) {
+        if (this.isNickIgnored(event.nick)) {
             return;
         }
 
 
     function onCtcpResponse(event) {
         // An ignored user? don't do anything with it
-        if (_kiwi.gateway.isNickIgnored(event.nick)) {
+        if (this.isNickIgnored(event.nick)) {
             return;
         }
 
 
 
     function onNotice(event) {
-        var panel, channel_name;
+        var panel, active_panel, channel_name;
 
         // An ignored user? don't do anything with it
-        if (!event.from_server && event.nick && _kiwi.gateway.isNickIgnored(event.nick)) {
+        if (!event.from_server && event.nick && this.isNickIgnored(event.nick)) {
             return;
         }
 
 
         panel.addMsg('[' + (event.nick||'') + ']', event.msg, 'notice', {time: event.time});
 
-        // Show this notice to the active panel if it didn't have a set target
-        if (!event.from_server && panel === this.panels.server && _kiwi.app.panels().active !== this.panels.server)
-            _kiwi.app.panels().active.addMsg('[' + (event.nick||'') + ']', event.msg, 'notice', {time: event.time});
+        // Show this notice to the active panel if it didn't have a set target, but only in an active channel or query window
+        active_panel = _kiwi.app.panels().active;
+
+        if (!event.from_server && panel === this.panels.server && active_panel !== this.panels.server) {
+            if (active_panel.isChannel() || active_panel.isQuery())
+                active_panel.addMsg('[' + (event.nick||'') + ']', event.msg, 'notice', {time: event.time});
+        }
     }
 
 
             is_pm = (event.channel.toLowerCase() == this.get('nick').toLowerCase());
 
         // An ignored user? don't do anything with it
-        if (_kiwi.gateway.isNickIgnored(event.nick)) {
+        if (this.isNickIgnored(event.nick)) {
             return;
         }
 
 
 
     function onBanlist(event) {
-        console.log('banlist', event);
         var channel = this.panels.getByName(event.channel);
         if (!channel)
             return;
 
             member = panel.get('members').getByNick(event.nick);
             if (member) {
-                member.set('away', !(!event.trailing));
+                member.set('away', !(!event.reason));
             }
         });
     }
             display_params.shift();
         }
 
-        if (event.trailing)
-            display_params.push(event.trailing);
-
         this.panels.server.addMsg('', '[' + event.command + '] ' + display_params.join(', ', ''));
     }
 }
index 90db39b1ab5b4aa22743694353ff5b44a9209592..a2e16e79612e1fcf8cf3f2510229db7d740e9ad5 100644 (file)
 _kiwi.model.NewConnection = Backbone.Collection.extend({
     initialize: function() {
-        this.view = new _kiwi.view.ServerSelect();
+        this.view = new _kiwi.view.ServerSelect({model: this});
 
         this.view.bind('server_connect', this.onMakeConnection, this);
 
     },
 
 
+    populateDefaultServerSettings: function () {
+        var parts;
+        var defaults = {
+            nick: '',
+            server: '',
+            port: 6667,
+            ssl: false,
+            channel: '',
+            channel_key: ''
+        };
+        var uricheck;
+
+
+        /**
+         * Get any settings set by the server
+         * These settings may be changed in the server selection dialog or via URL parameters
+         */
+        if (_kiwi.app.server_settings.client) {
+            if (_kiwi.app.server_settings.client.nick)
+                defaults.nick = _kiwi.app.server_settings.client.nick;
+
+            if (_kiwi.app.server_settings.client.server)
+                defaults.server = _kiwi.app.server_settings.client.server;
+
+            if (_kiwi.app.server_settings.client.port)
+                defaults.port = _kiwi.app.server_settings.client.port;
+
+            if (_kiwi.app.server_settings.client.ssl)
+                defaults.ssl = _kiwi.app.server_settings.client.ssl;
+
+            if (_kiwi.app.server_settings.client.channel)
+                defaults.channel = _kiwi.app.server_settings.client.channel;
+
+            if (_kiwi.app.server_settings.client.channel_key)
+                defaults.channel_key = _kiwi.app.server_settings.client.channel_key;
+        }
+
+
+
+        /**
+         * Get any settings passed in the URL
+         * These settings may be changed in the server selection dialog
+         */
+
+        // Any query parameters first
+        if (getQueryVariable('nick'))
+            defaults.nick = getQueryVariable('nick');
+
+        if (window.location.hash)
+            defaults.channel = window.location.hash;
+
+
+        // Process the URL part by part, extracting as we go
+        parts = window.location.pathname.toString().replace(_kiwi.app.get('base_path'), '').split('/');
+
+        if (parts.length > 0) {
+            parts.shift();
+
+            if (parts.length > 0 && parts[0]) {
+                // Check to see if we're dealing with an irc: uri, or whether we need to extract the server/channel info from the HTTP URL path.
+                uricheck = parts[0].substr(0, 7).toLowerCase();
+                if ((uricheck === 'ircs%3a') || (uricheck.substr(0,6) === 'irc%3a')) {
+                    parts[0] = decodeURIComponent(parts[0]);
+                    // irc[s]://<host>[:<port>]/[<channel>[?<password>]]
+                    uricheck = /^irc(s)?:(?:\/\/?)?([^:\/]+)(?::([0-9]+))?(?:(?:\/)([^\?]*)(?:(?:\?)(.*))?)?$/.exec(parts[0]);
+                    /*
+                        uricheck[1] = ssl (optional)
+                        uricheck[2] = host
+                        uricheck[3] = port (optional)
+                        uricheck[4] = channel (optional)
+                        uricheck[5] = channel key (optional, channel must also be set)
+                    */
+                    if (uricheck) {
+                        if (typeof uricheck[1] !== 'undefined') {
+                            defaults.ssl = true;
+                            if (defaults.port === 6667) {
+                                defaults.port = 6697;
+                            }
+                        }
+                        defaults.server = uricheck[2];
+                        if (typeof uricheck[3] !== 'undefined') {
+                            defaults.port = uricheck[3];
+                        }
+                        if (typeof uricheck[4] !== 'undefined') {
+                            defaults.channel = '#' + uricheck[4];
+                            if (typeof uricheck[5] !== 'undefined') {
+                                defaults.channel_key = uricheck[5];
+                            }
+                        }
+                    }
+                    parts = [];
+                } else {
+                    // Extract the port+ssl if we find one
+                    if (parts[0].search(/:/) > 0) {
+                        defaults.port = parts[0].substring(parts[0].search(/:/) + 1);
+                        defaults.server = parts[0].substring(0, parts[0].search(/:/));
+                        if (defaults.port[0] === '+') {
+                            defaults.port = parseInt(defaults.port.substring(1), 10);
+                            defaults.ssl = true;
+                        } else {
+                            defaults.ssl = false;
+                        }
+
+                    } else {
+                        defaults.server = parts[0];
+                    }
+
+                    parts.shift();
+                }
+            }
+
+            if (parts.length > 0 && parts[0]) {
+                defaults.channel = '#' + parts[0];
+                parts.shift();
+            }
+        }
+
+        // If any settings have been given by the server.. override any auto detected settings
+        /**
+         * Get any server restrictions as set in the server config
+         * These settings can not be changed in the server selection dialog
+         */
+        if (_kiwi.app.server_settings && _kiwi.app.server_settings.connection) {
+            if (_kiwi.app.server_settings.connection.server) {
+                defaults.server = _kiwi.app.server_settings.connection.server;
+            }
+
+            if (_kiwi.app.server_settings.connection.port) {
+                defaults.port = _kiwi.app.server_settings.connection.port;
+            }
+
+            if (_kiwi.app.server_settings.connection.ssl) {
+                defaults.ssl = _kiwi.app.server_settings.connection.ssl;
+            }
+
+            if (_kiwi.app.server_settings.connection.channel) {
+                defaults.channel = _kiwi.app.server_settings.connection.channel;
+            }
+
+            if (_kiwi.app.server_settings.connection.channel_key) {
+                defaults.channel_key = _kiwi.app.server_settings.connection.channel_key;
+            }
+
+            if (_kiwi.app.server_settings.connection.nick) {
+                defaults.nick = _kiwi.app.server_settings.connection.nick;
+            }
+        }
+
+        // Set any random numbers if needed
+        defaults.nick = defaults.nick.replace('?', Math.floor(Math.random() * 100000).toString());
+
+        if (getQueryVariable('encoding'))
+            defaults.encoding = getQueryVariable('encoding');
+
+        this.view.populateFields(defaults);
+    },
+
+
     onMakeConnection: function(new_connection_event) {
         var that = this,
             transport_path = '',
@@ -62,12 +220,8 @@ _kiwi.model.NewConnection = Backbone.Collection.extend({
                 channel: this.connect_details.channel,
                 key: this.connect_details.channel_key
             };
-        }
-
 
-        // Show the server panel if this is our first network
-        if (network && network.get('connection_id') === 0) {
-            network.panels.server.view.show();
+            this.trigger('new_network', network);
         }
     }
 });
\ No newline at end of file
index 943658e7acdd697225545673afe79fd90317d201..1a6c43ffa314216480daed09472117fbe59a1df7 100644 (file)
@@ -26,11 +26,6 @@ _kiwi.model.Panel = Backbone.Model.extend({
 \r
         this.unbind();\r
         this.destroy();\r
-\r
-        // If closing the active panel, switch to the server panel\r
-        if (this === _kiwi.app.panels().active) {\r
-            _kiwi.app.connections.active_connection.panels.server.view.show();\r
-        }\r
     },\r
 \r
     // Alias to closePanel() for child objects to override\r
@@ -39,27 +34,19 @@ _kiwi.model.Panel = Backbone.Model.extend({
     },\r
 \r
     isChannel: function () {\r
-        var channel_prefix = _kiwi.gateway.get('channel_prefix'),\r
-            this_name = this.get('name');\r
-\r
-        if (this.isApplet() || !this_name) return false;\r
-        return (channel_prefix.indexOf(this_name[0]) > -1);\r
+        return false;\r
     },\r
 \r
     isQuery: function () {\r
-        if (!this.isChannel() && !this.isApplet() && !this.isServer()) {\r
-            return true;\r
-        }\r
-\r
         return false;\r
     },\r
 \r
     isApplet: function () {\r
-        return this.applet ? true : false;\r
+        return false;\r
     },\r
 \r
     isServer: function () {\r
-        return this.server ? true : false;\r
+        return false;\r
     },\r
 \r
     isActive: function () {\r
index 3cf82ff4cbfed86f81f10cf87c24ff0cdaaa07a6..293be21b1eec1365e12e46ee103b834a48ec784a 100644 (file)
@@ -8,5 +8,13 @@ _kiwi.model.Query = _kiwi.model.Channel.extend({
             "name": name,\r
             "scrollback": []\r
         }, {"silent": true});\r
+    },\r
+\r
+    isChannel: function () {\r
+        return false;\r
+    },\r
+\r
+    isQuery: function () {\r
+        return true;\r
     }\r
 });
\ No newline at end of file
index f3017c22e46f9425c7d385ef79001c260b8b8c96..3410394e7ccc4d683f0db891321b66e0d138797b 100644 (file)
@@ -1,7 +1,4 @@
 _kiwi.model.Server = _kiwi.model.Channel.extend({\r
-    // Used to determine if this is a server panel\r
-    server: true,\r
-\r
     initialize: function (attributes) {\r
         var name = "Server";\r
         this.view = new _kiwi.view.Channel({"model": this, "name": name});\r
@@ -11,5 +8,13 @@ _kiwi.model.Server = _kiwi.model.Channel.extend({
         }, {"silent": true});\r
 \r
         //this.addMsg(' ', '--> Kiwi IRC: Such an awesome IRC client', '', {style: 'color:#009900;'});\r
+    },\r
+\r
+    isServer: function () {\r
+        return true;\r
+    },\r
+\r
+    isChannel: function () {\r
+        return false;\r
     }\r
 });
\ No newline at end of file
index 5f40c209dbc2f5c79aa198c8a007ed7bac1d4957..1cfccc2606394b2a9e86ee6da625d5199769e56b 100755 (executable)
@@ -66,7 +66,11 @@ msgstr "Join/part channel notifications"
 
 #: 
 msgid "client_applets_settings_timestamp"
-msgstr "Timestamps"
+msgstr "Show timestamps"
+
+#: 
+msgid "client_applets_settings_timestamp_24_hour"
+msgstr "Use 24-hour timestamps"
 
 #: 
 msgid "client_applets_settings_notification_sound"
@@ -320,6 +324,14 @@ msgstr "Cancel"
 msgid "client_views_panel_activity"
 msgstr "People are talking!"
 
+#:
+msgid "client_views_panel_timestamp_am"
+msgstr "%s AM"
+
+#:
+msgid "client_views_panel_timestamp_pm"
+msgstr "%s PM"
+
 #: client/assets/src/views/serverselect.js
 msgid "client_views_serverselect_form_title"
 msgstr "Think of a nickname..."
index 1fc51486749d7a155777f371afca1f5d676c9110..5d4b87b8b96337009008d0ec9c5eb3546e607c1d 100644 (file)
@@ -1,12 +1,19 @@
 _kiwi.view.AppToolbar = Backbone.View.extend({
     events: {
-        'click .settings': 'clickSettings'
+        'click .settings': 'clickSettings',
+        'click .startup': 'clickStartup'
     },
 
     initialize: function () {
     },
 
     clickSettings: function (event) {
+        event.preventDefault();
         _kiwi.app.controlbox.processInput('/settings');
-    }
+    },
+
+    clickStartup: function (event) {
+        event.preventDefault();
+        _kiwi.app.startup_applet.view.show();
+    },
 });
\ No newline at end of file
index cac53655b4238e4c04f0611c109b75215d0d517f..db2122f7882886f76c4eb36841bb431d4018623e 100644 (file)
@@ -58,7 +58,8 @@ _kiwi.view.Channel = _kiwi.view.Panel.extend({
             nick_colour_hex, nick_hex, is_highlight, msg_css_classes = '',
             time_difference,
             sb = this.model.get('scrollback'),
-            prev_msg = sb[sb.length-2];
+            prev_msg = sb[sb.length-2],
+            network, hour, pm;
 
         // Nick highlight detecting
         if ((new RegExp('(^|\\W)(' + escapeRegex(_kiwi.app.connections.active_connection.get('nick')) + ')(\\W|$)', 'i')).test(msg.msg)) {
@@ -70,10 +71,12 @@ _kiwi.view.Channel = _kiwi.view.Panel.extend({
         msg.msg =  $('<div />').text(msg.msg).html();
 
         // Make the channels clickable
-        re = new RegExp('(?:^|\\s)([' + escapeRegex(_kiwi.gateway.get('channel_prefix')) + '][^ ,\\007]+)', 'g');
-        msg.msg = msg.msg.replace(re, function (match) {
-            return '<a class="chan" data-channel="' + match.trim() + '">' + match + '</a>';
-        });
+        if ((network = this.model.get('network'))) {
+            re = new RegExp('(?:^|\\s)([' + escapeRegex(network.get('channel_prefix')) + '][^ ,\\007]+)', 'g');
+            msg.msg = msg.msg.replace(re, function (match) {
+                return '<a class="chan" data-channel="' + match.trim() + '">' + match + '</a>';
+            });
+        }
 
 
         // Parse any links found
@@ -139,7 +142,22 @@ _kiwi.view.Channel = _kiwi.view.Panel.extend({
 
         // Build up and add the line
         msg.msg_css_classes = msg_css_classes;
-        msg.time_string = msg.time.getHours().toString().lpad(2, "0") + ":" + msg.time.getMinutes().toString().lpad(2, "0") + ":" + msg.time.getSeconds().toString().lpad(2, "0");
+        if (_kiwi.global.settings.get('use_24_hour_timestamps')) {
+            msg.time_string = msg.time.getHours().toString().lpad(2, "0") + ":" + msg.time.getMinutes().toString().lpad(2, "0") + ":" + msg.time.getSeconds().toString().lpad(2, "0");
+        } else {
+            hour = msg.time.getHours();
+            pm = hour > 11;
+
+            hour = hour % 12;
+            if (hour === 0)
+                hour = 12;
+
+            if (pm) {
+                msg.time_string = _kiwi.global.i18n.translate('client_views_panel_timestamp_pm').fetch(hour + ":" + msg.time.getMinutes().toString().lpad(2, "0") + ":" + msg.time.getSeconds().toString().lpad(2, "0"));
+            } else {
+                msg.time_string = _kiwi.global.i18n.translate('client_views_panel_timestamp_am').fetch(hour + ":" + msg.time.getMinutes().toString().lpad(2, "0") + ":" + msg.time.getSeconds().toString().lpad(2, "0"));
+            }
+        }
         line_msg = '<div class="msg <%= type %> <%= msg_css_classes %>"><div class="time"><%- time_string %></div><div class="nick" style="<%= nick_style %>"><%- nick %></div><div class="text" style="<%= style %>"><%= msg %> </div></div>';
         this.$messages.append(_.template(line_msg, msg));
 
@@ -198,7 +216,7 @@ _kiwi.view.Channel = _kiwi.view.Panel.extend({
                 'action mode'
             ];
 
-            if (count_all_activity || exclude_message_types.indexOf(msg.type) === -1) {
+            if (count_all_activity || _.indexOf(exclude_message_types, msg.type) === -1) {
                 $act.text((parseInt($act.text(), 10) || 0) + 1);
             }
 
@@ -209,7 +227,7 @@ _kiwi.view.Channel = _kiwi.view.Panel.extend({
             }
         }).apply(this);
 
-        this.scrollToBottom();
+        if(this.model.isActive()) this.scrollToBottom();
 
         // Make sure our DOM isn't getting too large (Acts as scrollback)
         this.msg_count++;
@@ -249,7 +267,7 @@ _kiwi.view.Channel = _kiwi.view.Panel.extend({
 
                 menubox = new _kiwi.view.MenuBox(member.get('nick') || 'User');
                 menubox.addItem('userbox', userbox.$el);
-                menu.showFooter(false);
+                menubox.showFooter(false);
                 menubox.show();
 
                 // Position the userbox + menubox
@@ -275,12 +293,9 @@ _kiwi.view.Channel = _kiwi.view.Panel.extend({
 
 
     chanClick: function (event) {
-        if (event.target) {
-            _kiwi.gateway.join(null, $(event.target).data('channel'));
-        } else {
-            // IE...
-            _kiwi.gateway.join(null, $(event.srcElement).data('channel'));
-        }
+        var target = (event.target) ? $(event.target).data('channel') : $(event.srcElement).data('channel');
+
+        _kiwi.app.connections.active_connection.gateway.join(target);
     },
 
 
index ffbfda06eeab9e4e05801e8fd78e0733a14841ae..bc98fdf3d4e3e8e1bc562b6baa6d3f249d703b7b 100644 (file)
@@ -11,6 +11,6 @@ _kiwi.view.ChannelTools = Backbone.View.extend({
     },
 
     partClick: function (event) {
-        _kiwi.gateway.part(null, _kiwi.app.panels().active.get('name'));
+        _kiwi.app.connections.active_connection.gateway.part(_kiwi.app.panels().active.get('name'));
     }
 });
\ No newline at end of file
index 369c1ddaa500b74e6ee13827e71ea8ecebc0537a..f7f09d4c1198f64711c6d251bd031adc021fb59d 100644 (file)
@@ -132,14 +132,65 @@ _kiwi.view.MediaMessage = Backbone.View.extend({
             });
 
             return $('<div>' + _kiwi.global.i18n.translate('client_views_mediamessage_load_gist').fetch() + '...</div>');
-        }
+        },
+
+        spotify: function () {
+            var uri = this.$el.data('uri');
+            var method = this.$el.data('method');
+            var that = this;
+
+            switch (method) {
+                case "track":
+                case "album":
+                     var spot = {
+                         url: 'https://embed.spotify.com/?uri=' + uri,
+                         width: 300,
+                         height: 80 
+                     };
+                     break;
+                case "artist":
+                     var spot = {
+                         url: 'https://embed.spotify.com/follow/1/?uri=' + uri +'&size=detail&theme=dark',
+                         width: 300,
+                         height: 56
+                     };
+                     break;
+            };
+
+            var html = '<iframe src="' + spot.url + '" width="' + spot.width + '" height="' + spot.height + '" frameborder="0" allowtransparency="true"></iframe>';
+
+            return $(html);
+        },
+
+
     }
     }, {
 
+    /**
+     * Add a media message type to append HTML after a matching URL
+     * match() should return true if it wants to handle this URL
+     * buildHtml() should return the HTML string to append after the URL in the message
+     */
+    addType: function(match, buildHtml) {
+        if (typeof match !== 'function' || typeof buildHtml !== 'function')
+            return;
+
+        this.types = this.types || [];
+        this.types.push({match: match, buildHtml: buildHtml});
+    },
+
+
     // Build the closed media HTML from a URL
     buildHtml: function (url) {
         var html = '', matches;
 
+        _.each(this.types || [], function(type) {
+            if (!type.match(url))
+                return;
+
+            html += type.buildHtml(url);
+        });
+
         // Is it an image?
         if (url.match(/(\.jpe?g|\.gif|\.bmp|\.png)\??$/i)) {
             html += '<span class="media image" data-type="image" data-url="' + url + '" title="Open Image"><a class="open"><i class="icon-chevron-right"></i></a></span>';
@@ -175,6 +226,15 @@ _kiwi.view.MediaMessage = Backbone.View.extend({
             html += '<span class="media gist" data-type="gist" data-url="' + url + '" data-gist_id="' + matches[1] + '" title="GitHub Gist"><a class="open"><i class="icon-chevron-right"></i></a></span>';
         }
 
+        // Is this a spotify link?
+        matches = (/http:\/\/(?:play|open\.)?spotify.com\/(album|track|artist)\/([a-zA-Z0-9]+)\/?/i).exec(url);
+        if (matches) {
+            // Make it a Spotify URI! (spotify:<type>:<id>)
+            var method = matches[1],
+                uri = "spotify:" + matches[1] + ":" + matches[2];
+            html += '<span class="media spotify" data-type="spotify" data-uri="' + uri + '" data-method="' + method + '" title="Spotify ' + method + '"><a class="open"><i class="icon-chevron-right"></i></a></span>';
+        }
+
         return html;
     }
 });
index 3827def17f4e7b7aee188fdb86ec2948f7752394..c22d6f07e155e4620669031c0dce93a56fedd33c 100644 (file)
@@ -57,7 +57,8 @@ _kiwi.view.Panel = Backbone.View.extend({
 
         _kiwi.app.view.doLayout();
 
-        this.scrollToBottom(true);
+        if (!this.model.isApplet())
+            this.scrollToBottom(true);
     },
 
 
index ceb11dafff8159eebe894f569f6b8a06603a8f9f..ded2203c435634ab7d1a013f117e97db90a0c058 100644 (file)
-_kiwi.view.ServerSelect = function () {
-    // Are currently showing all the controlls or just a nick_change box?
-    var state = 'all';
-
-    var model = Backbone.View.extend({
-        events: {
-            'submit form': 'submitForm',
-            'click .show_more': 'showMore',
-            'change .have_pass input': 'showPass',
-            'change .have_key input': 'showKey',
-            'click .icon-key': 'channelKeyIconClick'
-        },
-
-        initialize: function () {
-            var that = this,
-                text = {
-                    think_nick: _kiwi.global.i18n.translate('client_views_serverselect_form_title').fetch(),
-                    nickname: _kiwi.global.i18n.translate('client_views_serverselect_nickname').fetch(),
-                    have_password: _kiwi.global.i18n.translate('client_views_serverselect_enable_password').fetch(),
-                    password: _kiwi.global.i18n.translate('client_views_serverselect_password').fetch(),
-                    channel: _kiwi.global.i18n.translate('client_views_serverselect_channel').fetch(),
-                    channel_key: _kiwi.global.i18n.translate('client_views_serverselect_channelkey').fetch(),
-                    require_key: _kiwi.global.i18n.translate('client_views_serverselect_channelkey_required').fetch(),
-                    key: _kiwi.global.i18n.translate('client_views_serverselect_key').fetch(),
-                    start: _kiwi.global.i18n.translate('client_views_serverselect_connection_start').fetch(),
-                    server_network: _kiwi.global.i18n.translate('client_views_serverselect_server_and_network').fetch(),
-                    server: _kiwi.global.i18n.translate('client_views_serverselect_server').fetch(),
-                    port: _kiwi.global.i18n.translate('client_views_serverselect_port').fetch(),
-                    powered_by: _kiwi.global.i18n.translate('client_views_serverselect_poweredby').fetch()
-                };
-
-            this.$el = $(_.template($('#tmpl_server_select').html().trim(), text));
-
-            // Remove the 'more' link if the server has disabled server changing
-            if (_kiwi.app.server_settings && _kiwi.app.server_settings.connection) {
-                if (!_kiwi.app.server_settings.connection.allow_change) {
-                    this.$el.find('.show_more').remove();
-                    this.$el.addClass('single_server');
-                }
-            }
+_kiwi.view.ServerSelect = Backbone.View.extend({
+    events: {
+        'submit form': 'submitForm',
+        'click .show_more': 'showMore',
+        'change .have_pass input': 'showPass',
+        'change .have_key input': 'showKey',
+        'click .icon-key': 'channelKeyIconClick',
+        'click .show_server': 'showServer'
+    },
+
+    initialize: function () {
+        var that = this,
+            text = {
+                think_nick: _kiwi.global.i18n.translate('client_views_serverselect_form_title').fetch(),
+                nickname: _kiwi.global.i18n.translate('client_views_serverselect_nickname').fetch(),
+                have_password: _kiwi.global.i18n.translate('client_views_serverselect_enable_password').fetch(),
+                password: _kiwi.global.i18n.translate('client_views_serverselect_password').fetch(),
+                channel: _kiwi.global.i18n.translate('client_views_serverselect_channel').fetch(),
+                channel_key: _kiwi.global.i18n.translate('client_views_serverselect_channelkey').fetch(),
+                require_key: _kiwi.global.i18n.translate('client_views_serverselect_channelkey_required').fetch(),
+                key: _kiwi.global.i18n.translate('client_views_serverselect_key').fetch(),
+                start: _kiwi.global.i18n.translate('client_views_serverselect_connection_start').fetch(),
+                server_network: _kiwi.global.i18n.translate('client_views_serverselect_server_and_network').fetch(),
+                server: _kiwi.global.i18n.translate('client_views_serverselect_server').fetch(),
+                port: _kiwi.global.i18n.translate('client_views_serverselect_port').fetch(),
+                powered_by: _kiwi.global.i18n.translate('client_views_serverselect_poweredby').fetch()
+            };
 
-            this.more_shown = false;
+        this.$el = $(_.template($('#tmpl_server_select').html().trim(), text));
+
+        // Remove the 'more' link if the server has disabled server changing
+        if (_kiwi.app.server_settings && _kiwi.app.server_settings.connection) {
+            if (!_kiwi.app.server_settings.connection.allow_change) {
+                this.$el.find('.show_more').remove();
+                this.$el.addClass('single_server');
+            }
+        }
 
-            _kiwi.gateway.bind('onconnect', this.networkConnected, this);
-            _kiwi.gateway.bind('connecting', this.networkConnecting, this);
-            _kiwi.gateway.bind('onirc_error', this.onIrcError, this);
-        },
+        // Are currently showing all the controlls or just a nick_change box?
+        this.state = 'all';
 
-        dispose: function() {
-            _kiwi.gateway.off('onconnect', this.networkConnected, this);
-            _kiwi.gateway.off('connecting', this.networkConnecting, this);
-            _kiwi.gateway.off('onirc_error', this.onIrcError, this);
+        this.more_shown = false;
 
-            this.$el.remove();
-        },
+        this.model.bind('new_network', this.newNetwork, this);
+        _kiwi.gateway.bind('onconnect', this.networkConnected, this);
+        _kiwi.gateway.bind('connecting', this.networkConnecting, this);
+        _kiwi.gateway.bind('onirc_error', this.onIrcError, this);
+    },
 
-        submitForm: function (event) {
-            event.preventDefault();
+    dispose: function() {
+        this.model.off('new_network', this.newNetwork, this);
+        _kiwi.gateway.off('onconnect', this.networkConnected, this);
+        _kiwi.gateway.off('connecting', this.networkConnecting, this);
+        _kiwi.gateway.off('onirc_error', this.onIrcError, this);
 
-            // Make sure a nick is chosen
-            if (!$('input.nick', this.$el).val().trim()) {
-                this.setStatus(_kiwi.global.i18n.translate('client_views_serverselect_nickname_error_empty').fetch());
-                $('input.nick', this.$el).select();
-                return;
-            }
+        this.remove();
+    },
 
-            if (state === 'nick_change') {
-                this.submitNickChange(event);
-            } else {
-                this.submitLogin(event);
-            }
+    submitForm: function (event) {
+        event.preventDefault();
 
-            $('button', this.$el).attr('disabled', 1);
+        // Make sure a nick is chosen
+        if (!$('input.nick', this.$el).val().trim()) {
+            this.setStatus(_kiwi.global.i18n.translate('client_views_serverselect_nickname_error_empty').fetch());
+            $('input.nick', this.$el).select();
             return;
-        },
-
-        submitLogin: function (event) {
-            // If submitting is disabled, don't do anything
-            if ($('button', this.$el).attr('disabled')) return;
-
-            var values = {
-                nick: $('input.nick', this.$el).val(),
-                server: $('input.server', this.$el).val(),
-                port: $('input.port', this.$el).val(),
-                ssl: $('input.ssl', this.$el).prop('checked'),
-                password: $('input.password', this.$el).val(),
-                channel: $('input.channel', this.$el).val(),
-                channel_key: $('input.channel_key', this.$el).val(),
-                options: this.server_options
-            };
+        }
 
-            this.trigger('server_connect', values);
-        },
+        if (this.state === 'nick_change') {
+            this.submitNickChange(event);
+        } else {
+            this.submitLogin(event);
+        }
 
-        submitNickChange: function (event) {
-            _kiwi.gateway.changeNick(null, $('input.nick', this.$el).val());
-            this.networkConnecting();
-        },
+        $('button', this.$el).attr('disabled', 1);
+        return;
+    },
+
+    submitLogin: function (event) {
+        // If submitting is disabled, don't do anything
+        if ($('button', this.$el).attr('disabled')) return;
+
+        var values = {
+            nick: $('input.nick', this.$el).val(),
+            server: $('input.server', this.$el).val(),
+            port: $('input.port', this.$el).val(),
+            ssl: $('input.ssl', this.$el).prop('checked'),
+            password: $('input.password', this.$el).val(),
+            channel: $('input.channel', this.$el).val(),
+            channel_key: $('input.channel_key', this.$el).val(),
+            options: this.server_options
+        };
+
+        this.trigger('server_connect', values);
+    },
+
+    submitNickChange: function (event) {
+        _kiwi.gateway.changeNick(null, $('input.nick', this.$el).val());
+        this.networkConnecting();
+    },
+
+    showPass: function (event) {
+        if (this.$el.find('tr.have_pass input').is(':checked')) {
+            this.$el.find('tr.pass').show().find('input').focus();
+        } else {
+            this.$el.find('tr.pass').hide().find('input').val('');
+        }
+    },
 
-        showPass: function (event) {
-            if (this.$el.find('tr.have_pass input').is(':checked')) {
-                this.$el.find('tr.pass').show().find('input').focus();
-            } else {
-                this.$el.find('tr.pass').hide().find('input').val('');
-            }
-        },
+    channelKeyIconClick: function (event) {
+        this.$el.find('tr.have_key input').click();
+    },
 
-        channelKeyIconClick: function (event) {
-            this.$el.find('tr.have_key input').click();
-        },
+    showKey: function (event) {
+        if (this.$el.find('tr.have_key input').is(':checked')) {
+            this.$el.find('tr.key').show().find('input').focus();
+        } else {
+            this.$el.find('tr.key').hide().find('input').val('');
+        }
+    },
+
+    showMore: function (event) {
+        if (!this.more_shown) {
+            $('.more', this.$el).slideDown('fast');
+            $('.show_more', this.$el)
+                .children('.icon-caret-down')
+                .removeClass('icon-caret-down')
+                .addClass('icon-caret-up');
+            $('input.server', this.$el).select();
+            this.more_shown = true;
+        } else {
+            $('.more', this.$el).slideUp('fast');
+            $('.show_more', this.$el)
+                .children('.icon-caret-up')
+                .removeClass('icon-caret-up')
+                .addClass('icon-caret-down');
+            $('input.nick', this.$el).select();
+            this.more_shown = false;
+        }
+    },
+
+    populateFields: function (defaults) {
+        var nick, server, port, channel, channel_key, ssl, password;
+
+        defaults = defaults || {};
+
+        nick = defaults.nick || '';
+        server = defaults.server || '';
+        port = defaults.port || 6667;
+        ssl = defaults.ssl || 0;
+        password = defaults.password || '';
+        channel = defaults.channel || '';
+        channel_key = defaults.channel_key || '';
+
+        $('input.nick', this.$el).val(nick);
+        $('input.server', this.$el).val(server);
+        $('input.port', this.$el).val(port);
+        $('input.ssl', this.$el).prop('checked', ssl);
+        $('input#server_select_show_pass', this.$el).prop('checked', !(!password));
+        $('input.password', this.$el).val(password);
+        if (!(!password)) {
+            $('tr.pass', this.$el).show();
+        }
+        $('input.channel', this.$el).val(channel);
+        $('input#server_select_show_channel_key', this.$el).prop('checked', !(!channel_key));
+        $('input.channel_key', this.$el).val(channel_key);
+        if (!(!channel_key)) {
+            $('tr.key', this.$el).show();
+        }
 
-        showKey: function (event) {
-            if (this.$el.find('tr.have_key input').is(':checked')) {
-                this.$el.find('tr.key').show().find('input').focus();
-            } else {
-                this.$el.find('tr.key').hide().find('input').val('');
-            }
-        },
-
-        showMore: function (event) {
-            if (!this.more_shown) {
-                $('.more', this.$el).slideDown('fast');
-                $('.show_more', this.$el)
-                    .children('.icon-caret-down')
-                    .removeClass('icon-caret-down')
-                    .addClass('icon-caret-up');
-                $('input.server', this.$el).select();
-                this.more_shown = true;
-            } else {
-                $('.more', this.$el).slideUp('fast');
-                $('.show_more', this.$el)
-                    .children('.icon-caret-up')
-                    .removeClass('icon-caret-up')
-                    .addClass('icon-caret-down');
-                $('input.nick', this.$el).select();
-                this.more_shown = false;
-            }
-        },
-
-        populateFields: function (defaults) {
-            var nick, server, port, channel, channel_key, ssl, password;
-
-            defaults = defaults || {};
-
-            nick = defaults.nick || '';
-            server = defaults.server || '';
-            port = defaults.port || 6667;
-            ssl = defaults.ssl || 0;
-            password = defaults.password || '';
-            channel = defaults.channel || '';
-            channel_key = defaults.channel_key || '';
-
-            $('input.nick', this.$el).val(nick);
-            $('input.server', this.$el).val(server);
-            $('input.port', this.$el).val(port);
-            $('input.ssl', this.$el).prop('checked', ssl);
-            $('input#server_select_show_pass', this.$el).prop('checked', !(!password));
-            $('input.password', this.$el).val(password);
-            if (!(!password)) {
-                $('tr.pass', this.$el).show();
-            }
-            $('input.channel', this.$el).val(channel);
-            $('input#server_select_show_channel_key', this.$el).prop('checked', !(!channel_key));
-            $('input.channel_key', this.$el).val(channel_key);
-            if (!(!channel_key)) {
-                $('tr.key', this.$el).show();
-            }
+        // Temporary values
+        this.server_options = {};
 
-            // Temporary values
-            this.server_options = {};
+        if (defaults.encoding)
+            this.server_options.encoding = defaults.encoding;
+    },
 
-            if (defaults.encoding)
-                this.server_options.encoding = defaults.encoding;
-        },
+    hide: function () {
+        this.$el.slideUp();
+    },
 
-        hide: function () {
-            this.$el.slideUp();
-        },
+    show: function (new_state) {
+        new_state = new_state || 'all';
 
-        show: function (new_state) {
-            new_state = new_state || 'all';
+        this.$el.show();
 
-            this.$el.show();
+        if (new_state === 'all') {
+            $('.show_more', this.$el).show();
 
-            if (new_state === 'all') {
-                $('.show_more', this.$el).show();
+        } else if (new_state === 'more') {
+            $('.more', this.$el).slideDown('fast');
 
-            } else if (new_state === 'more') {
-                $('.more', this.$el).slideDown('fast');
+        } else if (new_state === 'nick_change') {
+            $('.more', this.$el).hide();
+            $('.show_more', this.$el).hide();
+            $('input.nick', this.$el).select();
 
-            } else if (new_state === 'nick_change') {
-                $('.more', this.$el).hide();
-                $('.show_more', this.$el).hide();
-                $('input.nick', this.$el).select();
+        } else if (new_state === 'enter_password') {
+            $('.more', this.$el).hide();
+            $('.show_more', this.$el).hide();
+            $('input.password', this.$el).select();
+        }
 
-            } else if (new_state === 'enter_password') {
-                $('.more', this.$el).hide();
-                $('.show_more', this.$el).hide();
-                $('input.password', this.$el).select();
-            }
+        this.state = new_state;
+    },
 
-            state = new_state;
-        },
-
-        infoBoxShow: function() {
-            var $side_panel = this.$el.find('.side_panel');
-
-            // Some theme may hide the info panel so check before we
-            // resize ourselves
-            if (!$side_panel.is(':visible'))
-                return;
-
-            this.$el.animate({
-                width: parseInt($side_panel.css('left'), 10) + $side_panel.find('.content:first').outerWidth()
-            });
-        },
-
-        infoBoxHide: function() {
-            var $side_panel = this.$el.find('.side_panel');
-            this.$el.animate({
-                width: parseInt($side_panel.css('left'), 10)
-            });
-        },
-
-        infoBoxSet: function($info_view) {
-            this.$el.find('.side_panel .content')
-                .empty()
-                .append($info_view);
-        },
-
-        setStatus: function (text, class_name) {
-            $('.status', this.$el)
-                .text(text)
-                .attr('class', 'status')
-                .addClass(class_name||'')
-                .show();
-        },
-        clearStatus: function () {
-            $('.status', this.$el).hide();
-        },
-
-        networkConnected: function (event) {
-            this.setStatus(_kiwi.global.i18n.translate('client_views_serverselect_connection_successfully').fetch() + ' :)', 'ok');
-            $('form', this.$el).hide();
-        },
-
-        networkConnecting: function (event) {
-            this.setStatus(_kiwi.global.i18n.translate('client_views_serverselect_connection_trying').fetch(), 'ok');
-        },
-
-        onIrcError: function (data) {
-            $('button', this.$el).attr('disabled', null);
-
-            switch(data.error) {
-            case 'nickname_in_use':
-                this.setStatus(_kiwi.global.i18n.translate('client_views_serverselect_nickname_error_alreadyinuse').fetch());
-                this.show('nick_change');
-                this.$el.find('.nick').select();
-                break;
-            case 'erroneus_nickname':
-                this.setStatus(_kiwi.global.i18n.translate('client_views_serverselect_nickname_invalid').fetch());
-                this.show('nick_change');
-                this.$el.find('.nick').select();
-                break;
-            case 'password_mismatch':
-                this.setStatus(_kiwi.global.i18n.translate('client_views_serverselect_password_incorrect').fetch());
-                this.show('enter_password');
-                this.$el.find('.password').select();
-                break;
-            }
-        },
+    infoBoxShow: function() {
+        var $side_panel = this.$el.find('.side_panel');
 
-        showError: function (error_reason) {
-            var err_text = _kiwi.global.i18n.translate('client_views_serverselect_connection_error').fetch();
+        // Some theme may hide the info panel so check before we
+        // resize ourselves
+        if (!$side_panel.is(':visible'))
+            return;
 
-            if (error_reason) {
-                switch (error_reason) {
-                case 'ENOTFOUND':
-                    err_text = _kiwi.global.i18n.translate('client_views_serverselect_server_notfound').fetch();
-                    break;
+        this.$el.animate({
+            width: parseInt($side_panel.css('left'), 10) + $side_panel.find('.content:first').outerWidth()
+        });
+    },
+
+    infoBoxHide: function() {
+        var $side_panel = this.$el.find('.side_panel');
+        this.$el.animate({
+            width: parseInt($side_panel.css('left'), 10)
+        });
+    },
+
+    infoBoxSet: function($info_view) {
+        this.$el.find('.side_panel .content')
+            .empty()
+            .append($info_view);
+    },
+
+    setStatus: function (text, class_name) {
+        $('.status', this.$el)
+            .text(text)
+            .attr('class', 'status')
+            .addClass(class_name||'')
+            .show();
+    },
+    clearStatus: function () {
+        $('.status', this.$el).hide();
+    },
+
+    reset: function() {
+        this.populateFields();
+        this.clearStatus();
+
+        this.$('button').attr('disabled', null);
+    },
+
+    newNetwork: function(network) {
+        // Keep a reference to this network so we can interact with it
+        this.model.current_connecting_network = network;
+    },
+
+    networkConnected: function (event) {
+        this.model.trigger('connected', _kiwi.app.connections.getByConnectionId(event.server));
+        this.model.current_connecting_network = null;
+    },
+
+    networkConnecting: function (event) {
+        this.model.trigger('connecting');
+        this.setStatus(_kiwi.global.i18n.translate('client_views_serverselect_connection_trying').fetch(), 'ok');
+
+        this.$('.status').append('<a class="show_server"><i class="icon-info-sign"></i></a>');
+    },
+
+    showServer: function() {
+        // If we don't have a current connection in the making then we have nothing to show
+        if (!this.model.current_connecting_network)
+            return;
 
-                case 'ECONNREFUSED':
-                    err_text += ' (' + _kiwi.global.i18n.translate('client_views_serverselect_connection_refused').fetch() + ')';
-                    break;
+        _kiwi.app.view.barsShow();
+        this.model.current_connecting_network.panels.server.view.show();
+    },
+
+    onIrcError: function (data) {
+        $('button', this.$el).attr('disabled', null);
+
+        switch(data.error) {
+        case 'nickname_in_use':
+            this.setStatus(_kiwi.global.i18n.translate('client_views_serverselect_nickname_error_alreadyinuse').fetch());
+            this.show('nick_change');
+            this.$el.find('.nick').select();
+            break;
+        case 'erroneus_nickname':
+            this.setStatus(_kiwi.global.i18n.translate('client_views_serverselect_nickname_invalid').fetch());
+            this.show('nick_change');
+            this.$el.find('.nick').select();
+            break;
+        case 'password_mismatch':
+            this.setStatus(_kiwi.global.i18n.translate('client_views_serverselect_password_incorrect').fetch());
+            this.show('enter_password');
+            this.$el.find('.password').select();
+            break;
+        }
+    },
 
-                default:
-                    err_text += ' (' + error_reason + ')';
-                }
-            }
+    showError: function (error_reason) {
+        var err_text = _kiwi.global.i18n.translate('client_views_serverselect_connection_error').fetch();
 
-            this.setStatus(err_text, 'error');
-            $('button', this.$el).attr('disabled', null);
-            this.show();
-        }
-    });
+        if (error_reason) {
+            switch (error_reason) {
+            case 'ENOTFOUND':
+                err_text = _kiwi.global.i18n.translate('client_views_serverselect_server_notfound').fetch();
+                break;
 
+            case 'ECONNREFUSED':
+                err_text += ' (' + _kiwi.global.i18n.translate('client_views_serverselect_connection_refused').fetch() + ')';
+                break;
+
+            default:
+                err_text += ' (' + error_reason + ')';
+            }
+        }
 
-    return new model(arguments);
-};
\ No newline at end of file
+        this.setStatus(err_text, 'error');
+        $('button', this.$el).attr('disabled', null);
+        this.show();
+    }
+});
\ No newline at end of file
index 74b5a9584a258316bbe939fa8a67db40bbfb3adc..527592e9139ba16f2ddcd492d4dcd6783e8a3d06 100644 (file)
@@ -25,6 +25,8 @@ _kiwi.view.Tabs = Backbone.View.extend({
                 $('span', this.model.server.tab).text(new_val);
             }, this);
         }
+
+        this.panel_access = new Array();
     },
 
     render: function () {
@@ -80,16 +82,36 @@ _kiwi.view.Tabs = Backbone.View.extend({
         panel.bind('change:title', this.updateTabTitle);
         panel.bind('change:name', this.updateTabTitle);
 
+        //Adding a panel
+        this.panel_access.unshift(panel.cid);
+
         _kiwi.app.view.doLayout();
     },
     panelRemoved: function (panel) {
+        var connection = _kiwi.app.connections.active_connection;
+
         panel.tab.remove();
+
+        // If closing the active panel, switch to the last-accessed panel
+        if (this.panel_access[0] === _kiwi.app.panels().active.cid) {
+            this.panel_access.shift();
+
+            //Get the last-accessed panel model now that we removed the closed one
+            var model = connection.panels.getByCid(this.panel_access[0]);
+
+            if (model) {
+                model.view.show();
+            }
+        }
+
         delete panel.tab;
 
         _kiwi.app.view.doLayout();
     },
 
     panelActive: function (panel, previously_active_panel) {
+        var panel_index = this.panel_access.indexOf(panel.cid);
+
         // Remove any existing tabs or part images
         _kiwi.app.view.$el.find('.panellist .part').remove();
         _kiwi.app.view.$el.find('.panellist .active').removeClass('active');
@@ -100,6 +122,13 @@ _kiwi.view.Tabs = Backbone.View.extend({
         if (!panel.isServer()) {
             panel.tab.append('<span class="part icon-nonexistant"></span>');
         }
+
+        if (panel_index > -1) {
+            this.panel_access.splice(panel_index, 1);
+        }
+
+        //Make this panel the most recently accessed
+        this.panel_access.unshift(panel.cid);
     },
 
     tabClick: function (e) {
index 7cc2f3733db114e858d36b4ee52e664b9d499b64..c12507fe369b580384543408cdad8d578b7dec18 100644 (file)
@@ -29,7 +29,7 @@ _kiwi.view.TopicBar = Backbone.View.extend({
 
         // If hit return key, update the current topic
         if (ev.keyCode === 13) {
-            _kiwi.gateway.topic(null, _kiwi.app.panels().active.get('name'), inp_val);
+            _kiwi.app.connections.active_connection.gateway.topic(_kiwi.app.panels().active.get('name'), inp_val);
             return false;
         }
     },
index f41b115fb14fdf620e1f50b1083b773b5a33c8cb..8d21445a97ca9c8be394d98d5e273538293c76f5 100644 (file)
@@ -2,7 +2,8 @@ _kiwi.view.UserBox = Backbone.View.extend({
     events: {
         'click .query': 'queryClick',
         'click .info': 'infoClick',
-        'click .slap': 'slapClick',
+        'change .ignore': 'ignoreChange',
+        'click .ignore': 'ignoreClick',
         'click .op': 'opClick',
         'click .deop': 'deopClick',
         'click .voice': 'voiceClick',
@@ -21,7 +22,7 @@ _kiwi.view.UserBox = Backbone.View.extend({
             ban: _kiwi.global.i18n.translate('client_views_userbox_ban').fetch(),
             message: _kiwi.global.i18n.translate('client_views_userbox_query').fetch(),
             info: _kiwi.global.i18n.translate('client_views_userbox_whois').fetch(),
-            slap: _kiwi.global.i18n.translate('client_views_userbox_slap').fetch()
+            ignore: _kiwi.global.i18n.translate('client_views_userbox_ignore').fetch()
         };
         this.$el = $(_.template($('#tmpl_userbox').html().trim(), text));
     },
@@ -29,6 +30,9 @@ _kiwi.view.UserBox = Backbone.View.extend({
     setTargets: function (user, channel) {
         this.user = user;
         this.channel = channel;
+
+        var is_ignored = _kiwi.app.connections.active_connection.isNickIgnored(this.user.get('nick'));
+        this.$('.ignore input').attr('checked', is_ignored ? 'checked' : false);
     },
 
     displayOpItems: function(display_items) {
@@ -49,8 +53,17 @@ _kiwi.view.UserBox = Backbone.View.extend({
         _kiwi.app.controlbox.processInput('/whois ' + this.user.get('nick'));
     },
 
-    slapClick: function (event) {
-        _kiwi.app.controlbox.processInput('/slap ' + this.user.get('nick'));
+    ignoreClick: function (event) {
+        // Stop the menubox from closing since it will not update the checkbox otherwise
+        event.stopPropagation();
+    },
+
+    ignoreChange: function (event) {
+        if ($(event.currentTarget).find('input').is(':checked')) {
+            _kiwi.app.controlbox.processInput('/ignore ' + this.user.get('nick'));
+        } else {
+            _kiwi.app.controlbox.processInput('/unignore ' + this.user.get('nick'));
+        }
     },
 
     opClick: function (event) {
index 722042ac403727d6a6bfd5b359ae735a2a6c5b96..1314152faca35ffd7e098867d91271a7372bcfea 100644 (file)
@@ -182,6 +182,7 @@ conf.client = {
         scrollback: 250,
         show_joins_parts: true,
         show_timestamps: false,
+        use_24_hour_timestamps: true,
         mute_sounds: false,
         show_emoticons: true,
         count_all_activity: true
diff --git a/server/.jshintrc b/server/.jshintrc
new file mode 100644 (file)
index 0000000..021f917
--- /dev/null
@@ -0,0 +1,13 @@
+{
+       "node": true,
+       "curly": true,
+       "eqeqeq": true,
+       "immed": true,
+       "indent": 4,
+       "latedef": "nofunc",
+       "newcap": true,
+       "noarg": true,
+       "undef": true,
+       "unused": true,
+       "trailing": true
+}
\ No newline at end of file
index 5aebcb068ad7ee19072afc34881612ef2f8c7918..2226828a0372d1a49b44b3946af723867929330c 100644 (file)
@@ -4,7 +4,9 @@ var util        = require('util'),
 
 var IrcChannel = function(irc_connection, name) {
     this.irc_connection = irc_connection;
-    this.name = name;
+
+    // Lowercase the channel name so we don't run into case-sensitive issues
+    this.name = name.toLowerCase();
 
     this.members = [];
     this.ban_list_buffer = [];
index 03899aa66e537cebb8e1fb0d66fc62508334b95a..e1bf1191b1b765ec7f60398fd30a85ff24da724b 100644 (file)
@@ -115,29 +115,16 @@ unknownCommand = function (command, data) {
 
     this.irc_connection.emit('server ' + this.irc_connection.irc_host.hostname + ' unknown_command', {
         command: command,
-        params: params,
-        trailing: data.trailing
+        params: params
     });
-
-
-/*
-            this.irc_connection.emit(namespace + ' ' + command.params[0] + ' notice', {
-                from_server: command.prefix ? true : false,
-                nick: command.nick || command.prefix || undefined,
-                ident: command.ident,
-                hostname: command.hostname,
-                target: command.params[0],
-                msg: command.trailing
-            });
-            */
- };
+};
 
 
 handlers = {
     'RPL_WELCOME': function (command) {
         var nick =  command.params[0];
         this.irc_connection.registered = true;
-        this.cap_negotation = false;
+        this.cap_negotiation = false;
         this.irc_connection.emit('server ' + this.irc_connection.irc_host.hostname + ' connect', {
             nick: nick
         });
@@ -177,14 +164,14 @@ handlers = {
     'RPL_ENDOFWHOIS': function (command) {
         this.irc_connection.emit('user ' + command.params[1] + ' endofwhois', {
             nick: command.params[1],
-            msg: command.trailing
+            msg: command.params[command.params.length - 1]
         });
     },
 
     'RPL_AWAY': function (command) {
         this.irc_connection.emit('user ' + command.params[1] + ' whoisaway', {
             nick: command.params[1],
-            reason: command.trailing
+            reason: command.params[command.params.length - 1]
         });
     },
 
@@ -193,7 +180,7 @@ handlers = {
             nick: command.params[1],
             ident: command.params[2],
             host: command.params[3],
-            msg: command.trailing
+            msg: command.params[command.params.length - 1]
         });
     },
 
@@ -201,28 +188,28 @@ handlers = {
         this.irc_connection.emit('user ' + command.params[1] + ' whoisserver', {
             nick: command.params[1],
             irc_server: command.params[2],
-            server_info: command.trailing
+            server_info: command.params[command.params.length - 1]
         });
     },
 
     'RPL_WHOISOPERATOR': function (command) {
         this.irc_connection.emit('user ' + command.params[1] + ' whoisoperator', {
             nick: command.params[1],
-            msg: command.trailing
+            msg: command.params[command.params.length - 1]
         });
     },
 
     'RPL_WHOISCHANNELS':       function (command) {
         this.irc_connection.emit('user ' + command.params[1] + ' whoischannels', {
             nick: command.params[1],
-            chans: command.trailing
+            chans: command.params[command.params.length - 1]
         });
     },
 
     'RPL_WHOISMODES': function (command) {
         this.irc_connection.emit('user ' + command.params[1] + ' whoismodes', {
             nick: command.params[1],
-            msg: command.trailing
+            msg: command.params[command.params.length - 1]
         });
     },
 
@@ -237,14 +224,14 @@ handlers = {
     'RPL_WHOISREGNICK': function (command) {
         this.irc_connection.emit('user ' + command.params[1] + ' whoisregnick', {
             nick: command.params[1],
-            msg: command.trailing
+            msg: command.params[command.params.length - 1]
         });
     },
 
     'RPL_WHOISHOST': function (command) {
         this.irc_connection.emit('user ' + command.params[1] + ' whoishost', {
             nick: command.params[1],
-            msg: command.trailing
+            msg: command.params[command.params.length - 1]
         });
     },
 
@@ -266,7 +253,7 @@ handlers = {
             nick: command.params[1],
             ident: command.params[2],
             host: command.params[3],
-            real_name: command.trailing
+            real_name: command.params[command.params.length - 1]
         });
     },
 
@@ -294,7 +281,7 @@ handlers = {
         this.irc_connection.emit('server ' + this.irc_connection.irc_host.hostname + ' list_channel', {
             channel: command.params[1],
             num_users: parseInt(command.params[2], 10),
-            topic: command.trailing
+            topic: command.params[3] || ''
         });
     },
 
@@ -322,13 +309,13 @@ handlers = {
 
         this.irc_connection.emit('channel ' + channel + ' info', {
             channel: channel,
-            url: command.trailing
+            url: command.params[command.params.length - 1]
         });
     },
 
     'RPL_MOTD': function (command) {
         this.irc_connection.emit('server '  + this.irc_connection.irc_host.hostname + ' motd', {
-            motd: command.trailing + '\n'
+            motd: command.params[command.params.length - 1] + '\n'
         });
     },
 
@@ -341,7 +328,7 @@ handlers = {
     },
 
     'RPL_NAMEREPLY': function (command) {
-        var members = command.trailing.split(' ');
+        var members = command.params[command.params.length - 1].split(' ');
         var member_list = [];
         var that = this;
         _.each(members, function (member) {
@@ -404,7 +391,7 @@ handlers = {
     'RPL_TOPIC': function (command) {
         this.irc_connection.emit('channel ' + command.params[1] + ' topic', {
             channel: command.params[1],
-            topic: command.trailing
+            topic: command.params[command.params.length - 1]
         });
     },
 
@@ -431,14 +418,12 @@ handlers = {
     },
 
     'PING': function (command) {
-        this.irc_connection.write('PONG ' + command.trailing);
+        this.irc_connection.write('PONG ' + command.params[command.params.length - 1]);
     },
 
     'JOIN': function (command) {
         var channel, time;
-        if (typeof command.trailing === 'string' && command.trailing !== '') {
-            channel = command.trailing;
-        } else if (typeof command.params[0] === 'string' && command.params[0] !== '') {
+        if (typeof command.params[0] === 'string' && command.params[0] !== '') {
             channel = command.params[0];
         }
 
@@ -455,17 +440,22 @@ handlers = {
     },
 
     'PART': function (command) {
-        var time;
+        var time, channel, message;
 
         // Check if we have a server-time
         time = getServerTime.call(this, command);
 
-        this.irc_connection.emit('channel ' + command.params[0] + ' part', {
+        channel = command.params[0];
+        if (command.params.length > 1) {
+            message = command.params[command.params.length - 1];
+        }
+
+        this.irc_connection.emit('channel ' + channel + ' part', {
             nick: command.nick,
             ident: command.ident,
             hostname: command.hostname,
-            channel: command.params[0],
-            message: command.trailing,
+            channel: channel,
+            message: message,
             time: time
         });
     },
@@ -482,7 +472,7 @@ handlers = {
             ident: command.ident,
             hostname: command.hostname,
             channel: command.params[0],
-            message: command.trailing,
+            message: command.params[command.params.length - 1],
             time: time
         });
     },
@@ -497,32 +487,33 @@ handlers = {
             nick: command.nick,
             ident: command.ident,
             hostname: command.hostname,
-            message: command.trailing,
+            message: command.params[command.params.length - 1],
             time: time
         });
     },
 
     'NOTICE': function (command) {
         var namespace,
-            time;
+            time,
+            msg;
 
         // Check if we have a server-time
         time = getServerTime.call(this, command);
 
-
-        if ((command.trailing.charAt(0) === String.fromCharCode(1)) && (command.trailing.charAt(command.trailing.length - 1) === String.fromCharCode(1))) {
+        msg = command.params[command.params.length - 1];
+        if ((msg.charAt(0) === String.fromCharCode(1)) && (msg.charAt(msg.length - 1) === String.fromCharCode(1))) {
             // It's a CTCP response
-            namespace = (command.params[0].toLowerCase() == this.irc_connection.nick.toLowerCase()) ? 'user' : 'channel';
+            namespace = (command.params[0].toLowerCase() === this.irc_connection.nick.toLowerCase()) ? 'user' : 'channel';
             this.irc_connection.emit(namespace + ' ' + command.params[0] + ' ctcp_response', {
                 nick: command.nick,
                 ident: command.ident,
                 hostname: command.hostname,
                 channel: command.params[0],
-                msg: command.trailing.substring(1, command.trailing.length - 1),
+                msg: msg.substring(1, msg.length - 1),
                 time: time
             });
         } else {
-            namespace = (command.params[0].toLowerCase() == this.irc_connection.nick.toLowerCase() || command.params[0] == '*') ?
+            namespace = (command.params[0].toLowerCase() === this.irc_connection.nick.toLowerCase() || command.params[0] === '*') ?
                 'user' :
                 'channel';
 
@@ -532,7 +523,7 @@ handlers = {
                 ident: command.ident,
                 hostname: command.hostname,
                 target: command.params[0],
-                msg: command.trailing,
+                msg: msg,
                 time: time
             });
         }
@@ -548,7 +539,7 @@ handlers = {
             nick: command.nick,
             ident: command.ident,
             hostname: command.hostname,
-            newnick: command.trailing || command.params[0],
+            newnick: command.params[0],
             time: time
         });
     },
@@ -557,13 +548,15 @@ handlers = {
         var time;
 
         // If we don't have an associated channel, no need to continue
-        if (!command.params[0]) return;
+        if (!command.params[0]) {
+            return;
+        }
 
         // Check if we have a server-time
         time = getServerTime.call(this, command);
 
         var channel = command.params[0],
-            topic = command.trailing || '';
+            topic = command.params[command.params.length - 1] || '';
 
         this.irc_connection.emit('channel ' + channel + ' topic', {
             nick: command.nick,
@@ -580,7 +573,7 @@ handlers = {
         time = getServerTime.call(this, command);
 
         // Get a JSON representation of the modes
-        modes = parseModeList.call(this, command.params[1] || command.trailing, command.params.slice(2));
+        modes = parseModeList.call(this, command.params[1], command.params.slice(2));
         event = (_.contains(this.irc_connection.options.CHANTYPES, command.params[0][0]) ? 'channel ' : 'user ') + command.params[0] + ' mode';
 
         this.irc_connection.emit(event, {
@@ -592,57 +585,58 @@ handlers = {
     },
 
     'PRIVMSG': function (command) {
-        var tmp, namespace, time;
+        var tmp, namespace, time, msg;
 
         // Check if we have a server-time
         time = getServerTime.call(this, command);
 
-        if ((command.trailing.charAt(0) === String.fromCharCode(1)) && (command.trailing.charAt(command.trailing.length - 1) === String.fromCharCode(1))) {
+        msg = command.params[command.params.length - 1];
+        if ((msg.charAt(0) === String.fromCharCode(1)) && (msg.charAt(msg.length - 1) === String.fromCharCode(1))) {
             //CTCP request
-            if (command.trailing.substr(1, 6) === 'ACTION') {
+            if (msg.substr(1, 6) === 'ACTION') {
                 this.irc_connection.clientEvent('action', {
                     nick: command.nick,
                     ident: command.ident,
                     hostname: command.hostname,
                     channel: command.params[0],
-                    msg: command.trailing.substring(8, command.trailing.length - 1),
+                    msg: msg.substring(8, msg.length - 1),
                     time: time
                 });
-            } else if (command.trailing.substr(1, 4) === 'KIWI') {
-                tmp = command.trailing.substring(6, command.trailing.length - 1);
+            } else if (msg.substr(1, 4) === 'KIWI') {
+                tmp = msg.substring(6, msg.length - 1);
                 namespace = tmp.split(' ', 1)[0];
                 this.irc_connection.clientEvent('kiwi', {
                     namespace: namespace,
                     data: tmp.substr(namespace.length + 1),
                     time: time
                 });
-            } else if (command.trailing.substr(1, 7) === 'VERSION') {
+            } else if (msg.substr(1, 7) === 'VERSION') {
                 this.irc_connection.write('NOTICE ' + command.nick + ' :' + String.fromCharCode(1) + 'VERSION KiwiIRC' + String.fromCharCode(1));
-            } else if (command.trailing.substr(1, 6) === 'SOURCE') {
+            } else if (msg.substr(1, 6) === 'SOURCE') {
                 this.irc_connection.write('NOTICE ' + command.nick + ' :' + String.fromCharCode(1) + 'SOURCE http://www.kiwiirc.com/' + String.fromCharCode(1));
-            } else if (command.trailing.substr(1, 10) === 'CLIENTINFO') {
+            } else if (msg.substr(1, 10) === 'CLIENTINFO') {
                 this.irc_connection.write('NOTICE ' + command.nick + ' :' + String.fromCharCode(1) + 'CLIENTINFO SOURCE VERSION TIME' + String.fromCharCode(1));
             } else {
-                namespace = (command.params[0].toLowerCase() == this.irc_connection.nick.toLowerCase()) ? 'user' : 'channel';
+                namespace = (command.params[0].toLowerCase() === this.irc_connection.nick.toLowerCase()) ? 'user' : 'channel';
                 this.irc_connection.emit(namespace + ' ' + command.nick + ' ctcp_request', {
                     nick: command.nick,
                     ident: command.ident,
                     hostname: command.hostname,
                     target: command.params[0],
-                    type: (command.trailing.substring(1, command.trailing.length - 1).split(' ') || [null])[0],
-                    msg: command.trailing.substring(1, command.trailing.length - 1),
+                    type: (msg.substring(1, msg.length - 1).split(' ') || [null])[0],
+                    msg: msg.substring(1, msg.length - 1),
                     time: time
                 });
             }
         } else {
             // A message to a user (private message) or to a channel?
-            namespace = (command.params[0].toLowerCase() == this.irc_connection.nick.toLowerCase()) ? 'user ' + command.nick : 'channel ' + command.params[0];
+            namespace = (command.params[0].toLowerCase() === this.irc_connection.nick.toLowerCase()) ? 'user ' + command.nick : 'channel ' + command.params[0];
             this.irc_connection.emit(namespace + ' privmsg', {
                 nick: command.nick,
                 ident: command.ident,
                 hostname: command.hostname,
                 channel: command.params[0],
-                msg: command.trailing,
+                msg: msg,
                 time: time
             });
         }
@@ -651,7 +645,7 @@ handlers = {
     'CAP': function (command) {
         // TODO: capability modifiers
         // i.e. - for disable, ~ for requires ACK, = for sticky
-        var capabilities = command.trailing.replace(/(?:^| )[\-~=]/, '').split(' ');
+        var capabilities = command.params[command.params.length - 1].replace(/(?:^| )[\-~=]/, '').split(' ');
         var request;
 
         // Which capabilities we want to enable
@@ -670,7 +664,7 @@ handlers = {
                     this.irc_connection.write('CAP REQ :' + request.join(' '));
                 } else {
                     this.irc_connection.write('CAP END');
-                    this.irc_connection.cap_negotation = false;
+                    this.irc_connection.cap_negotiation = false;
                 }
                 break;
             case 'ACK':
@@ -686,7 +680,7 @@ handlers = {
                         this.irc_connection.write('AUTHENTICATE PLAIN');
                     } else {
                         this.irc_connection.write('CAP END');
-                        this.irc_connection.cap_negotation = false;
+                        this.irc_connection.cap_negotiation = false;
                     }
                 }
                 break;
@@ -696,7 +690,7 @@ handlers = {
                 }
                 if (this.irc_connection.cap.requested.length > 0) {
                     this.irc_connection.write('CAP END');
-                    this.irc_connection.cap_negotation = false;
+                    this.irc_connection.cap_negotiation = false;
                 }
                 break;
             case 'LIST':
@@ -720,7 +714,7 @@ handlers = {
             }
         } else {
             this.irc_connection.write('CAP END');
-            this.irc_connection.cap_negotation = false;
+            this.irc_connection.cap_negotiation = false;
         }
     },
 
@@ -732,31 +726,32 @@ handlers = {
 
         this.irc_connection.emit('user ' + command.nick + ' away', {
             nick: command.nick,
-            msg: command.trailing,
+            msg: command.params[command.params.length - 1],
             time: time
         });
     },
 
     'RPL_SASLAUTHENTICATED': function (command) {
         this.irc_connection.write('CAP END');
-        this.irc_connection.cap_negotation = false;
+        this.irc_connection.cap_negotiation = false;
         this.irc_connection.sasl = true;
     },
 
     'RPL_SASLLOGGEDIN': function (command) {
-        if (this.irc_connection.cap_negotation === false) {
+        if (this.irc_connection.cap_negotiation === true) {
             this.irc_connection.write('CAP END');
+            this.irc_connection.cap_negotiation = false;
         }
     },
 
     'ERR_SASLNOTAUTHORISED': function (command) {
         this.irc_connection.write('CAP END');
-        this.irc_connection.cap_negotation = false;
+        this.irc_connection.cap_negotiation = false;
     },
 
     'ERR_SASLABORTED': function (command) {
         this.irc_connection.write('CAP END');
-        this.irc_connection.cap_negotation = false;
+        this.irc_connection.cap_negotiation = false;
     },
 
     'ERR_SASLALREADYAUTHED': function (command) {
@@ -765,7 +760,7 @@ handlers = {
 
     'ERROR': function (command) {
         this.irc_connection.emit('server ' + this.irc_connection.irc_host.hostname + ' error', {
-            reason: command.trailing
+            reason: command.params[command.params.length - 1]
         });
     },
     ERR_PASSWDMISMATCH: function (command) {
@@ -782,21 +777,21 @@ handlers = {
     ERR_NOSUCHNICK: function (command) {
         this.irc_connection.emit('server ' + this.irc_connection.irc_host.hostname + ' no_such_nick', {
             nick: command.params[1],
-            reason: command.trailing
+            reason: command.params[command.params.length - 1]
         });
     },
 
     ERR_CANNOTSENDTOCHAN: function (command) {
         this.irc_connection.emit('server ' + this.irc_connection.irc_host.hostname + ' cannot_send_to_chan', {
             channel: command.params[1],
-            reason: command.trailing
+            reason: command.params[command.params.length - 1]
         });
     },
 
     ERR_TOOMANYCHANNELS: function (command) {
         this.irc_connection.emit('server ' + this.irc_connection.irc_host.hostname + ' too_many_channels', {
             channel: command.params[1],
-            reason: command.trailing
+            reason: command.params[command.params.length - 1]
         });
     },
 
@@ -804,14 +799,14 @@ handlers = {
         this.irc_connection.emit('server ' + this.irc_connection.irc_host.hostname + ' user_not_in_channel', {
             nick: command.params[0],
             channel: command.params[1],
-            reason: command.trailing
+            reason: command.params[command.params.length - 1]
         });
     },
 
     ERR_NOTONCHANNEL: function (command) {
         this.irc_connection.emit('server ' + this.irc_connection.irc_host.hostname + ' not_on_channel', {
             channel: command.params[1],
-            reason: command.trailing
+            reason: command.params[command.params.length - 1]
         });
     },
 
@@ -825,49 +820,49 @@ handlers = {
     ERR_CHANNELISFULL: function (command) {
         this.irc_connection.emit('server ' + this.irc_connection.irc_host.hostname + ' channel_is_full', {
             channel: command.params[1],
-            reason: command.trailing
+            reason: command.params[command.params.length - 1]
         });
     },
 
     ERR_INVITEONLYCHAN: function (command) {
         this.irc_connection.emit('server ' + this.irc_connection.irc_host.hostname + ' invite_only_channel', {
             channel: command.params[1],
-            reason: command.trailing
+            reason: command.params[command.params.length - 1]
         });
     },
 
     ERR_BANNEDFROMCHAN: function (command) {
         this.irc_connection.emit('server ' + this.irc_connection.irc_host.hostname + ' banned_from_channel', {
             channel: command.params[1],
-            reason: command.trailing
+            reason: command.params[command.params.length - 1]
         });
     },
 
     ERR_BADCHANNELKEY: function (command) {
         this.irc_connection.emit('server ' + this.irc_connection.irc_host.hostname + ' bad_channel_key', {
             channel: command.params[1],
-            reason: command.trailing
+            reason: command.params[command.params.length - 1]
         });
     },
 
     ERR_CHANOPRIVSNEEDED: function (command) {
         this.irc_connection.emit('server ' + this.irc_connection.irc_host.hostname + ' chanop_privs_needed', {
             channel: command.params[1],
-            reason: command.trailing
+            reason: command.params[command.params.length - 1]
         });
     },
 
     ERR_NICKNAMEINUSE: function (command) {
         this.irc_connection.emit('server ' + this.irc_connection.irc_host.hostname + ' nickname_in_use', {
             nick: command.params[1],
-            reason: command.trailing
+            reason: command.params[command.params.length - 1]
         });
     },
 
     ERR_ERRONEUSNICKNAME: function(command) {
         this.irc_connection.emit('server ' + this.irc_connection.irc_host.hostname + ' erroneus_nickname', {
             nick: command.params[1],
-            reason: command.trailing
+            reason: command.params[command.params.length - 1]
         });
     },
 
@@ -877,91 +872,91 @@ handlers = {
     RPL_MAPMORE: function (command) {
         var params = _.clone(command.params);
         params.shift();
-        genericNotice.call(this, command, params.join(', ') + ' ' + command.trailing);
+        genericNotice.call(this, command, params.slice(0, -1).join(', ') + ' ' + command.params[command.params.length - 1]);
     },
 
     RPL_MAPEND: function (command) {
         var params = _.clone(command.params);
         params.shift();
-        genericNotice.call(this, command, params.join(', ') + ' ' + command.trailing);
+        genericNotice.call(this, command, params.slice(0, -1).join(', ') + ' ' + command.params[command.params.length - 1]);
     },
 
     RPL_LINKS: function (command) {
         var params = _.clone(command.params);
         params.shift();
-        genericNotice.call(this, command, params.join(', ') + ' ' + command.trailing);
+        genericNotice.call(this, command, params.slice(0, -1).join(', ') + ' ' + command.params[command.params.length - 1]);
     },
 
     RPL_ENDOFLINKS: function (command) {
         var params = _.clone(command.params);
         params.shift();
-        genericNotice.call(this, command, params.join(', ') + ' ' + command.trailing);
+        genericNotice.call(this, command, params.slice(0, -1).join(', ') + ' ' + command.params[command.params.length - 1]);
     },
 
     ERR_UNKNOWNCOMMAND: function (command) {
         var params = _.clone(command.params);
         params.shift();
-        genericNotice.call(this, command, '`' + params.join(', ') + '` ' + command.trailing);
+        genericNotice.call(this, command, '`' + params.slice(0, -1).join(', ') + '` ' + command.params[command.params.length - 1]);
     },
 
     ERR_NOMOTD: function (command) {
         var params = _.clone(command.params);
         params.shift();
-        genericNotice.call(this, command, command.trailing);
+        genericNotice.call(this, command, command.params[command.params.length - 1]);
     },
 
     ERR_NOPRIVILEGES: function (command) {
         var params = _.clone(command.params);
         params.shift();
-        genericNotice.call(this, command, command.trailing);
+        genericNotice.call(this, command, command.params[command.params.length - 1]);
     },
 
     RPL_STATSCONN: function (command) {
         var params = _.clone(command.params);
         params.shift();
-        genericNotice.call(this, command, params.join(', ') + ' ' + command.trailing);
+        genericNotice.call(this, command, params.slice(0, -1).join(', ') + ' ' + command.params[command.params.length - 1]);
     },
 
     RPL_LUSERCLIENT: function (command) {
         var params = _.clone(command.params);
         params.shift();
-        genericNotice.call(this, command, params.join(', ') + ' ' + command.trailing);
+        genericNotice.call(this, command, params.slice(0, -1).join(', ') + ' ' + command.params[command.params.length - 1]);
     },
 
     RPL_LUSEROP: function (command) {
         var params = _.clone(command.params);
         params.shift();
-        genericNotice.call(this, command, params.join(', ') + ' ' + command.trailing);
+        genericNotice.call(this, command, params.slice(0, -1).join(', ') + ' ' + command.params[command.params.length - 1]);
     },
 
     RPL_LUSERUNKNOWN: function (command) {
         var params = _.clone(command.params);
         params.shift();
-        genericNotice.call(this, command, params.join(', ') + ' ' + command.trailing);
+        genericNotice.call(this, command, params.slice(0, -1).join(', ') + ' ' + command.params[command.params.length - 1]);
     },
 
     RPL_LUSERCHANNELS: function (command) {
         var params = _.clone(command.params);
         params.shift();
-        genericNotice.call(this, command, params.join(', ') + ' ' + command.trailing);
+        genericNotice.call(this, command, params.slice(0, -1).join(', ') + ' ' + command.params[command.params.length - 1]);
     },
 
     RPL_LUSERME: function (command) {
         var params = _.clone(command.params);
         params.shift();
-        genericNotice.call(this, command, params.join(', ') + ' ' + command.trailing);
+        genericNotice.call(this, command, params.slice(0, -1).join(', ') + ' ' + command.params[command.params.length - 1]);
     },
 
     RPL_LOCALUSERS: function (command) {
         var params = _.clone(command.params);
         params.shift();
-        genericNotice.call(this, command, params.join(', ') + ' ' + command.trailing);
+        genericNotice.call(this, command, params.slice(0, -1).join(', ') + ' ' + command.params[command.params.length - 1]);
     },
 
     RPL_GLOBALUSERS: function (command) {
         var params = _.clone(command.params);
         params.shift();
-        genericNotice.call(this, command, params.join(', ') + ' ' + command.trailing);
+        genericNotice.call(this, command, params.slice(0, -1).join(', ') + ' ' + command.params[command.params.length - 1]);
     }
 };
 
index 13c4d43366e88273c1df563e25614fd7f8277fd9..b764a1bde5860443cc28b60a19d1f8f8b0aff2c9 100644 (file)
@@ -739,14 +739,17 @@ var parse_regex = /^(?:(?:(?:@([^ ]+) )?):(?:([^\s!]+)|([^\s!]+)!([^\s@]+)@?([^\
 
 function parseIrcLine(buffer_line) {
     var msg,
-        i, j,
+        i,
         tags = [],
         tag,
-        line = '';
+        line = '',
+        msg_obj;
 
     // Decode server encoding
     line = iconv.decode(buffer_line, this.encoding);
-    if (!line) return;
+    if (!line) {
+        return;
+    }
 
     // Parse the complete line, removing any carriage returns
     msg = parse_regex.exec(line.replace(/^\r+|\r+$/, ''));
@@ -762,23 +765,25 @@ function parseIrcLine(buffer_line) {
     if (msg[1]) {
         tags = msg[1].split(';');
 
-        for (j = 0; j < tags.length; j++) {
-            tag = tags[j].split('=');
-            tags[j] = {tag: tag[0], value: tag[1]};
+        for (i = 0; i < tags.length; i++) {
+            tag = tags[i].split('=');
+            tags[i] = {tag: tag[0], value: tag[1]};
         }
     }
 
-    msg = {
+    msg_obj = {
         tags:       tags,
         prefix:     msg[2],
         nick:       msg[3],
         ident:      msg[4],
         hostname:   msg[5] || '',
         command:    msg[6],
-        params:     msg[7] || '',
-        trailing:   (msg[8]) ? msg[8].trim() : ''
+        params:     msg[7] ? msg[7].split(/ +/) : []
     };
 
-    msg.params = msg.params.split(/ +/);
-    this.irc_commands.dispatch(msg.command.toUpperCase(), msg);
+    if (msg[8]) {
+        msg_obj.params.push(msg[8].trim());
+    }
+
+    this.irc_commands.dispatch(msg_obj.command.toUpperCase(), msg_obj);
 }
index 6ec4828aedc3ceeb0e7b87ffa026719ba26bf753..d1fc35360b40a6c2a2b18f94ac84b7c1c75271f2 100755 (executable)
@@ -251,7 +251,6 @@ function onUnknownCommand(event) {
     this.irc_connection.clientEvent('unknown_command', {
         error: 'unknown_command',
         command: event.command,
-        params: event.params,
-        trailing: event.trailing
+        params: event.params
     });
 }
index 213775f3bd877edb3c5601490744948657733e1b..67303e6cd5913369b28a2c1eb2b7baa3d84dab58 100755 (executable)
@@ -71,7 +71,7 @@ function onQuit(event) {
         nick: event.nick,\r
         ident: event.ident,\r
         hostname: event.hostname,\r
-        message: event.trailing,\r
+        message: event.message,\r
         time: event.time\r
     });\r
 }\r
index 0d30a798444add3896e44f8aafe4e219982f0f5d..0782fdd97d974a1b6f6f55c5c76cb2575f6a5887 100644 (file)
@@ -108,17 +108,15 @@ function ProxyPipe(kiwi_socket, proxy_server) {
     this.kiwi_socket  = kiwi_socket;
     this.proxy_server = proxy_server;
     this.irc_socket   = null;
-    this.buffer       = '';
+    this.buffers      = [];
     this.meta         = null;
 
-    debug('[KiwiProxy] Setting encoding to utf8');
-    kiwi_socket.setEncoding('utf8');
     kiwi_socket.on('readable', this.kiwiSocketOnReadable.bind(this));
 }
 
 
 ProxyPipe.prototype.destroy = function() {
-    this.buffer = null;
+    this.buffers = null;
     this.meta = null;
 
     if (this.irc_socket) {
@@ -136,19 +134,23 @@ ProxyPipe.prototype.destroy = function() {
 
 
 ProxyPipe.prototype.kiwiSocketOnReadable = function() {
-    var chunk, meta;
+    var chunk, buffer, meta;
 
     while ((chunk = this.kiwi_socket.read()) !== null) {
-        this.buffer += chunk;
+        this.buffers.push(chunk);
     }
 
     // Not got a complete line yet? Wait some more
-    if (this.buffer.indexOf('\n') === -1)
+    chunk = this.buffers[this.buffers.length-1];
+    if (!chunk || chunk[chunk.length-1] !== 0x0A)
         return;
 
+    buffer = new Buffer.concat(this.buffers);
+    this.buffers = null;
+
     try {
         debug('[KiwiProxy] Found a complete line in the buffer');
-        meta = JSON.parse(this.buffer.substr(0, this.buffer.indexOf('\n')));
+        meta = JSON.parse(buffer.toString('utf8'));
     } catch (err) {
         debug('[KiwiProxy] Error parsing meta');
         this.destroy();
@@ -161,7 +163,6 @@ ProxyPipe.prototype.kiwiSocketOnReadable = function() {
         return;
     }
 
-    this.buffer = '';
     this.meta = meta;
     this.kiwi_socket.removeAllListeners('readable');
 
@@ -257,8 +258,6 @@ ProxyPipe.prototype.startPiping = function() {
 
     this.irc_socket.on('close', this._onSocketClose.bind(this));
 
-    this.kiwi_socket.setEncoding('binary');
-
     this.kiwi_socket.pipe(this.irc_socket);
     this.irc_socket.pipe(this.kiwi_socket);
 };
index 3399db0def8914a5ecfc03276d660de2a5adca1b..4bb95e5cf7b591dc7ec68700297c0478e1005e61 100644 (file)
@@ -1,10 +1,26 @@
 var kiwi_app = './kiwi.js';\r
+var pidfile = '../kiwiirc.pid';\r
+var pidfile_arg;\r
+\r
+// Check if a pidfile has been set as an argument\r
+if (process.argv.indexOf('-p') > -1) {\r
+    pidfile_arg = process.argv[process.argv.indexOf('-p') + 1];\r
+\r
+    if (pidfile_arg) {\r
+        // Don't set the relative path if we have an absolute path given to us\r
+        if (['/', '\\', '.'].indexOf(pidfile_arg[0]) === -1) {\r
+            pidfile = '../' + pidfile_arg;\r
+        } else {\r
+            pidfile = pidfile_arg;\r
+        }\r
+    }\r
+}\r
 \r
 \r
 var daemon = require('daemonize2').setup({\r
     main: kiwi_app,\r
     name: 'kiwiirc',\r
-    pidfile: '../kiwiirc.pid'\r
+    pidfile: pidfile\r
 });\r
 \r
 switch (process.argv[2]) {\r
@@ -47,7 +63,7 @@ switch (process.argv[2]) {
     case 'build':\r
         require('../client/build.js');\r
         break;\r
-        \r
+\r
     default:\r
-        console.log('Usage: [-f|start|stop|restart|status|reconfig|build [-c <config file>]]');\r
+        console.log('Usage: [-f|start|stop|restart|status|reconfig|build [-c <config file>] [-p <pid file>]]');\r
 }\r
index d79753564a1fcf4a0cead80395ca1dea5f612d83..89d1d25d54fe4dcda4b840eb92722636d9bdaf5e 100644 (file)
@@ -213,12 +213,6 @@ function addScripts(vars, debug) {
         [
             'src/models/query.js',
             'src/models/server.js',     // Depends on models/channel.js
-            'src/applets/settings.js',
-            'src/applets/chanlist.js',
-            'src/applets/scripteditor.js'
-        ],
-
-        [
             'src/models/pluginmanager.js',
             'src/models/datastore.js',
             'src/helpers/utils.js'
@@ -250,6 +244,12 @@ function addScripts(vars, debug) {
             'src/views/userbox.js',
             'src/views/channeltools.js',
             'src/views/channelinfo.js'
+        ],
+        [
+            'src/applets/settings.js',
+            'src/applets/chanlist.js',
+            'src/applets/scripteditor.js',
+            'src/applets/startup.js'
         ]
     ]);
 }
\ No newline at end of file