Reconnecting when IRCd drops the connection
[KiwiIRC.git] / client / src / views / serverselect.js
1 _kiwi.view.ServerSelect = Backbone.View.extend({
2 events: {
3 'submit form': 'submitForm',
4 'click .show_more': 'showMore',
5 'change .have_pass input': 'showPass',
6 'change .have_key input': 'showKey',
7 'click .fa-key': 'channelKeyIconClick',
8 'click .show_server': 'showServer'
9 },
10
11 initialize: function () {
12 var that = this,
13 text = {
14 think_nick: _kiwi.global.i18n.translate('client_views_serverselect_form_title').fetch(),
15 nickname: _kiwi.global.i18n.translate('client_views_serverselect_nickname').fetch(),
16 have_password: _kiwi.global.i18n.translate('client_views_serverselect_enable_password').fetch(),
17 password: _kiwi.global.i18n.translate('client_views_serverselect_password').fetch(),
18 channel: _kiwi.global.i18n.translate('client_views_serverselect_channel').fetch(),
19 channel_key: _kiwi.global.i18n.translate('client_views_serverselect_channelkey').fetch(),
20 require_key: _kiwi.global.i18n.translate('client_views_serverselect_channelkey_required').fetch(),
21 key: _kiwi.global.i18n.translate('client_views_serverselect_key').fetch(),
22 start: _kiwi.global.i18n.translate('client_views_serverselect_connection_start').fetch(),
23 server_network: _kiwi.global.i18n.translate('client_views_serverselect_server_and_network').fetch(),
24 server: _kiwi.global.i18n.translate('client_views_serverselect_server').fetch(),
25 port: _kiwi.global.i18n.translate('client_views_serverselect_port').fetch(),
26 powered_by: _kiwi.global.i18n.translate('client_views_serverselect_poweredby').fetch()
27 };
28
29 this.$el = $(_.template($('#tmpl_server_select').html().trim(), text));
30
31 // Remove the 'more' link if the server has disabled server changing
32 if (_kiwi.app.server_settings && _kiwi.app.server_settings.connection) {
33 if (!_kiwi.app.server_settings.connection.allow_change) {
34 this.$el.find('.show_more').remove();
35 this.$el.addClass('single_server');
36 }
37 }
38
39 // Are currently showing all the controlls or just a nick_change box?
40 this.state = 'all';
41
42 this.more_shown = false;
43
44 this.model.bind('new_network', this.newNetwork, this);
45
46 this.gateway = _kiwi.global.components.Network();
47 this.gateway.on('connect', this.networkConnected, this);
48 this.gateway.on('connecting', this.networkConnecting, this);
49 this.gateway.on('disconnect', this.networkDisconnected, this);
50 this.gateway.on('irc_error', this.onIrcError, this);
51 },
52
53 dispose: function() {
54 this.model.off('new_network', this.newNetwork, this);
55 this.gateway.off();
56
57 this.remove();
58 },
59
60 submitForm: function (event) {
61 event.preventDefault();
62
63 // Make sure a nick is chosen
64 if (!$('input.nick', this.$el).val().trim()) {
65 this.setStatus(_kiwi.global.i18n.translate('client_views_serverselect_nickname_error_empty').fetch());
66 $('input.nick', this.$el).select();
67 return;
68 }
69
70 if (this.state === 'nick_change') {
71 this.submitNickChange(event);
72 } else {
73 this.submitLogin(event);
74 }
75
76 $('button', this.$el).attr('disabled', 1);
77 return;
78 },
79
80 submitLogin: function (event) {
81 // If submitting is disabled, don't do anything
82 if ($('button', this.$el).attr('disabled')) return;
83
84 var values = {
85 nick: $('input.nick', this.$el).val(),
86 server: $('input.server', this.$el).val(),
87 port: $('input.port', this.$el).val(),
88 ssl: $('input.ssl', this.$el).prop('checked'),
89 password: $('input.password', this.$el).val(),
90 channel: $('input.channel', this.$el).val(),
91 channel_key: $('input.channel_key', this.$el).val(),
92 options: this.server_options
93 };
94
95 this.trigger('server_connect', values);
96 },
97
98 submitNickChange: function (event) {
99 _kiwi.gateway.changeNick(null, $('input.nick', this.$el).val());
100 this.networkConnecting();
101 },
102
103 showPass: function (event) {
104 if (this.$el.find('tr.have_pass input').is(':checked')) {
105 this.$el.find('tr.pass').show().find('input').focus();
106 } else {
107 this.$el.find('tr.pass').hide().find('input').val('');
108 }
109 },
110
111 channelKeyIconClick: function (event) {
112 this.$el.find('tr.have_key input').click();
113 },
114
115 showKey: function (event) {
116 if (this.$el.find('tr.have_key input').is(':checked')) {
117 this.$el.find('tr.key').show().find('input').focus();
118 } else {
119 this.$el.find('tr.key').hide().find('input').val('');
120 }
121 },
122
123 showMore: function (event) {
124 if (!this.more_shown) {
125 $('.more', this.$el).slideDown('fast');
126 $('.show_more', this.$el)
127 .children('.fa-caret-down')
128 .removeClass('fa-caret-down')
129 .addClass('fa-caret-up');
130 $('input.server', this.$el).select();
131 this.more_shown = true;
132 } else {
133 $('.more', this.$el).slideUp('fast');
134 $('.show_more', this.$el)
135 .children('.fs-caret-up')
136 .removeClass('fa-caret-up')
137 .addClass('fa-caret-down');
138 $('input.nick', this.$el).select();
139 this.more_shown = false;
140 }
141 },
142
143 populateFields: function (defaults) {
144 var nick, server, port, channel, channel_key, ssl, password;
145
146 defaults = defaults || {};
147
148 nick = defaults.nick || '';
149 server = defaults.server || '';
150 port = defaults.port || 6667;
151 ssl = defaults.ssl || 0;
152 password = defaults.password || '';
153 channel = defaults.channel || '';
154 channel_key = defaults.channel_key || '';
155
156 $('input.nick', this.$el).val(nick);
157 $('input.server', this.$el).val(server);
158 $('input.port', this.$el).val(port);
159 $('input.ssl', this.$el).prop('checked', ssl);
160 $('input#server_select_show_pass', this.$el).prop('checked', !(!password));
161 $('input.password', this.$el).val(password);
162 if (!(!password)) {
163 $('tr.pass', this.$el).show();
164 }
165 $('input.channel', this.$el).val(channel);
166 $('input#server_select_show_channel_key', this.$el).prop('checked', !(!channel_key));
167 $('input.channel_key', this.$el).val(channel_key);
168 if (!(!channel_key)) {
169 $('tr.key', this.$el).show();
170 }
171
172 // Temporary values
173 this.server_options = {};
174
175 if (defaults.encoding)
176 this.server_options.encoding = defaults.encoding;
177 },
178
179 hide: function () {
180 this.$el.slideUp();
181 },
182
183 show: function (new_state) {
184 new_state = new_state || 'all';
185
186 this.$el.show();
187
188 if (new_state === 'all') {
189 $('.show_more', this.$el).show();
190
191 } else if (new_state === 'more') {
192 $('.more', this.$el).slideDown('fast');
193
194 } else if (new_state === 'nick_change') {
195 $('.more', this.$el).hide();
196 $('.show_more', this.$el).hide();
197 $('input.nick', this.$el).select();
198
199 } else if (new_state === 'enter_password') {
200 $('.more', this.$el).hide();
201 $('.show_more', this.$el).hide();
202 $('input.password', this.$el).select();
203 }
204
205 this.state = new_state;
206 },
207
208 infoBoxShow: function() {
209 var $side_panel = this.$el.find('.side_panel');
210
211 // Some theme may hide the info panel so check before we
212 // resize ourselves
213 if (!$side_panel.is(':visible'))
214 return;
215
216 this.$el.animate({
217 width: parseInt($side_panel.css('left'), 10) + $side_panel.find('.content:first').outerWidth()
218 });
219 },
220
221 infoBoxHide: function() {
222 var $side_panel = this.$el.find('.side_panel');
223 this.$el.animate({
224 width: parseInt($side_panel.css('left'), 10)
225 });
226 },
227
228 infoBoxSet: function($info_view) {
229 this.$el.find('.side_panel .content')
230 .empty()
231 .append($info_view);
232 },
233
234 setStatus: function (text, class_name) {
235 $('.status', this.$el)
236 .text(text)
237 .attr('class', 'status')
238 .addClass(class_name||'')
239 .show();
240 },
241 clearStatus: function () {
242 $('.status', this.$el).hide();
243 },
244
245 reset: function() {
246 this.populateFields();
247 this.clearStatus();
248
249 this.$('button').attr('disabled', null);
250 },
251
252 newNetwork: function(network) {
253 // Keep a reference to this network so we can interact with it
254 this.model.current_connecting_network = network;
255 },
256
257 networkConnected: function (event) {
258 this.model.trigger('connected', _kiwi.app.connections.getByConnectionId(event.server));
259 this.model.current_connecting_network = null;
260 },
261
262 networkDisconnected: function () {
263 this.model.current_connecting_network = null;
264 this.state = 'all';
265 },
266
267 networkConnecting: function (event) {
268 this.model.trigger('connecting');
269 this.setStatus(_kiwi.global.i18n.translate('client_views_serverselect_connection_trying').fetch(), 'ok');
270
271 this.$('.status').append('<a class="show_server"><i class="fa fa-info-circle"></i></a>');
272 },
273
274 showServer: function() {
275 // If we don't have a current connection in the making then we have nothing to show
276 if (!this.model.current_connecting_network)
277 return;
278
279 _kiwi.app.view.barsShow();
280 this.model.current_connecting_network.panels.server.view.show();
281 },
282
283 onIrcError: function (data) {
284 $('button', this.$el).attr('disabled', null);
285
286 switch(data.error) {
287 case 'nickname_in_use':
288 this.setStatus(_kiwi.global.i18n.translate('client_views_serverselect_nickname_error_alreadyinuse').fetch());
289 this.show('nick_change');
290 this.$el.find('.nick').select();
291 break;
292 case 'erroneus_nickname':
293 if (data.reason) {
294 this.setStatus(data.reason);
295 } else {
296 this.setStatus(_kiwi.global.i18n.translate('client_views_serverselect_nickname_invalid').fetch());
297 }
298 this.show('nick_change');
299 this.$el.find('.nick').select();
300 break;
301 case 'password_mismatch':
302 this.setStatus(_kiwi.global.i18n.translate('client_views_serverselect_password_incorrect').fetch());
303 this.show('enter_password');
304 this.$el.find('.password').select();
305 break;
306 }
307 },
308
309 showError: function (error_reason) {
310 var err_text = _kiwi.global.i18n.translate('client_views_serverselect_connection_error').fetch();
311
312 if (error_reason) {
313 switch (error_reason) {
314 case 'ENOTFOUND':
315 err_text = _kiwi.global.i18n.translate('client_views_serverselect_server_notfound').fetch();
316 break;
317
318 case 'ECONNREFUSED':
319 err_text += ' (' + _kiwi.global.i18n.translate('client_views_serverselect_connection_refused').fetch() + ')';
320 break;
321
322 default:
323 err_text += ' (' + error_reason + ')';
324 }
325 }
326
327 this.setStatus(err_text, 'error');
328 $('button', this.$el).attr('disabled', null);
329 this.show();
330 }
331 });