[feature] Create option to automatically reconnect after a few seconds
On some erros that display a modal with "Force reconnect" button, allow Etherpad to automatically reload pad after a few seconds. Amount of seconds is defined on settings.json. Still need to create tests for this feature, and implement i18n.pull/3161/head
parent
ed029b599e
commit
009cd31243
|
@ -121,6 +121,10 @@
|
|||
/* Privacy: disable IP logging */
|
||||
"disableIPlogging" : false,
|
||||
|
||||
/* Time (in seconds) to automatically reconnect pad when a "Force reconnect"
|
||||
message is shown to user. Set to 0 to disable automatic reconnection */
|
||||
"automaticReconnectionTimeout" : 0,
|
||||
|
||||
/* Users for basic authentication. is_admin = true gives access to /admin.
|
||||
If you do not uncomment this, /admin will not be available! */
|
||||
/*
|
||||
|
|
|
@ -1176,6 +1176,7 @@ function handleClientReady(client, message)
|
|||
"accountPrivs": {
|
||||
"maxRevisions": 100
|
||||
},
|
||||
"automaticReconnectionTimeout": settings.automaticReconnectionTimeout,
|
||||
"initialRevisionList": [],
|
||||
"initialOptions": {
|
||||
"guestPolicy": "deny"
|
||||
|
|
|
@ -177,6 +177,11 @@ exports.loglevel = "INFO";
|
|||
*/
|
||||
exports.disableIPlogging = false;
|
||||
|
||||
/**
|
||||
* Number of seconds to automatically reconnect pad
|
||||
*/
|
||||
exports.automaticReconnectionTimeout = 0;
|
||||
|
||||
/**
|
||||
* Disable Load Testing
|
||||
*/
|
||||
|
|
|
@ -517,6 +517,23 @@ table#otheruserstable {
|
|||
display: block;
|
||||
}
|
||||
|
||||
/* styles for the automatic reconnection timer: */
|
||||
#connectivity .visible.with_reconnect_timer button,
|
||||
#connectivity .visible.with_reconnect_timer .reconnecttimer * {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
#connectivity .with_reconnect_timer .hidden,
|
||||
#connectivity .with_reconnect_timer #defaulttext.hidden,
|
||||
#connectivity .with_reconnect_timer button.hidden {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#connectivity .with_reconnect_timer #cancelreconnect {
|
||||
margin-left: 10px;
|
||||
}
|
||||
/* end of styles for the automatic reconnection timer */
|
||||
|
||||
#reconnect_form button {
|
||||
font-size: 12pt;
|
||||
padding: 5px;
|
||||
|
|
|
@ -0,0 +1,135 @@
|
|||
|
||||
exports.showCountDownTimerToReconnectOnModal = function($modal) {
|
||||
if (clientVars.automaticReconnectionTimeout && $modal.is('.with_reconnect_timer')) {
|
||||
createCountDownElementsIfNecessary($modal);
|
||||
|
||||
var timer = createTimerForModal($modal);
|
||||
|
||||
$modal.find('#cancelreconnect').one('click', function() {
|
||||
timer.cancel();
|
||||
disableAutomaticReconnection($modal);
|
||||
});
|
||||
|
||||
enableAutomaticReconnection($modal);
|
||||
}
|
||||
}
|
||||
|
||||
var createCountDownElementsIfNecessary = function($modal) {
|
||||
var elementsDoNotExist = $modal.find('#cancelreconnect').length === 0;
|
||||
if (elementsDoNotExist) {
|
||||
var $defaultMessage = $modal.find('#defaulttext');
|
||||
var $reconnectButton = $modal.find('#forcereconnect');
|
||||
|
||||
// create extra DOM elements, if they don't exist
|
||||
var $reconnectTimerMessage = $('<p class="reconnecttimer"> \
|
||||
<span data-l10n-id="pad.modals.reconnecttimer">This window will automatically reconnect in </span> \
|
||||
<span class="timetoexpire"></span> \
|
||||
</p>');
|
||||
var $cancelReconnect = $('<button id="cancelreconnect" data-l10n-id="pad.modals.cancel">Cancel</button>');
|
||||
|
||||
$reconnectTimerMessage.insertAfter($defaultMessage);
|
||||
$cancelReconnect.insertAfter($reconnectButton);
|
||||
}
|
||||
}
|
||||
|
||||
var createTimerForModal = function($modal) {
|
||||
var timer = new CountDownTimer(clientVars.automaticReconnectionTimeout);
|
||||
|
||||
timer.onTick(function(minutes, seconds) {
|
||||
updateCountDownTimerMessage($modal, minutes, seconds);
|
||||
}).onExpire(function() {
|
||||
reconnect($modal);
|
||||
}).start();
|
||||
|
||||
return timer;
|
||||
}
|
||||
|
||||
var disableAutomaticReconnection = function($modal) {
|
||||
toggleAutomaticReconnectionOption($modal, true);
|
||||
}
|
||||
var enableAutomaticReconnection = function($modal) {
|
||||
toggleAutomaticReconnectionOption($modal, false);
|
||||
}
|
||||
var toggleAutomaticReconnectionOption = function($modal, disableAutomaticReconnect) {
|
||||
$modal.find('#cancelreconnect, .reconnecttimer').toggleClass('hidden', disableAutomaticReconnect);
|
||||
$modal.find('#defaulttext').toggleClass('hidden', !disableAutomaticReconnect);
|
||||
}
|
||||
|
||||
var reconnect = function($modal) {
|
||||
$modal.find('#forcereconnect').click();
|
||||
}
|
||||
|
||||
var updateCountDownTimerMessage = function($modal, minutes, seconds) {
|
||||
minutes = minutes < 10 ? '0' + minutes : minutes;
|
||||
seconds = seconds < 10 ? '0' + seconds : seconds;
|
||||
|
||||
$modal.find('.timetoexpire').text(minutes + ':' + seconds);
|
||||
}
|
||||
|
||||
// Timer based on http://stackoverflow.com/a/20618517.
|
||||
// duration: how many **seconds** until the timer ends
|
||||
// granularity (optional): how many **milliseconds** between each 'tick' of timer. Default: 1000ms (1s)
|
||||
var CountDownTimer = function(duration, granularity) {
|
||||
this.duration = duration;
|
||||
this.granularity = granularity || 1000;
|
||||
this.running = false;
|
||||
|
||||
this.onTickCallbacks = [];
|
||||
this.onExpireCallbacks = [];
|
||||
}
|
||||
|
||||
CountDownTimer.prototype.start = function() {
|
||||
if (this.running) {
|
||||
return;
|
||||
}
|
||||
this.running = true;
|
||||
var start = Date.now(),
|
||||
that = this,
|
||||
diff, obj;
|
||||
|
||||
(function timer() {
|
||||
diff = that.duration - Math.floor((Date.now() - start) / 1000);
|
||||
|
||||
if (diff > 0) {
|
||||
that.timeoutId = setTimeout(timer, that.granularity);
|
||||
|
||||
obj = CountDownTimer.parse(diff);
|
||||
that.onTickCallbacks.forEach(function(callback) {
|
||||
callback.call(this, obj.minutes, obj.seconds);
|
||||
}, that);
|
||||
} else {
|
||||
that.running = false;
|
||||
|
||||
that.onExpireCallbacks.forEach(function(callback) {
|
||||
callback.call(this);
|
||||
}, that);
|
||||
}
|
||||
}());
|
||||
};
|
||||
|
||||
CountDownTimer.prototype.onTick = function(callback) {
|
||||
if (typeof callback === 'function') {
|
||||
this.onTickCallbacks.push(callback);
|
||||
}
|
||||
return this;
|
||||
};
|
||||
|
||||
CountDownTimer.prototype.onExpire = function(callback) {
|
||||
if (typeof callback === 'function') {
|
||||
this.onExpireCallbacks.push(callback);
|
||||
}
|
||||
return this;
|
||||
};
|
||||
|
||||
CountDownTimer.prototype.cancel = function() {
|
||||
this.running = false;
|
||||
clearTimeout(this.timeoutId);
|
||||
return this;
|
||||
};
|
||||
|
||||
CountDownTimer.parse = function(seconds) {
|
||||
return {
|
||||
'minutes': (seconds / 60) | 0,
|
||||
'seconds': (seconds % 60) | 0
|
||||
};
|
||||
};
|
|
@ -21,6 +21,7 @@
|
|||
*/
|
||||
|
||||
var padeditbar = require('./pad_editbar').padeditbar;
|
||||
var automaticReconnect = require('./pad_automatic_reconnect');
|
||||
|
||||
var padmodals = (function()
|
||||
{
|
||||
|
@ -35,6 +36,9 @@ var padmodals = (function()
|
|||
padeditbar.toggleDropDown("none", function() {
|
||||
$("#connectivity .visible").removeClass('visible');
|
||||
$("#connectivity ."+messageId).addClass('visible');
|
||||
|
||||
automaticReconnect.showCountDownTimerToReconnectOnModal($('#connectivity .' + messageId));
|
||||
|
||||
padeditbar.toggleDropDown("connectivity");
|
||||
});
|
||||
},
|
||||
|
|
|
@ -249,12 +249,12 @@
|
|||
<div class="userdup">
|
||||
<h1 data-l10n-id="pad.modals.userdup"></h1>
|
||||
<h2 data-l10n-id="pad.modals.userdup.explanation"></h2>
|
||||
<p data-l10n-id="pad.modals.userdup.advice"></p>
|
||||
<p id="defaulttext" data-l10n-id="pad.modals.userdup.advice"></p>
|
||||
<button id="forcereconnect" data-l10n-id="pad.modals.forcereconnect"></button>
|
||||
</div>
|
||||
<div class="unauth">
|
||||
<h1 data-l10n-id="pad.modals.unauth"></h1>
|
||||
<p data-l10n-id="pad.modals.unauth.explanation"></p>
|
||||
<p id="defaulttext" data-l10n-id="pad.modals.unauth.explanation"></p>
|
||||
<button id="forcereconnect" data-l10n-id="pad.modals.forcereconnect"></button>
|
||||
</div>
|
||||
<div class="looping">
|
||||
|
@ -267,16 +267,16 @@
|
|||
<h2 data-l10n-id="pad.modals.initsocketfail.explanation"></h2>
|
||||
<p data-l10n-id="pad.modals.initsocketfail.cause"></p>
|
||||
</div>
|
||||
<div class="slowcommit">
|
||||
<div class="slowcommit with_reconnect_timer">
|
||||
<h1 data-l10n-id="pad.modals.disconnected"></h1>
|
||||
<h2 data-l10n-id="pad.modals.slowcommit.explanation"></h2>
|
||||
<p data-l10n-id="pad.modals.slowcommit.cause"></p>
|
||||
<p id="defaulttext" data-l10n-id="pad.modals.slowcommit.cause"></p>
|
||||
<button id="forcereconnect" data-l10n-id="pad.modals.forcereconnect"></button>
|
||||
</div>
|
||||
<div class="badChangeset">
|
||||
<div class="badChangeset with_reconnect_timer">
|
||||
<h1 data-l10n-id="pad.modals.disconnected"></h1>
|
||||
<h2 data-l10n-id="pad.modals.badChangeset.explanation"></h2>
|
||||
<p data-l10n-id="pad.modals.badChangeset.cause"></p>
|
||||
<p id="defaulttext" data-l10n-id="pad.modals.badChangeset.cause"></p>
|
||||
<button id="forcereconnect" data-l10n-id="pad.modals.forcereconnect"></button>
|
||||
</div>
|
||||
<div class="corruptPad">
|
||||
|
@ -288,11 +288,11 @@
|
|||
<h1 data-l10n-id="pad.modals.deleted"></h1>
|
||||
<p data-l10n-id="pad.modals.deleted.explanation"></p>
|
||||
</div>
|
||||
<div class="disconnected">
|
||||
<div class="disconnected with_reconnect_timer">
|
||||
<% e.begin_block("disconnected"); %>
|
||||
<h1 data-l10n-id="pad.modals.disconnected"></h1>
|
||||
<h2 data-l10n-id="pad.modals.disconnected.explanation"></h2>
|
||||
<p data-l10n-id="pad.modals.disconnected.cause"></p>
|
||||
<p id="defaulttext" data-l10n-id="pad.modals.disconnected.cause"></p>
|
||||
<button id="forcereconnect" data-l10n-id="pad.modals.forcereconnect"></button>
|
||||
<% e.end_block(); %>
|
||||
</div>
|
||||
|
|
Loading…
Reference in New Issue