diff --git a/css/glowingbear.css b/css/glowingbear.css
index cf54fed..64b4f65 100644
--- a/css/glowingbear.css
+++ b/css/glowingbear.css
@@ -263,6 +263,19 @@ td.time {
font-family: sans-serif;
}
+#reconnect {
+ top: 35px;
+ position: fixed;
+ z-index: 9999;
+ width: 80%;
+ margin: 0;
+ padding: 5px;
+ left: 10%;
+}
+#reconnect a {
+ color: white;
+}
+
.footer {
position: fixed;
bottom: 0;
diff --git a/index.html b/index.html
index e6ab70d..adad7ef 100644
--- a/index.html
+++ b/index.html
@@ -295,6 +295,11 @@ $ openssl req -nodes -newkey rsa:4096 -keyout relay.pem -x509 -days 365 -out rel
diff --git a/js/connection.js b/js/connection.js
index 5c2eb06..e80c031 100644
--- a/js/connection.js
+++ b/js/connection.js
@@ -12,9 +12,12 @@ weechat.factory('connection',
var protocol = new weeChat.Protocol();
- // Takes care of the connection and websocket hooks
+ var connectionData = [];
+ var reconnectTimer;
- var connect = function (host, port, passwd, ssl, noCompression) {
+ // Takes care of the connection and websocket hooks
+ var connect = function (host, port, passwd, ssl, noCompression, successCallback, failCallback) {
+ connectionData = [host, port, passwd, ssl, noCompression];
var proto = ssl ? 'wss' : 'ws';
// If host is an IPv6 literal wrap it in brackets
if (host.indexOf(":") !== -1) {
@@ -79,21 +82,15 @@ weechat.factory('connection',
// Connection is successful
// Send all the other commands required for initialization
_requestBufferInfos().then(function(bufinfo) {
- //XXX move to handlers?
- var bufferInfos = bufinfo.objects[0].content;
- // buffers objects
- for (var i = 0; i < bufferInfos.length ; i++) {
- var buffer = new models.Buffer(bufferInfos[i]);
- models.addBuffer(buffer);
- // Switch to first buffer on startup
- if (i === 0) {
- models.setActiveBuffer(buffer.id);
- }
- }
+ handlers.handleBufferInfo(bufinfo);
});
_requestHotlist().then(function(hotlist) {
handlers.handleHotlistInfo(hotlist);
+
+ if (successCallback) {
+ successCallback();
+ }
});
_requestSync();
@@ -123,10 +120,19 @@ weechat.factory('connection',
* Handles websocket disconnection
*/
$log.info("Disconnected from relay");
+ if ($rootScope.userdisconnect || !$rootScope.waseverconnected) {
+ handleClose(evt);
+ $rootScope.userdisconnect = false;
+ } else {
+ reconnect(evt);
+ }
+ };
+
+ var handleClose = function (evt) {
ngWebsockets.failCallbacks('disconnection');
$rootScope.connected = false;
$rootScope.$emit('relayDisconnect');
- if (ssl && evt.code === 1006) {
+ if (ssl && evt && evt.code === 1006) {
// A password error doesn't trigger onerror, but certificate issues do. Check time of last error.
if (typeof $rootScope.lastError !== "undefined" && (Date.now() - $rootScope.lastError) < 1000) {
// abnormal disconnect by client, most likely ssl error
@@ -166,11 +172,64 @@ weechat.factory('connection',
$rootScope.errorMessage = true;
$rootScope.securityError = true;
$rootScope.$emit('relayDisconnect');
+
+ if (failCallback) {
+ failCallback();
+ }
}
};
+ var attemptReconnect = function (bufferId, timeout) {
+ $log.info('Attempting to reconnect...');
+ var d = connectionData;
+ connect(d[0], d[1], d[2], d[3], d[4], function() {
+ $rootScope.reconnecting = false;
+ // on success, update active buffer
+ models.setActiveBuffer(bufferId);
+ $log.info('Sucessfully reconnected to relay');
+ }, function() {
+ // on failure, schedule another attempt
+ if (timeout >= 600000) {
+ // If timeout is ten minutes or more, give up
+ $log.info('Failed to reconnect, giving up');
+ handleClose();
+ } else {
+ $log.info('Failed to reconnect, scheduling next attempt in', timeout/1000, 'seconds');
+ // Clear previous timer, if exists
+ if (reconnectTimer !== undefined) {
+ clearTimeout(reconnectTimer);
+ }
+ reconnectTimer = setTimeout(function() {
+ // exponential timeout increase
+ attemptReconnect(bufferId, timeout * 1.5);
+ }, timeout);
+ }
+ });
+ };
+
+
+ var reconnect = function (evt) {
+ if (connectionData.length < 5) {
+ // something is wrong
+ $log.error('Cannot reconnect, connection information is missing');
+ return;
+ }
+
+ $rootScope.reconnecting = true;
+ // Have to do this to get the reconnect banner to show
+ $rootScope.$apply();
+
+ var bufferId = models.getActiveBuffer().id,
+ timeout = 3000; // start with a three-second timeout
+
+ reconnectTimer = setTimeout(function() {
+ attemptReconnect(bufferId, timeout);
+ }, timeout);
+ };
+
var disconnect = function() {
+ $rootScope.userdisconnect = true;
ngWebsockets.send(weeChat.Protocol.formatQuit());
};
@@ -270,7 +329,8 @@ weechat.factory('connection',
sendMessage: sendMessage,
sendCoreCommand: sendCoreCommand,
fetchMoreLines: fetchMoreLines,
- requestNicklist: requestNicklist
+ requestNicklist: requestNicklist,
+ attemptReconnect: attemptReconnect
};
}]);
})();
diff --git a/js/glowingbear.js b/js/glowingbear.js
index edd0724..526c46f 100644
--- a/js/glowingbear.js
+++ b/js/glowingbear.js
@@ -264,6 +264,8 @@ weechat.controller('WeechatCtrl', ['$rootScope', '$scope', '$store', '$timeout',
$rootScope.connected = false;
$rootScope.waseverconnected = false;
+ $rootScope.userdisconnect = false;
+ $rootScope.reconnecting = false;
$rootScope.models = models;
@@ -513,6 +515,10 @@ weechat.controller('WeechatCtrl', ['$rootScope', '$scope', '$store', '$timeout',
$scope.connectbutton = 'Connect';
connection.disconnect();
};
+ $scope.reconnect = function() {
+ var bufferId = models.getActiveBuffer().id;
+ connection.attemptReconnect(bufferId, 3000);
+ };
//XXX this is a bit out of place here, either move up to the rest of the firefox install code or remove
$scope.install = function() {
diff --git a/js/handlers.js b/js/handlers.js
index 8dcae0d..b01757a 100644
--- a/js/handlers.js
+++ b/js/handlers.js
@@ -43,6 +43,53 @@ weechat.factory('handlers', ['$rootScope', '$log', 'models', 'plugins', 'notific
}
};
+ var handleBufferInfo = function(message) {
+ var bufferInfos = message.objects[0].content;
+ // buffers objects
+ for (var i = 0; i < bufferInfos.length ; i++) {
+ var bufferId = bufferInfos[i].pointers[0];
+ var buffer = models.getBuffer(bufferId);
+ if (buffer !== undefined) {
+ // We already know this buffer
+ handleBufferUpdate(buffer, bufferInfos[i]);
+ } else {
+ buffer = new models.Buffer(bufferInfos[i]);
+ models.addBuffer(buffer);
+ // Switch to first buffer on startup
+ if (i === 0) {
+ models.setActiveBuffer(buffer.id);
+ }
+ }
+ }
+ };
+
+ var handleBufferUpdate = function(buffer, message) {
+ if (message.pointers[0] !== buffer.id) {
+ // this is information about some other buffer!
+ return;
+ }
+
+ // weechat properties -- short name can be changed
+ buffer.shortName = message.short_name;
+ buffer.trimmedName = buffer.shortName.replace(/^[#&+]/, '');
+ buffer.title = message.title;
+ buffer.number = message.number;
+
+ // reset these, hotlist info will arrive shortly
+ buffer.notification = 0;
+ buffer.unread = 0;
+ buffer.lastSeen = -1;
+
+ if (message.local_variables.type !== undefined) {
+ buffer.type = message.local_variables.type;
+ buffer.indent = (['channel', 'private'].indexOf(buffer.type) >= 0);
+ }
+
+ if (message.notify !== undefined) {
+ buffer.notify = message.notify;
+ }
+ };
+
var handleBufferLineAdded = function(message) {
message.objects[0].content.forEach(function(l) {
handleLine(l, false);
@@ -216,7 +263,8 @@ weechat.factory('handlers', ['$rootScope', '$log', 'models', 'plugins', 'notific
handleEvent: handleEvent,
handleLineInfo: handleLineInfo,
handleHotlistInfo: handleHotlistInfo,
- handleNicklist: handleNicklist
+ handleNicklist: handleNicklist,
+ handleBufferInfo: handleBufferInfo
};
}]);
diff --git a/js/websockets.js b/js/websockets.js
index 939b31a..44fb552 100644
--- a/js/websockets.js
+++ b/js/websockets.js
@@ -110,7 +110,6 @@ function($rootScope, $q) {
$rootScope.$emit('onMessage', message);
}
- $rootScope.$apply();
};
var connect = function(url,