Log client startup errors to console
[KiwiIRC.git] / client / src / app.js
index 4331567a657be3441f313a912b2444fd7786ce8b..619507cc7e2569c22b6f35c2cf12d77573571142 100644 (file)
@@ -4,9 +4,11 @@
 */\r
 var _kiwi = {};\r
 \r
+_kiwi.misc = {};\r
 _kiwi.model = {};\r
 _kiwi.view = {};\r
 _kiwi.applets = {};\r
+_kiwi.utils = {};\r
 \r
 \r
 /**\r
@@ -17,13 +19,24 @@ _kiwi.applets = {};
 _kiwi.global = {\r
     build_version: '',  // Kiwi IRC version this is built from (Set from index.html)\r
     settings: undefined, // Instance of _kiwi.model.DataStore\r
-    plugins: undefined,\r
-    utils: undefined, // TODO: Re-usable methods\r
-    user: undefined, // TODO: Limited user methods\r
-    server: undefined, // TODO: Limited server methods\r
-\r
-    // 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
+    plugins: undefined, // Instance of _kiwi.model.PluginManager\r
+    events: undefined, // Instance of PluginInterface\r
+    rpc: undefined, // Instance of WebsocketRpc\r
+    utils: {}, // References to misc. re-usable helpers / functions\r
+\r
+    // Make public some internal utils for plugins to make use of\r
+    initUtils: function() {\r
+        this.utils.randomString = randomString;\r
+        this.utils.secondsToTime = secondsToTime;\r
+        this.utils.parseISO8601 = parseISO8601;\r
+        this.utils.escapeRegex = escapeRegex;\r
+        this.utils.formatIRCMsg = formatIRCMsg;\r
+        this.utils.styleText = styleText;\r
+        this.utils.hsl2rgb = hsl2rgb;\r
+\r
+        this.utils.notifications = _kiwi.utils.notifications;\r
+        this.utils.formatDate = _kiwi.utils.formatDate;\r
+    },\r
 \r
     addMediaMessageType: function(match, buildHtml) {\r
         _kiwi.view.MediaMessage.addType(match, buildHtml);\r
@@ -32,8 +45,27 @@ _kiwi.global = {
     // Event managers for plugins\r
     components: {\r
         EventComponent: function(event_source, proxy_event_name) {\r
+            /*\r
+             * proxyEvent() listens for events then re-triggers them on its own\r
+             * event emitter. Why? So we can .off() on this emitter without\r
+             * effecting the source of events. Handy for plugins that we don't\r
+             * trust meddling with the core events.\r
+             *\r
+             * If listening for 'all' events the arguments are as follows:\r
+             *     1. Name of the triggered event\r
+             *     2. The event data\r
+             * For all other events, we only have one argument:\r
+             *     1. The event data\r
+             *\r
+             * When this is used via `new kiwi.components.Network()`, this listens\r
+             * for 'all' events so the first argument is the event name which is\r
+             * the connection ID. We don't want to re-trigger this event name so\r
+             * we need to juggle the arguments to find the real event name we want\r
+             * to emit.\r
+             */\r
             function proxyEvent(event_name, event_data) {\r
-                if (proxy_event_name !== 'all') {\r
+                if (proxy_event_name == 'all') {\r
+                } else {\r
                     event_data = event_name.event_data;\r
                     event_name = event_name.event_name;\r
                 }\r
@@ -44,7 +76,6 @@ _kiwi.global = {
             // The event we are to proxy\r
             proxy_event_name = proxy_event_name || 'all';\r
 \r
-\r
             _.extend(this, Backbone.Events);\r
             this._source = event_source;\r
 \r
@@ -62,19 +93,37 @@ _kiwi.global = {
         Network: function(connection_id) {\r
             var connection_event;\r
 \r
+            // If no connection id given, use all connections\r
             if (typeof connection_id !== 'undefined') {\r
                 connection_event = 'connection:' + connection_id.toString();\r
+            } else {\r
+                connection_event = 'connection';\r
             }\r
 \r
+            // Helper to get the network object\r
+            var getNetwork = function() {\r
+                var network = typeof connection_id === 'undefined' ?\r
+                    _kiwi.app.connections.active_connection :\r
+                    _kiwi.app.connections.getByConnectionId(connection_id);\r
+\r
+                return network ?\r
+                    network :\r
+                    undefined;\r
+            };\r
+\r
+            // Create the return object (events proxy from the gateway)\r
             var obj = new this.EventComponent(_kiwi.gateway, connection_event);\r
+\r
+            // Proxy several gateway functions onto the return object\r
             var funcs = {\r
                 kiwi: 'kiwi', raw: 'raw', kick: 'kick', topic: 'topic',\r
                 part: 'part', join: 'join', action: 'action', ctcp: 'ctcp',\r
-                notice: 'notice', msg: 'privmsg', changeNick: 'changeNick',\r
-                channelInfo: 'channelInfo', mode: 'mode'\r
+                ctcpRequest: 'ctcpRequest', ctcpResponse: 'ctcpResponse',\r
+                notice: 'notice', msg: 'privmsg', say: 'privmsg',\r
+                changeNick: 'changeNick', channelInfo: 'channelInfo',\r
+                mode: 'mode', quit: 'quit'\r
             };\r
 \r
-            // Proxy each gateway method\r
             _.each(funcs, function(gateway_fn, func_name) {\r
                 obj[func_name] = function() {\r
                     var fn_name = gateway_fn;\r
@@ -88,6 +137,46 @@ _kiwi.global = {
                 };\r
             });\r
 \r
+            // Now for some network related functions...\r
+            obj.createQuery = function(nick) {\r
+                var network, restricted_keys;\r
+\r
+                network = getNetwork();\r
+                if (!network) {\r
+                    return;\r
+                }\r
+\r
+                return network.createQuery(nick);\r
+            };\r
+\r
+            // Add the networks getters/setters\r
+            obj.get = function(name) {\r
+                var network, restricted_keys;\r
+\r
+                network = getNetwork();\r
+                if (!network) {\r
+                    return;\r
+                }\r
+\r
+                restricted_keys = [\r
+                    'password'\r
+                ];\r
+                if (restricted_keys.indexOf(name) > -1) {\r
+                    return undefined;\r
+                }\r
+\r
+                return network.get(name);\r
+            };\r
+\r
+            obj.set = function() {\r
+                var network = getNetwork();\r
+                if (!network) {\r
+                    return;\r
+                }\r
+\r
+                return network.set.apply(network, arguments);\r
+            };\r
+\r
             return obj;\r
         },\r
 \r
@@ -104,46 +193,67 @@ _kiwi.global = {
                 };\r
             });\r
 \r
+            // Give access to the control input textarea\r
+            obj.input = _kiwi.app.controlbox.$('.inp');\r
+\r
             return obj;\r
         }\r
     },\r
 \r
     // Entry point to start the kiwi application\r
     init: function (opts, callback) {\r
-        var continueStart, locale;\r
+        var locale_promise, theme_promise,\r
+            that = this;\r
+\r
         opts = opts || {};\r
 \r
-        continueInit = function (locale, s, xhr) {\r
-            if (locale) {\r
-                _kiwi.global.i18n = new Jed(locale);\r
-            } else {\r
-                _kiwi.global.i18n = new Jed();\r
-            }\r
+        this.initUtils();\r
+\r
+        // Set up the settings datastore\r
+        _kiwi.global.settings = _kiwi.model.DataStore.instance('kiwi.settings');\r
+        _kiwi.global.settings.load();\r
+\r
+        // Set the window title\r
+        window.document.title = opts.server_settings.client.window_title || 'Kiwi IRC';\r
+\r
+        locale_promise = new Promise(function (resolve) {\r
+            var locale = _kiwi.global.settings.get('locale') || 'magic';\r
+            $.getJSON(opts.base_path + '/assets/locales/' + locale + '.json', function (locale) {\r
+                if (locale) {\r
+                    that.i18n = new Jed(locale);\r
+                } else {\r
+                    that.i18n = new Jed();\r
+                }\r
+                resolve();\r
+            });\r
+        });\r
 \r
+        theme_promise = new Promise(function (resolve) {\r
+            var text_theme = opts.server_settings.client.settings.text_theme || 'default';\r
+            $.getJSON(opts.base_path + '/assets/text_themes/' + text_theme + '.json', function(text_theme) {\r
+                opts.text_theme = text_theme;\r
+                resolve();\r
+            });\r
+        });\r
+\r
+\r
+        Promise.all([locale_promise, theme_promise]).then(function () {\r
             _kiwi.app = new _kiwi.model.Application(opts);\r
 \r
             // Start the client up\r
             _kiwi.app.initializeInterfaces();\r
 \r
+            // Event emitter to let plugins interface with parts of kiwi\r
+            _kiwi.global.events  = new PluginInterface();\r
+\r
             // Now everything has started up, load the plugin manager for third party plugins\r
             _kiwi.global.plugins = new _kiwi.model.PluginManager();\r
 \r
-            callback && callback();\r
-        };\r
+            callback();\r
 \r
-        // Set up the settings datastore\r
-        _kiwi.global.settings = _kiwi.model.DataStore.instance('kiwi.settings');\r
-        _kiwi.global.settings.load();\r
-\r
-        // Set the window title\r
-        window.document.title = opts.server_settings.client.window_title || 'Kiwi IRC';\r
-\r
-        locale = _kiwi.global.settings.get('locale');\r
-        if (!locale) {\r
-            $.getJSON(opts.base_path + '/assets/locales/magic.json', continueInit);\r
-        } else {\r
-            $.getJSON(opts.base_path + '/assets/locales/' + locale + '.json', continueInit);\r
-        }\r
+        }).then(null, function(err) {\r
+            console.error(err.stack);\r
+        });\r
     },\r
 \r
     start: function() {\r
@@ -334,4 +444,4 @@ if (typeof global !== 'undefined') {
 } else {\r
     // Not within a closure so set a var in the current scope\r
     var kiwi = _kiwi.global;\r
-}
\ No newline at end of file
+}\r