Merge branch 'development' of https://github.com/CoryChaplin/KiwiIRC into text_themes
[KiwiIRC.git] / client / src / app.js
1 // Holds anything kiwi client specific (ie. front, gateway, _kiwi.plugs..)
2 /**
3 * @namespace
4 */
5 var _kiwi = {};
6
7 _kiwi.model = {};
8 _kiwi.view = {};
9 _kiwi.applets = {};
10
11
12 /**
13 * A global container for third party access
14 * Will be used to access a limited subset of kiwi functionality
15 * and data (think: plugins)
16 */
17 _kiwi.global = {
18 build_version: '', // Kiwi IRC version this is built from (Set from index.html)
19 settings: undefined, // Instance of _kiwi.model.DataStore
20 plugins: undefined,
21 utils: undefined, // TODO: Re-usable methods
22 user: undefined, // TODO: Limited user methods
23 server: undefined, // TODO: Limited server methods
24
25 // TODO: think of a better term for this as it will also refer to queries
26 channels: undefined, // TODO: Limited access to panels list
27
28 addMediaMessageType: function(match, buildHtml) {
29 _kiwi.view.MediaMessage.addType(match, buildHtml);
30 },
31
32 // Event managers for plugins
33 components: {
34 EventComponent: function(event_source, proxy_event_name) {
35 function proxyEvent(event_name, event_data) {
36 if (proxy_event_name !== 'all') {
37 event_data = event_name.event_data;
38 event_name = event_name.event_name;
39 }
40
41 this.trigger(event_name, event_data);
42 }
43
44 // The event we are to proxy
45 proxy_event_name = proxy_event_name || 'all';
46
47
48 _.extend(this, Backbone.Events);
49 this._source = event_source;
50
51 // Proxy the events to this dispatcher
52 event_source.on(proxy_event_name, proxyEvent, this);
53
54 // Clean up this object
55 this.dispose = function () {
56 event_source.off(proxy_event_name, proxyEvent);
57 this.off();
58 delete this.event_source;
59 };
60 },
61
62 Network: function(connection_id) {
63 var connection_event;
64
65 if (typeof connection_id !== 'undefined') {
66 connection_event = 'connection:' + connection_id.toString();
67 }
68
69 var obj = new this.EventComponent(_kiwi.gateway, connection_event);
70 var funcs = {
71 kiwi: 'kiwi', raw: 'raw', kick: 'kick', topic: 'topic',
72 part: 'part', join: 'join', action: 'action', ctcp: 'ctcp',
73 notice: 'notice', msg: 'privmsg', changeNick: 'changeNick',
74 channelInfo: 'channelInfo', mode: 'mode'
75 };
76
77 // Proxy each gateway method
78 _.each(funcs, function(gateway_fn, func_name) {
79 obj[func_name] = function() {
80 var fn_name = gateway_fn;
81
82 // Add connection_id to the argument list
83 var args = Array.prototype.slice.call(arguments, 0);
84 args.unshift(connection_id);
85
86 // Call the gateway function on behalf of this connection
87 return _kiwi.gateway[fn_name].apply(_kiwi.gateway, args);
88 };
89 });
90
91 return obj;
92 },
93
94 ControlInput: function() {
95 var obj = new this.EventComponent(_kiwi.app.controlbox);
96 var funcs = {
97 run: 'processInput', addPluginIcon: 'addPluginIcon'
98 };
99
100 _.each(funcs, function(controlbox_fn, func_name) {
101 obj[func_name] = function() {
102 var fn_name = controlbox_fn;
103 return _kiwi.app.controlbox[fn_name].apply(_kiwi.app.controlbox, arguments);
104 };
105 });
106
107 return obj;
108 }
109 },
110
111 // Entry point to start the kiwi application
112 init: function (opts, callback) {
113 var continueStart, locale, jobs, igniteTextTheme, text_theme;
114 opts = opts || {};
115
116 jobs = new JobManager();
117 jobs.onFinish(callback);
118
119 continueInit = function (locale, s, xhr) {
120 if (locale) {
121 _kiwi.global.i18n = new Jed(locale);
122 } else {
123 _kiwi.global.i18n = new Jed();
124 }
125
126 _kiwi.app = new _kiwi.model.Application(opts);
127
128 // Start the client up
129 _kiwi.app.initializeInterfaces();
130
131 // Now everything has started up, load the plugin manager for third party plugins
132 _kiwi.global.plugins = new _kiwi.model.PluginManager();
133
134 jobs.finishJob('load_locale');
135 };
136
137 igniteTextTheme = function(text_theme, s, xhr) {
138 _kiwi.global.text_theme = new _kiwi.view.TextTheme(text_theme);
139
140 jobs.finishJob('load_text_theme');
141 };
142
143 // Set up the settings datastore
144 _kiwi.global.settings = _kiwi.model.DataStore.instance('kiwi.settings');
145 _kiwi.global.settings.load();
146
147 // Set the window title
148 window.document.title = opts.server_settings.client.window_title || 'Kiwi IRC';
149
150 jobs.registerJob('load_locale');
151 locale = _kiwi.global.settings.get('locale');
152 if (!locale) {
153 $.getJSON(opts.base_path + '/assets/locales/magic.json', continueInit);
154 } else {
155 $.getJSON(opts.base_path + '/assets/locales/' + locale + '.json', continueInit);
156 }
157
158 jobs.registerJob('load_text_theme');
159 text_theme = opts.text_theme;
160 if (!text_theme) {
161 $.getJSON(opts.base_path + '/assets/text_themes/default.json', igniteTextTheme);
162 } else {
163 $.getJSON(opts.base_path + '/assets/text_themes/' + text_theme + '.json', igniteTextTheme);
164 }
165 },
166
167 start: function() {
168 _kiwi.app.showStartup();
169 },
170
171 // Allow plugins to change the startup applet
172 registerStartupApplet: function(startup_applet_name) {
173 _kiwi.app.startup_applet_name = startup_applet_name;
174 },
175
176 /**
177 * Open a new IRC connection
178 * @param {Object} connection_details {nick, host, port, ssl, password, options}
179 * @param {Function} callback function(err, network){}
180 */
181 newIrcConnection: function(connection_details, callback) {
182 _kiwi.gateway.newConnection(connection_details, callback);
183 },
184
185
186 /**
187 * Taking settings from the server and URL, extract the default server/channel/nick settings
188 */
189 defaultServerSettings: function () {
190 var parts;
191 var defaults = {
192 nick: '',
193 server: '',
194 port: 6667,
195 ssl: false,
196 channel: '',
197 channel_key: ''
198 };
199 var uricheck;
200
201
202 /**
203 * Get any settings set by the server
204 * These settings may be changed in the server selection dialog or via URL parameters
205 */
206 if (_kiwi.app.server_settings.client) {
207 if (_kiwi.app.server_settings.client.nick)
208 defaults.nick = _kiwi.app.server_settings.client.nick;
209
210 if (_kiwi.app.server_settings.client.server)
211 defaults.server = _kiwi.app.server_settings.client.server;
212
213 if (_kiwi.app.server_settings.client.port)
214 defaults.port = _kiwi.app.server_settings.client.port;
215
216 if (_kiwi.app.server_settings.client.ssl)
217 defaults.ssl = _kiwi.app.server_settings.client.ssl;
218
219 if (_kiwi.app.server_settings.client.channel)
220 defaults.channel = _kiwi.app.server_settings.client.channel;
221
222 if (_kiwi.app.server_settings.client.channel_key)
223 defaults.channel_key = _kiwi.app.server_settings.client.channel_key;
224 }
225
226
227
228 /**
229 * Get any settings passed in the URL
230 * These settings may be changed in the server selection dialog
231 */
232
233 // Any query parameters first
234 if (getQueryVariable('nick'))
235 defaults.nick = getQueryVariable('nick');
236
237 if (window.location.hash)
238 defaults.channel = window.location.hash;
239
240
241 // Process the URL part by part, extracting as we go
242 parts = window.location.pathname.toString().replace(_kiwi.app.get('base_path'), '').split('/');
243
244 if (parts.length > 0) {
245 parts.shift();
246
247 if (parts.length > 0 && parts[0]) {
248 // 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.
249 uricheck = parts[0].substr(0, 7).toLowerCase();
250 if ((uricheck === 'ircs%3a') || (uricheck.substr(0,6) === 'irc%3a')) {
251 parts[0] = decodeURIComponent(parts[0]);
252 // irc[s]://<host>[:<port>]/[<channel>[?<password>]]
253 uricheck = /^irc(s)?:(?:\/\/?)?([^:\/]+)(?::([0-9]+))?(?:(?:\/)([^\?]*)(?:(?:\?)(.*))?)?$/.exec(parts[0]);
254 /*
255 uricheck[1] = ssl (optional)
256 uricheck[2] = host
257 uricheck[3] = port (optional)
258 uricheck[4] = channel (optional)
259 uricheck[5] = channel key (optional, channel must also be set)
260 */
261 if (uricheck) {
262 if (typeof uricheck[1] !== 'undefined') {
263 defaults.ssl = true;
264 if (defaults.port === 6667) {
265 defaults.port = 6697;
266 }
267 }
268 defaults.server = uricheck[2];
269 if (typeof uricheck[3] !== 'undefined') {
270 defaults.port = uricheck[3];
271 }
272 if (typeof uricheck[4] !== 'undefined') {
273 defaults.channel = '#' + uricheck[4];
274 if (typeof uricheck[5] !== 'undefined') {
275 defaults.channel_key = uricheck[5];
276 }
277 }
278 }
279 parts = [];
280 } else {
281 // Extract the port+ssl if we find one
282 if (parts[0].search(/:/) > 0) {
283 defaults.port = parts[0].substring(parts[0].search(/:/) + 1);
284 defaults.server = parts[0].substring(0, parts[0].search(/:/));
285 if (defaults.port[0] === '+') {
286 defaults.port = parseInt(defaults.port.substring(1), 10);
287 defaults.ssl = true;
288 } else {
289 defaults.ssl = false;
290 }
291
292 } else {
293 defaults.server = parts[0];
294 }
295
296 parts.shift();
297 }
298 }
299
300 if (parts.length > 0 && parts[0]) {
301 defaults.channel = '#' + parts[0];
302 parts.shift();
303 }
304 }
305
306 // If any settings have been given by the server.. override any auto detected settings
307 /**
308 * Get any server restrictions as set in the server config
309 * These settings can not be changed in the server selection dialog
310 */
311 if (_kiwi.app.server_settings && _kiwi.app.server_settings.connection) {
312 if (_kiwi.app.server_settings.connection.server) {
313 defaults.server = _kiwi.app.server_settings.connection.server;
314 }
315
316 if (_kiwi.app.server_settings.connection.port) {
317 defaults.port = _kiwi.app.server_settings.connection.port;
318 }
319
320 if (_kiwi.app.server_settings.connection.ssl) {
321 defaults.ssl = _kiwi.app.server_settings.connection.ssl;
322 }
323
324 if (_kiwi.app.server_settings.connection.channel) {
325 defaults.channel = _kiwi.app.server_settings.connection.channel;
326 }
327
328 if (_kiwi.app.server_settings.connection.channel_key) {
329 defaults.channel_key = _kiwi.app.server_settings.connection.channel_key;
330 }
331
332 if (_kiwi.app.server_settings.connection.nick) {
333 defaults.nick = _kiwi.app.server_settings.connection.nick;
334 }
335 }
336
337 // Set any random numbers if needed
338 defaults.nick = defaults.nick.replace('?', Math.floor(Math.random() * 100000).toString());
339
340 if (getQueryVariable('encoding'))
341 defaults.encoding = getQueryVariable('encoding');
342
343 return defaults;
344 },
345 };
346
347
348
349 // If within a closure, expose the kiwi globals
350 if (typeof global !== 'undefined') {
351 global.kiwi = _kiwi.global;
352 } else {
353 // Not within a closure so set a var in the current scope
354 var kiwi = _kiwi.global;
355 }