cryptpad/www/common/sframe-chainpad-netflux-inner.js

184 lines
6.9 KiB
JavaScript
Raw Normal View History

2017-08-07 14:27:57 +00:00
/*
* Copyright 2014 XWiki SAS
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
define([
'/common/common-util.js',
'/customize/application_config.js',
2017-08-10 12:49:21 +00:00
'/bower_components/chainpad/chainpad.dist.js'
], function (Util, AppConfig, ChainPad) {
2017-08-07 14:27:57 +00:00
var module = { exports: {} };
var badStateTimeout = typeof(AppConfig.badStateTimeout) === 'number' ?
AppConfig.badStateTimeout : 30000;
2017-08-07 14:27:57 +00:00
var verbose = function (x) { console.log(x); };
verbose = function () {}; // comment out to enable verbose logging
2017-08-09 12:45:39 +00:00
module.exports.start = function (config) {
var onConnectionChange = config.onConnectionChange || function () { };
var onRemote = config.onRemote || function () { };
var onInit = config.onInit || function () { };
var onLocal = config.onLocal || function () { };
var setMyID = config.setMyID || function () { };
var onReady = config.onReady || function () { };
2018-02-13 17:20:13 +00:00
var onError = config.onError || function () { };
2017-08-09 12:45:39 +00:00
var userName = config.userName;
var initialState = config.initialState;
if (config.transformFunction) { throw new Error("transformFunction is nolonger allowed"); }
2017-10-23 11:22:33 +00:00
var patchTransformer = config.patchTransformer;
2017-08-09 12:45:39 +00:00
var validateContent = config.validateContent;
var avgSyncMilliseconds = config.avgSyncMilliseconds;
2018-03-21 17:27:20 +00:00
var logLevel = typeof(config.logLevel) !== 'undefined'? config.logLevel : 1;
2017-08-09 12:45:39 +00:00
var readOnly = config.readOnly || false;
2017-08-09 15:37:55 +00:00
var sframeChan = config.sframeChan;
var metadataMgr = config.metadataMgr;
var updateLoadingProgress = config.updateLoadingProgress;
2017-08-09 12:45:39 +00:00
config = undefined;
2020-01-30 17:39:59 +00:00
var evPatchSent = Util.mkEvent();
var chainpad;
2020-01-30 17:39:59 +00:00
var makeChainPad = function () {
var _chainpad = ChainPad.create({
userName: userName,
initialState: initialState,
patchTransformer: patchTransformer,
validateContent: validateContent,
avgSyncMilliseconds: avgSyncMilliseconds,
logLevel: logLevel
2020-01-30 17:39:59 +00:00
});
_chainpad.onMessage(function(message, cb) {
// -1 ==> no timeout, we may receive the callback only when we reconnect
sframeChan.query('Q_RT_MESSAGE', message, function (_err, obj) {
var err = _err || (obj && obj.error);
if (!err) { evPatchSent.fire(); }
cb(err);
}, { timeout: -1 });
});
_chainpad.onPatch(function () {
onRemote({ realtime: chainpad });
});
return _chainpad;
};
chainpad = makeChainPad();
2017-08-09 12:45:39 +00:00
var myID;
var isReady = false;
var isHistory = 1;
var evConnected = Util.mkEvent(true);
var evInfiniteSpinner = Util.mkEvent(true);
window.setInterval(function () {
if (!chainpad || !myID) { return; }
var l;
try {
l = chainpad.getLag();
} catch (e) {
throw new Error("ChainPad.getLag() does not exist, please `bower update`");
}
if (l.lag < badStateTimeout) { return; }
evInfiniteSpinner.fire();
}, 2000);
2017-08-09 12:45:39 +00:00
sframeChan.on('EV_RT_DISCONNECT', function (isPermanent) {
2017-08-09 12:45:39 +00:00
isReady = false;
chainpad.abort();
// Permanent flag is here to choose if we wnat to display
// "reconnecting" or "disconnected" in the toolbar state
onConnectionChange({ state: false, permanent: isPermanent });
2017-08-09 12:45:39 +00:00
});
2018-02-13 17:20:13 +00:00
sframeChan.on('EV_RT_ERROR', function (err) {
isReady = false;
chainpad.abort();
2020-03-26 16:25:36 +00:00
if (err.type === 'EUNKNOWN') {
// Recoverable error: make a new chainpad
chainpad = makeChainPad();
return;
}
2018-02-13 17:20:13 +00:00
onError(err);
});
2017-08-09 15:37:55 +00:00
sframeChan.on('EV_RT_CONNECT', function (content) {
2017-08-10 16:31:44 +00:00
//content.members.forEach(userList.onJoin);
if (isReady && myID === content.myID) {
// We are connected and we are "reconnecting" ==> we probably had to rejoin
// the channel because of a server error (enoent), don't update the toolbar
return;
}
2017-08-09 12:45:39 +00:00
isReady = false;
if (myID) {
2017-08-09 12:45:39 +00:00
// it's a reconnect
myID = content.myID;
//chainpad.start();
2017-08-09 12:45:39 +00:00
onConnectionChange({ state: true, myId: myID });
return;
}
myID = content.myID;
2017-08-09 12:45:39 +00:00
onInit({
2017-08-09 15:37:55 +00:00
myID: myID,
2017-08-09 12:45:39 +00:00
realtime: chainpad,
readOnly: readOnly
2017-08-07 14:27:57 +00:00
});
evConnected.fire();
2017-08-09 12:45:39 +00:00
});
2017-08-09 15:37:55 +00:00
sframeChan.on('Q_RT_MESSAGE', function (content, cb) {
2017-08-09 12:45:39 +00:00
if (isReady) {
onLocal(true); // should be onBeforeMessage
2017-08-07 14:27:57 +00:00
}
2017-08-09 12:45:39 +00:00
chainpad.message(content);
if (isHistory && updateLoadingProgress) {
updateLoadingProgress({
state: 2,
progress: isHistory
}, false);
isHistory++;
}
2017-08-09 12:45:39 +00:00
cb('OK');
});
2017-08-09 15:37:55 +00:00
sframeChan.on('EV_RT_READY', function () {
2017-08-09 12:45:39 +00:00
if (isReady) { return; }
isReady = true;
isHistory = false;
2017-08-09 12:45:39 +00:00
chainpad.start();
setMyID({ myID: myID });
onReady({ realtime: chainpad });
});
var whenRealtimeSyncs = function (cb) {
evConnected.reg(function () {
if (chainpad.getAuthDoc() === chainpad.getUserDoc()) {
return void cb();
} else {
chainpad.onSettle(cb);
}
});
};
var cpNfInner = {
2017-08-10 12:49:21 +00:00
getMyID: function () { return myID; },
metadataMgr: metadataMgr,
whenRealtimeSyncs: whenRealtimeSyncs,
onInfiniteSpinner: evInfiniteSpinner.reg,
2020-01-30 17:39:59 +00:00
onPatchSent: evPatchSent.reg,
offPatchSent: evPatchSent.unreg,
};
cpNfInner.__defineGetter__("chainpad", function () {
return chainpad;
2017-08-10 12:49:21 +00:00
});
return Object.freeze(cpNfInner);
2017-08-07 14:27:57 +00:00
};
2017-08-10 12:49:21 +00:00
return Object.freeze(module.exports);
2017-10-09 08:32:24 +00:00
});