diff --git a/node_modules/kaefer/lib/client.js b/node_modules/kaefer/lib/client.js
index 5586f63d..3f6bd7f0 100644
--- a/node_modules/kaefer/lib/client.js
+++ b/node_modules/kaefer/lib/client.js
@@ -86,27 +86,29 @@ var connectClient = module.exports = function(connectEio, options) {
});
}
- function reconnect() {
- if (isReconnecting)
+ var timer;
+ function reconnect(delay) {
+ if (isReconnecting && typeof delay !== "number")
return;
reconnectSocket.setSocket(null);
connectAttempts += 1;
- var delay = 250;
- if (connectAttempts > 10) {
- delay = 10 * 1000;
- }
- else if (connectAttempts > 5) {
- delay = 5 * 1000;
- }
- else if (connectAttempts > 3) {
- delay = 1 * 1000;
+ if (typeof delay !== "number") {
+ if (connectAttempts < 10) {
+ delay = 250;
+ }
+ else {
+ delay = Math.min(60000, 250 * Math.pow(2, connectAttempts - 10));
+ }
}
isReconnecting = true;
console.log("Schedule re-connect in: " + delay);
- setTimeout(function() {
+ socket.emit("reconnectDelay", { delay: delay });
+
+ clearTimeout(timer);
+ timer = setTimeout(function() {
isReconnecting = false;
connect();
}, delay);
diff --git a/plugins/c9.core/c9.js b/plugins/c9.core/c9.js
index 7f0947d2..6e7f9b1c 100644
--- a/plugins/c9.core/c9.js
+++ b/plugins/c9.core/c9.js
@@ -57,7 +57,7 @@ define(function(require, module, exports) {
}, plugin);
vfs.on("disconnect", function(reason) {
- setStatus(status & ~STORAGE & ~PROCESS & ~NETWORK);
+ setStatus(state & ~STORAGE & ~PROCESS & ~NETWORK);
emit("disconnect");
}, plugin);
@@ -67,7 +67,7 @@ define(function(require, module, exports) {
}, plugin);
vfs.on("error", function(message) {
- setStatus(status & ~STORAGE & ~PROCESS);
+ setStatus(state & ~STORAGE & ~PROCESS);
// TODO: Don't display all errors?
if (emit("showerrormessage", message) !== false) {
console.error(
diff --git a/plugins/c9.ide.dialog.common/error.css b/plugins/c9.ide.dialog.common/error.css
index f3d14fb7..96f0a115 100644
--- a/plugins/c9.ide.dialog.common/error.css
+++ b/plugins/c9.ide.dialog.common/error.css
@@ -1,18 +1,23 @@
-.errorlabel{
+.errorlabel, .disconnectlabel{
position: absolute;
left: 0;
right: 0;
top: 0;
z-index: 10000000;
- text-align: center;
+ /*text-align: center;*/
pointer-events: none;
.font-smoothing(@error-font-smoothing);
}
-.errorlabel.anim{
+.errorlabel.anim, .disconnectlabel.anim{
transition: top 0.2s;
-moz-transition: top 0.2s; /* Gecko */
-webkit-transition: top 0.2s; /* Safari */
}
+.errorlabel.fade-in{
+ transition: opacity 0.2s;
+ -moz-transition: opacity 0.2s; /* Gecko */
+ -webkit-transition: opacity 0.2s; /* Safari */
+}
.errorlabel div{
background: @error-background;
padding: @error-padding;
@@ -26,6 +31,9 @@
max-width: 100%;
pointer-events: auto;
}
+.errorlabel.fade-in div{
+ border-radius: 3px;
+}
.errorlabel u.close{
.image-2x("@{image-path}/@{error-close-image}", 42px, 28px);
background-position: @error-close-idle-position;
@@ -33,7 +41,7 @@
height: 14px;
position: absolute;
right: 8px;
- top: 8px;
+ top: 6px;
cursor: pointer;
}
.errorlabel u.close:hover{
@@ -45,4 +53,25 @@
.errorlabel div span{
border-bottom: 1px dotted rgb(255, 174, 174);
cursor: help;
+}
+
+.disconnectlabel{
+ z-index: 10000001;
+}
+.disconnectlabel div{
+ background: @disconnect-background;
+ padding: @disconnect-padding;
+ color: @disconnect-color;
+ border-radius: 0 0 3px 3px;
+ box-shadow: @disconnect-box-shadow;
+ line-height: 1.4;
+ display: inline-block;
+ position: relative;
+ word-wrap: break-word;
+ text-align: center;
+ width: 300px;
+ pointer-events: auto;
+}
+.disconnectlabel u{
+ cursor: pointer;
}
\ No newline at end of file
diff --git a/plugins/c9.ide.dialog.common/error.js b/plugins/c9.ide.dialog.common/error.js
index 3642818a..3d28bb20 100644
--- a/plugins/c9.ide.dialog.common/error.js
+++ b/plugins/c9.ide.dialog.common/error.js
@@ -12,22 +12,72 @@ define(function(require, exports, module) {
/***** Initialization *****/
var plugin = new Plugin("Ajax.org", main.consumes);
+ var emit = plugin.getEmitter();
var topPx = 0;
- var error, hideTimeout;
var lastCookie = 0;
+ var offset = 0;
+ var error, hideTimeout, disconnect;
+
+ var DISCONNECTDELAY = 1000;
- var loaded = false;
function load() {
- if (loaded) return false;
- loaded = true;
-
ui.insertCss(require("text!./error.css"),
options.staticPrefix, plugin);
}
+ function initDisconnectEvents(vfs){
+ var timer;
+
+ vfs.once("connect", function(){
+ vfs.connection.on("reconnectDelay", function(e){
+ clearInterval(timer);
+
+ var delay = e.delay;
+ if (delay > 999) {
+ timer = setInterval(function(){
+ if (vfs.connected)
+ return clearInterval(timer);
+
+ delay -= 1000;
+ showDisconnect({ delay: delay });
+
+ if (delay <= 0)
+ clearInterval(timer);
+ }, 1000);
+ }
+
+ showDisconnect(e);
+ });
+ });
+ vfs.on("connect", function(){
+ hideDisconnect();
+ });
+ vfs.on("disconnect", function(){
+ // setTimeout(function(){
+ // showDisconnect();
+ // }, DISCONNECTDELAY);
+ });
+ vfs.on("connecting", function(){
+ showDisconnect({ connecting: true });
+ });
+ plugin.on("retryConnect", function(){
+ vfs.connection.reconnect(0);
+ });
+ }
+
/***** Methods *****/
+ function getCenterX(){
+ var bartools = document.querySelector(".bartools");
+ if (!bartools) return 0; // For testing
+
+ var b1 = bartools.getBoundingClientRect();
+ var b2 = bartools.nextSibling.getBoundingClientRect();
+
+ return b1.left + b1.width + ((b2.left - b1.left - b1.width)/2);
+ }
+
function show(message, timeout) {
// Error message container
if (!error) {
@@ -63,18 +113,21 @@ define(function(require, exports, module) {
error.innerHTML = "
"
+ messageString + "
";
+ error.style.opacity = 0;
error.style.display = "block";
- error.style.top = (-1 * error.offsetHeight - 10 + topPx) + "px";
+ error.style.top = (offset - (error.offsetHeight - 10 + topPx)) + "px";
+ error.firstChild.style.marginLeft = Math.max(0, (getCenterX() - (error.firstChild.offsetWidth / 2))) + "px";
// Start anim
setTimeout(function() {
- error.className = "errorlabel anim";
- error.style.top = topPx + "px";
+ error.className = "errorlabel anim " + (offset > 0 ? "fade-in" : "");
+ error.style.top = (offset + topPx) + "px";
+ error.style.opacity = 1;
}, 10);
clearTimeout(hideTimeout);
if (!(timeout < 0))
- setTimeout(hide, timeout || 15000);
+ hideTimeout = setTimeout(hide, timeout || 15000);
});
return ++lastCookie;
@@ -89,19 +142,96 @@ define(function(require, exports, module) {
if (!error || error.style.display === "none")
return callback && callback();
- error.className = "errorlabel anim";
- error.style.top = (-1 * error.offsetHeight - 10 + topPx) + "px";
+ error.className = "errorlabel anim " + (offset > 0 ? "fade-in" : "");
+ if (offset > 0)
+ error.style.opacity = 0;
+ else
+ error.style.top = (-1 * error.offsetHeight - 10 + topPx) + "px";
+
setTimeout(function() {
error.style.display = "none";
callback && callback();
}, 220);
}
+ function showDisconnect(options){
+ // Error message container
+ if (!disconnect) {
+ disconnect = document.body.appendChild(document.createElement("div"));
+ disconnect.className = "disconnectlabel";
+ disconnect.addEventListener("mouseup", function(e) {
+ if (e.target.tagName == "U")
+ emit("retryConnect");
+ });
+ }
+
+ var message;
+ if (!options || options.delay < 1000 || options.connecting)
+ message = "Reconnecting...";
+ else if (options.delay)
+ message = "Reconnecting in " + Math.ceil(options.delay/1000)
+ + " seconds."
+ + (options.delay < 2001 ? "" : " Retry Now.");
+ else
+ message = "Reconnecting...";
+
+ disconnect.innerHTML = "" + message + "
";
+ disconnect.firstChild.style.marginLeft
+ = Math.max(0, (getCenterX() - 150)) + "px";
+
+ if (disconnect.style.display == "block")
+ return;
+
+ disconnect.style.display = "block";
+ disconnect.style.top = (-1 * disconnect.offsetHeight - 10 + topPx) + "px";
+
+ // Start anim
+ setTimeout(function() {
+ disconnect.className = "disconnectlabel anim";
+ disconnect.style.top = (topPx) + "px";
+ }, 10);
+
+ offset = 28;
+
+ // document.querySelector(".c9-offline").addEventListener("click", function(){
+ // alert("Offline Notication", "You are currently offline.",
+ // "This indicator notifies you that Cloud9 is unable to reach "
+ // + "the server. This usually happens because you are offline. "
+ // + "Some features will be disabled until the "
+ // + "network connection becomes available again. "
+ // + "This notication could also show when the server is "
+ // + "unreachable due to other reasons. Sometimes a refresh of "
+ // + "the tab will fix an issue. Please e-mail "
+ // + "support@c9.io for further problem resolution.");
+ // }, false);
+ }
+
+ function hideDisconnect(cookie, callback) {
+ if (!disconnect || disconnect.style.display === "none")
+ return callback && callback();
+
+ disconnect.className = "disconnectlabel anim";
+ disconnect.style.top = (-1 * disconnect.offsetHeight - 10 + topPx) + "px";
+ setTimeout(function() {
+ disconnect.style.display = "none";
+ callback && callback();
+ }, 220);
+
+ offset = 0;
+ }
+
/***** Lifecycle *****/
plugin.on("load", function() {
load();
});
+ plugin.on("unload", function() {
+ topPx = 0;
+ lastCookie = 0;
+ offset = 0;
+ error = null;
+ hideTimeout = null;
+ });
/***** Register and define API *****/
@@ -116,6 +246,19 @@ define(function(require, exports, module) {
get top(){ return topPx; },
set top(value){ topPx = value; },
+ get vfs(){ throw new Error("Permission Denied"); },
+ set vfs(v){ initDisconnectEvents(v); },
+
+ /**
+ *
+ */
+ showDisconnect: showDisconnect,
+
+ /**
+ *
+ */
+ hideDisconnect: hideDisconnect,
+
/**
* Displays an error message in the main error reporting UI.
* @param {String} message The message to display.
diff --git a/plugins/c9.ide.layout.classic/layout.js b/plugins/c9.ide.layout.classic/layout.js
index c3124ceb..5d3aee91 100644
--- a/plugins/c9.ide.layout.classic/layout.js
+++ b/plugins/c9.ide.layout.classic/layout.js
@@ -8,11 +8,11 @@ define(function(require, exports, module) {
function main(options, imports, register) {
var c9 = imports.c9;
- var alert = imports["dialog.alert"].show;
var Plugin = imports.Plugin;
- var question = imports["dialog.question"];
var settings = imports.settings;
var commands = imports.commands;
+ var alert = imports["dialog.alert"].show;
+ var question = imports["dialog.question"];
var preload = imports["layout.preload"];
var anims = imports.anims;
var ui = imports.ui;
@@ -126,33 +126,6 @@ define(function(require, exports, module) {
img.src = options.staticPrefix + "/images/" + p;
});
- var hideOffline;
- c9.on("stateChange", function(e) {
- // Online
- if (e.state & c9.NETWORK && e.state & c9.STORAGE) {
- hideOffline && hideOffline();
- }
- // Offline
- else if (!hideOffline || hideOffline.hasClosed()) {
- hideOffline = notify("No internet "
- + "connection detected. Cloud9 will automatically try to "
- + "reconnect when it detects an internet connection."
- + "
", true, 1000);
-
- document.querySelector(".c9-offline").addEventListener("click", function(){
- alert("Offline Notication", "You are currently offline.",
- "This indicator notifies you that Cloud9 is unable to reach "
- + "the server. This usually happens because you are offline. "
- + "Some features will be disabled until the "
- + "network connection becomes available again. "
- + "This notication could also show when the server is "
- + "unreachable due to other reasons. Sometimes a refresh of "
- + "the tab will fix an issue. Please e-mail "
- + "support@c9.io for further problem resolution.");
- }, false);
- }
- });
-
window.addEventListener("resize", resize, false);
window.addEventListener("focus", resize, false);
@@ -542,6 +515,21 @@ define(function(require, exports, module) {
window.removeEventListener("resize", resize);
if (removeTheme) removeTheme();
+
+ logobar = null;
+ removeTheme = null;
+ theme = null;
+ c9console = null;
+ menus = null;
+ tabManager = null;
+ panels = null;
+ userLayout = null;
+ ignoreTheme = null;
+ notify = null;
+ hideFlagUpdate = null;
+ activeFindArea = null;
+ defaultFindArea = null;
+ activating = null;
});
/***** Register and define API *****/
diff --git a/plugins/c9.ide.layout.classic/themes/default-dark-gray.less b/plugins/c9.ide.layout.classic/themes/default-dark-gray.less
index 6c78b067..f78fd8a0 100644
--- a/plugins/c9.ide.layout.classic/themes/default-dark-gray.less
+++ b/plugins/c9.ide.layout.classic/themes/default-dark-gray.less
@@ -632,6 +632,12 @@
@error-close-hover-position: -14px -14px;
@error-close-active-position: -28px -14px;
+// Disconnect Dialog
+@disconnect-background: #D8B112;
+@disconnect-color: @error-color;
+@disconnect-padding: @error-padding;
+@disconnect-box-shadow: @error-box-shadow;
+
// Offline Dialog
@offline-gradient: linear-gradient(top, rgb(60, 112, 153) 0%, rgb(61, 97, 126) 100%);
@offline-border-bottom: 1px solid rgba(0, 0, 0, 0.61);
diff --git a/plugins/c9.ide.layout.classic/themes/default-dark.less b/plugins/c9.ide.layout.classic/themes/default-dark.less
index fd62d0f3..26707588 100644
--- a/plugins/c9.ide.layout.classic/themes/default-dark.less
+++ b/plugins/c9.ide.layout.classic/themes/default-dark.less
@@ -632,6 +632,12 @@
@error-close-hover-position: -14px -14px;
@error-close-active-position: -28px -14px;
+// Disconnect Dialog
+@disconnect-background: #D8B112;
+@disconnect-color: @error-color;
+@disconnect-padding: @error-padding;
+@disconnect-box-shadow: @error-box-shadow;
+
// Offline Dialog
@offline-gradient: linear-gradient(top, rgb(60, 112, 153) 0%, rgb(61, 97, 126) 100%);
@offline-border-bottom: 1px solid rgba(0, 0, 0, 0.61);
diff --git a/plugins/c9.ide.layout.classic/themes/default-flat-light.less b/plugins/c9.ide.layout.classic/themes/default-flat-light.less
index b23ca74b..6425061b 100644
--- a/plugins/c9.ide.layout.classic/themes/default-flat-light.less
+++ b/plugins/c9.ide.layout.classic/themes/default-flat-light.less
@@ -632,6 +632,12 @@
@error-close-hover-position: -14px -14px;
@error-close-active-position: -28px -14px;
+// Disconnect Dialog
+@disconnect-background: #D8B112;
+@disconnect-color: @error-color;
+@disconnect-padding: @error-padding;
+@disconnect-box-shadow: @error-box-shadow;
+
// Offline Dialog
@offline-gradient: linear-gradient(top, #3d9ac4 0%, #3d9ac4 100%);
@offline-border-bottom: 0;
diff --git a/plugins/c9.ide.layout.classic/themes/default-light-gray.less b/plugins/c9.ide.layout.classic/themes/default-light-gray.less
index 39472337..ebf4895d 100644
--- a/plugins/c9.ide.layout.classic/themes/default-light-gray.less
+++ b/plugins/c9.ide.layout.classic/themes/default-light-gray.less
@@ -632,6 +632,12 @@
@error-close-hover-position: -14px -14px;
@error-close-active-position: -28px -14px;
+// Disconnect Dialog
+@disconnect-background: #D8B112;
+@disconnect-color: @error-color;
+@disconnect-padding: @error-padding;
+@disconnect-box-shadow: @error-box-shadow;
+
// Offline Dialog
@offline-gradient: linear-gradient(top, rgb(60, 112, 153) 0%, rgb(61, 97, 126) 100%);
@offline-border-bottom: 1px solid rgba(0, 0, 0, 0.61);
diff --git a/plugins/c9.ide.layout.classic/themes/default-light.less b/plugins/c9.ide.layout.classic/themes/default-light.less
index 48928aee..982b7177 100644
--- a/plugins/c9.ide.layout.classic/themes/default-light.less
+++ b/plugins/c9.ide.layout.classic/themes/default-light.less
@@ -632,6 +632,12 @@
@error-close-hover-position: -14px -14px;
@error-close-active-position: -28px -14px;
+// Disconnect Dialog
+@disconnect-background: #D8B112;
+@disconnect-color: @error-color;
+@disconnect-padding: @error-padding;
+@disconnect-box-shadow: @error-box-shadow;
+
// Offline Dialog
@offline-gradient: linear-gradient(top, rgb(60, 112, 153) 0%, rgb(61, 97, 126) 100%);
@offline-border-bottom: 1px solid rgba(0, 0, 0, 0.61);
diff --git a/plugins/c9.vfs.client/vfs_client.js b/plugins/c9.vfs.client/vfs_client.js
index 22a5916f..266974e7 100644
--- a/plugins/c9.vfs.client/vfs_client.js
+++ b/plugins/c9.vfs.client/vfs_client.js
@@ -30,8 +30,9 @@ define(function(require, exports, module) {
var Plugin = imports.Plugin;
var auth = imports.auth;
var vfsEndpoint = imports["vfs.endpoint"];
- var showError = imports["dialog.error"].show;
- var hideError = imports["dialog.error"].hide;
+ var errorDialog = imports["dialog.error"];
+ var showError = errorDialog.show;
+ var hideError = errorDialog.hide;
var showAlert = imports["dialog.alert"].show;
var eio = require("engine.io");
@@ -49,6 +50,9 @@ define(function(require, exports, module) {
var plugin = new Plugin("Ajax.org", main.consumes);
var emit = plugin.getEmitter();
+ // Give reference to vfs to plugin
+ errorDialog.vfs = plugin;
+
var buffer = [];
var installChecked = false;
var withInstall = options.withInstall;
@@ -330,6 +334,22 @@ define(function(require, exports, module) {
});
plugin.on("unload", function(){
loaded = false;
+
+ id = null;
+ buffer = [];
+ installChecked = false;
+ region = null;
+ vfsBaseUrl = null;
+ homeUrl = null;
+ projectUrl = null;
+ pingUrl = null;
+ serviceUrl = null;
+ eioOptions = null;
+ consumer = null;
+ vfs = null;
+ showErrorTimer = null;
+ showErrorTimerMessage = null;
+ lastError = null;
});
/***** Register and define API *****/