X-Git-Url: https://vcs.fsf.org/?a=blobdiff_plain;f=client%2Fsrc%2Fapp.js;h=619507cc7e2569c22b6f35c2cf12d77573571142;hb=f91187cfa693c4093033f1698deb90e6b70a7acc;hp=8349f697aa7be36f603d6eb05ff7650522bc2061;hpb=ac915057a143b0e4c44f7a582457597a4f0dc188;p=KiwiIRC.git diff --git a/client/src/app.js b/client/src/app.js index 8349f69..619507c 100644 --- a/client/src/app.js +++ b/client/src/app.js @@ -4,9 +4,11 @@ */ var _kiwi = {}; +_kiwi.misc = {}; _kiwi.model = {}; _kiwi.view = {}; _kiwi.applets = {}; +_kiwi.utils = {}; /** @@ -15,14 +17,26 @@ _kiwi.applets = {}; * and data (think: plugins) */ _kiwi.global = { + build_version: '', // Kiwi IRC version this is built from (Set from index.html) settings: undefined, // Instance of _kiwi.model.DataStore - plugins: undefined, - utils: undefined, // TODO: Re-usable methods - user: undefined, // TODO: Limited user methods - server: undefined, // TODO: Limited server methods - - // TODO: think of a better term for this as it will also refer to queries - channels: undefined, // TODO: Limited access to panels list + plugins: undefined, // Instance of _kiwi.model.PluginManager + events: undefined, // Instance of PluginInterface + rpc: undefined, // Instance of WebsocketRpc + utils: {}, // References to misc. re-usable helpers / functions + + // Make public some internal utils for plugins to make use of + initUtils: function() { + this.utils.randomString = randomString; + this.utils.secondsToTime = secondsToTime; + this.utils.parseISO8601 = parseISO8601; + this.utils.escapeRegex = escapeRegex; + this.utils.formatIRCMsg = formatIRCMsg; + this.utils.styleText = styleText; + this.utils.hsl2rgb = hsl2rgb; + + this.utils.notifications = _kiwi.utils.notifications; + this.utils.formatDate = _kiwi.utils.formatDate; + }, addMediaMessageType: function(match, buildHtml) { _kiwi.view.MediaMessage.addType(match, buildHtml); @@ -31,8 +45,27 @@ _kiwi.global = { // Event managers for plugins components: { EventComponent: function(event_source, proxy_event_name) { + /* + * proxyEvent() listens for events then re-triggers them on its own + * event emitter. Why? So we can .off() on this emitter without + * effecting the source of events. Handy for plugins that we don't + * trust meddling with the core events. + * + * If listening for 'all' events the arguments are as follows: + * 1. Name of the triggered event + * 2. The event data + * For all other events, we only have one argument: + * 1. The event data + * + * When this is used via `new kiwi.components.Network()`, this listens + * for 'all' events so the first argument is the event name which is + * the connection ID. We don't want to re-trigger this event name so + * we need to juggle the arguments to find the real event name we want + * to emit. + */ function proxyEvent(event_name, event_data) { - if (proxy_event_name !== 'all') { + if (proxy_event_name == 'all') { + } else { event_data = event_name.event_data; event_name = event_name.event_name; } @@ -43,7 +76,6 @@ _kiwi.global = { // The event we are to proxy proxy_event_name = proxy_event_name || 'all'; - _.extend(this, Backbone.Events); this._source = event_source; @@ -61,19 +93,37 @@ _kiwi.global = { Network: function(connection_id) { var connection_event; + // If no connection id given, use all connections if (typeof connection_id !== 'undefined') { connection_event = 'connection:' + connection_id.toString(); + } else { + connection_event = 'connection'; } + // Helper to get the network object + var getNetwork = function() { + var network = typeof connection_id === 'undefined' ? + _kiwi.app.connections.active_connection : + _kiwi.app.connections.getByConnectionId(connection_id); + + return network ? + network : + undefined; + }; + + // Create the return object (events proxy from the gateway) var obj = new this.EventComponent(_kiwi.gateway, connection_event); + + // Proxy several gateway functions onto the return object var funcs = { kiwi: 'kiwi', raw: 'raw', kick: 'kick', topic: 'topic', part: 'part', join: 'join', action: 'action', ctcp: 'ctcp', - notice: 'notice', msg: 'privmsg', changeNick: 'changeNick', - channelInfo: 'channelInfo', mode: 'mode' + ctcpRequest: 'ctcpRequest', ctcpResponse: 'ctcpResponse', + notice: 'notice', msg: 'privmsg', say: 'privmsg', + changeNick: 'changeNick', channelInfo: 'channelInfo', + mode: 'mode', quit: 'quit' }; - // Proxy each gateway method _.each(funcs, function(gateway_fn, func_name) { obj[func_name] = function() { var fn_name = gateway_fn; @@ -87,6 +137,46 @@ _kiwi.global = { }; }); + // Now for some network related functions... + obj.createQuery = function(nick) { + var network, restricted_keys; + + network = getNetwork(); + if (!network) { + return; + } + + return network.createQuery(nick); + }; + + // Add the networks getters/setters + obj.get = function(name) { + var network, restricted_keys; + + network = getNetwork(); + if (!network) { + return; + } + + restricted_keys = [ + 'password' + ]; + if (restricted_keys.indexOf(name) > -1) { + return undefined; + } + + return network.get(name); + }; + + obj.set = function() { + var network = getNetwork(); + if (!network) { + return; + } + + return network.set.apply(network, arguments); + }; + return obj; }, @@ -103,47 +193,247 @@ _kiwi.global = { }; }); + // Give access to the control input textarea + obj.input = _kiwi.app.controlbox.$('.inp'); + return obj; } }, // Entry point to start the kiwi application - start: function (opts, callback) { - var continueStart, locale; + init: function (opts, callback) { + var locale_promise, theme_promise, + that = this; + opts = opts || {}; - continueStart = function (locale, s, xhr) { - if (locale) { - _kiwi.global.i18n = new Jed(locale); - } else { - _kiwi.global.i18n = new Jed(); - } + this.initUtils(); + // Set up the settings datastore + _kiwi.global.settings = _kiwi.model.DataStore.instance('kiwi.settings'); + _kiwi.global.settings.load(); + + // Set the window title + window.document.title = opts.server_settings.client.window_title || 'Kiwi IRC'; + + locale_promise = new Promise(function (resolve) { + var locale = _kiwi.global.settings.get('locale') || 'magic'; + $.getJSON(opts.base_path + '/assets/locales/' + locale + '.json', function (locale) { + if (locale) { + that.i18n = new Jed(locale); + } else { + that.i18n = new Jed(); + } + resolve(); + }); + }); + + theme_promise = new Promise(function (resolve) { + var text_theme = opts.server_settings.client.settings.text_theme || 'default'; + $.getJSON(opts.base_path + '/assets/text_themes/' + text_theme + '.json', function(text_theme) { + opts.text_theme = text_theme; + resolve(); + }); + }); + + + Promise.all([locale_promise, theme_promise]).then(function () { _kiwi.app = new _kiwi.model.Application(opts); // Start the client up - _kiwi.app.start(); + _kiwi.app.initializeInterfaces(); + + // Event emitter to let plugins interface with parts of kiwi + _kiwi.global.events = new PluginInterface(); // Now everything has started up, load the plugin manager for third party plugins _kiwi.global.plugins = new _kiwi.model.PluginManager(); - callback && callback(); + callback(); + + }).then(null, function(err) { + console.error(err.stack); + }); + }, + + start: function() { + _kiwi.app.showStartup(); + }, + + // Allow plugins to change the startup applet + registerStartupApplet: function(startup_applet_name) { + _kiwi.app.startup_applet_name = startup_applet_name; + }, + + /** + * Open a new IRC connection + * @param {Object} connection_details {nick, host, port, ssl, password, options} + * @param {Function} callback function(err, network){} + */ + newIrcConnection: function(connection_details, callback) { + _kiwi.gateway.newConnection(connection_details, callback); + }, + + + /** + * Taking settings from the server and URL, extract the default server/channel/nick settings + */ + defaultServerSettings: function () { + var parts; + var defaults = { + nick: '', + server: '', + port: 6667, + ssl: false, + channel: '', + channel_key: '' }; + var uricheck; - // Set up the settings datastore - _kiwi.global.settings = _kiwi.model.DataStore.instance('kiwi.settings'); - _kiwi.global.settings.load(); - // Set the window title - window.document.title = opts.server_settings.client.window_title || 'Kiwi IRC'; + /** + * 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; - locale = _kiwi.global.settings.get('locale'); - if (!locale) { - $.getJSON(opts.base_path + '/assets/locales/magic.json', continueStart); - } else { - $.getJSON(opts.base_path + '/assets/locales/' + locale + '.json', continueStart); + 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]://[:]/[[?]] + 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'); + + return defaults; + }, }; @@ -154,4 +444,4 @@ if (typeof global !== 'undefined') { } else { // Not within a closure so set a var in the current scope var kiwi = _kiwi.global; -} \ No newline at end of file +}