Use lastKnownHash to handle checkpoints in the realtime channel
This commit is contained in:
parent
8dbeee1af9
commit
a66d8c1384
@ -49,6 +49,8 @@ define([
|
|||||||
$: $
|
$: $
|
||||||
};
|
};
|
||||||
|
|
||||||
|
var CHECKPOINT_INTERVAL = 50;
|
||||||
|
|
||||||
var stringify = function (obj) {
|
var stringify = function (obj) {
|
||||||
return JSONSortify(obj);
|
return JSONSortify(obj);
|
||||||
};
|
};
|
||||||
@ -58,11 +60,66 @@ define([
|
|||||||
var andThen = function (common) {
|
var andThen = function (common) {
|
||||||
var sframeChan = common.getSframeChannel();
|
var sframeChan = common.getSframeChannel();
|
||||||
var metadataMgr = common.getMetadataMgr();
|
var metadataMgr = common.getMetadataMgr();
|
||||||
|
var privateData = metadataMgr.getPrivateData();
|
||||||
var readOnly = false;
|
var readOnly = false;
|
||||||
var locked = false;
|
//var locked = false;
|
||||||
var config = {};
|
var config = {};
|
||||||
var hashes = [];
|
var content = {
|
||||||
var channel;
|
hashes: {},
|
||||||
|
ids: {}
|
||||||
|
};
|
||||||
|
var myOOId;
|
||||||
|
|
||||||
|
var deleteOffline = function () {
|
||||||
|
var ids = content.ids;
|
||||||
|
var users = Object.keys(metadataMgr.getMetadata().users);
|
||||||
|
Object.keys(ids).forEach(function (id) {
|
||||||
|
var nId = id.slice(0,32);
|
||||||
|
if (users.indexOf(nId) === -1) {
|
||||||
|
delete ids[id];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
APP.onLocal();
|
||||||
|
};
|
||||||
|
|
||||||
|
var isUserOnline = function (ooid) {
|
||||||
|
// Remove ids for users that have left the channel
|
||||||
|
deleteOffline();
|
||||||
|
var ids = content.ids;
|
||||||
|
// Check if the provided id is in the ID list
|
||||||
|
return Object.keys(ids).some(function (id) {
|
||||||
|
return ooid === ids[id];
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
var setMyId = function (netfluxId) {
|
||||||
|
// Remove ids for users that have left the channel
|
||||||
|
deleteOffline();
|
||||||
|
var ids = content.ids;
|
||||||
|
if (!myOOId) {
|
||||||
|
myOOId = Util.createRandomInteger();
|
||||||
|
while (Object.keys(ids).some(function (id) {
|
||||||
|
return ids[id] === myOOId;
|
||||||
|
})) {
|
||||||
|
myOOId = Util.createRandomInteger();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var myId = (netfluxId || metadataMgr.getNetfluxId()) + '-' + privateData.clientId;
|
||||||
|
ids[myId] = myOOId;
|
||||||
|
APP.onLocal();
|
||||||
|
};
|
||||||
|
|
||||||
|
// Another tab from our worker has left: remove its id from the list
|
||||||
|
var removeClient = function (obj) {
|
||||||
|
var tabId = metadataMgr.getNetfluxId() + '-' + obj.id;
|
||||||
|
console.log(tabId);
|
||||||
|
if (content.ids[tabId]) {
|
||||||
|
console.log('delete');
|
||||||
|
delete content.ids[tabId];
|
||||||
|
APP.onLocal();
|
||||||
|
console.log(content.ids);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
var getFileType = function () {
|
var getFileType = function () {
|
||||||
var type = common.getMetadataMgr().getPrivateData().ooType;
|
var type = common.getMetadataMgr().getPrivateData().ooType;
|
||||||
@ -91,12 +148,12 @@ define([
|
|||||||
var now = function () { return +new Date(); };
|
var now = function () { return +new Date(); };
|
||||||
|
|
||||||
var getLastCp = function () {
|
var getLastCp = function () {
|
||||||
if (!hashes || !hashes.length) { return; }
|
var hashes = content.hashes;
|
||||||
var last = hashes.slice().pop();
|
if (!hashes || !Object.keys(hashes).length) { return {}; }
|
||||||
var parsed = Hash.parsePadUrl(last);
|
var lastIndex = Math.max.apply(null, Object.keys(hashes).map(Number));
|
||||||
var secret = Hash.getSecrets('file', parsed.hash);
|
// TODO check if hashes[lastIndex] is undefined?
|
||||||
if (!secret || !secret.channel) { return; }
|
var last = JSON.parse(JSON.stringify(hashes[lastIndex]));
|
||||||
return 'cp|' + secret.channel.slice(0,8);
|
return last;
|
||||||
};
|
};
|
||||||
|
|
||||||
var rtChannel = {
|
var rtChannel = {
|
||||||
@ -119,32 +176,112 @@ define([
|
|||||||
var ooChannel = {
|
var ooChannel = {
|
||||||
ready: false,
|
ready: false,
|
||||||
queue: [],
|
queue: [],
|
||||||
send: function () {}
|
send: function () {},
|
||||||
|
cpIndex: 0
|
||||||
|
};
|
||||||
|
|
||||||
|
var getContent = APP.getContent = function () {
|
||||||
|
try {
|
||||||
|
return window.frames[0].editor.asc_nativeGetFile();
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var fmConfig = {
|
||||||
|
noHandlers: true,
|
||||||
|
noStore: true,
|
||||||
|
body: $('body'),
|
||||||
|
onUploaded: function (ev, data) {
|
||||||
|
if (!data || !data.url) { return; }
|
||||||
|
sframeChan.query('Q_OO_SAVE', data, function (err) {
|
||||||
|
if (err) {
|
||||||
|
console.error(err);
|
||||||
|
return void UI.alert(Messages.oo_saveError);
|
||||||
|
}
|
||||||
|
var i = Math.floor(ev.index / CHECKPOINT_INTERVAL);
|
||||||
|
// XXX check if content.hashes[i] already exists?
|
||||||
|
content.hashes[i] = {
|
||||||
|
file: data.url,
|
||||||
|
hash: ev.hash,
|
||||||
|
index: ev.index
|
||||||
|
};
|
||||||
|
content.saveLock = undefined;
|
||||||
|
APP.onLocal();
|
||||||
|
sframeChan.query('Q_OO_COMMAND', {
|
||||||
|
cmd: 'UPDATE_HASH',
|
||||||
|
data: ev.hash
|
||||||
|
}, function (err, obj) {
|
||||||
|
if (err || (obj && obj.error)) { console.error(err || obj.error); }
|
||||||
|
});
|
||||||
|
UI.log(Messages.saved);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
APP.FM = common.createFileManager(fmConfig);
|
||||||
|
|
||||||
|
var saveToServer = function () {
|
||||||
|
var text = getContent();
|
||||||
|
var blob = new Blob([text], {type: 'plain/text'});
|
||||||
|
var file = getFileType();
|
||||||
|
blob.name = (metadataMgr.getMetadataLazy().title || file.doc) + '.' + file.type;
|
||||||
|
var data = {
|
||||||
|
hash: ooChannel.lastHash,
|
||||||
|
index: ooChannel.cpIndex
|
||||||
|
};
|
||||||
|
APP.FM.handleFile(blob, data);
|
||||||
|
};
|
||||||
|
var makeCheckpoint = function (force) {
|
||||||
|
var locked = content.saveLock;
|
||||||
|
if (!locked || !isUserOnline(locked) || force) {
|
||||||
|
content.saveLock = myOOId;
|
||||||
|
APP.onLocal();
|
||||||
|
APP.realtime.onSettle(function () {
|
||||||
|
saveToServer();
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// The save is locked by someone else. If no new checkpoint is created
|
||||||
|
// in the next 20 to 40 secondes and the lock is kept by the same user,
|
||||||
|
// force the lock and make a checkpoint.
|
||||||
|
var saved = stringify(content.hashes);
|
||||||
|
var to = 20000 + (Math.random() * 20000)
|
||||||
|
setTimeout(function () {
|
||||||
|
if (stringify(content.hashes) === saved && locked === content.saveLock) {
|
||||||
|
makeCheckpoint(force);
|
||||||
|
}
|
||||||
|
}, to);
|
||||||
};
|
};
|
||||||
|
|
||||||
var openRtChannel = function (cb) {
|
var openRtChannel = function (cb) {
|
||||||
if (rtChannel.ready) { return; }
|
if (rtChannel.ready) { return void cb(); }
|
||||||
var chan = channel || Hash.createChannelId();
|
var chan = content.channel || Hash.createChannelId();
|
||||||
if (!channel) {
|
if (!content.channel) {
|
||||||
channel = chan;
|
content.channel = chan;
|
||||||
APP.onLocal();
|
APP.onLocal();
|
||||||
}
|
}
|
||||||
sframeChan.query('Q_OO_OPENCHANNEL', {
|
sframeChan.query('Q_OO_OPENCHANNEL', {
|
||||||
channel: channel,
|
channel: content.channel,
|
||||||
lastCp: getLastCp()
|
lastCpHash: getLastCp().hash
|
||||||
}, function (err, obj) {
|
}, function (err, obj) {
|
||||||
if (err || (obj && obj.error)) { console.error(err || (obj && obj.error)); }
|
if (err || (obj && obj.error)) { console.error(err || (obj && obj.error)); }
|
||||||
});
|
});
|
||||||
sframeChan.on('EV_OO_EVENT', function (data) {
|
sframeChan.on('EV_OO_EVENT', function (obj) {
|
||||||
switch (data.ev) {
|
switch (obj.ev) {
|
||||||
case 'READY':
|
case 'READY':
|
||||||
rtChannel.ready = true;
|
rtChannel.ready = true;
|
||||||
break;
|
break;
|
||||||
|
case 'LEAVE':
|
||||||
|
removeClient(obj.data);
|
||||||
|
break;
|
||||||
case 'MESSAGE':
|
case 'MESSAGE':
|
||||||
if (ooChannel.ready) {
|
if (ooChannel.ready) {
|
||||||
ooChannel.send(data.data);
|
ooChannel.send(obj.data.msg);
|
||||||
|
ooChannel.lastHash = obj.data.hash;
|
||||||
|
ooChannel.cpIndex++;
|
||||||
} else {
|
} else {
|
||||||
ooChannel.queue.push(data.data);
|
ooChannel.queue.push(obj.data);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -168,7 +305,7 @@ define([
|
|||||||
};
|
};
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
var mkChannel = function () {
|
var makeChannel = function () {
|
||||||
var msgEv = Util.mkEvent();
|
var msgEv = Util.mkEvent();
|
||||||
var iframe = $('#cp-app-oo-container > iframe')[0].contentWindow;
|
var iframe = $('#cp-app-oo-container > iframe')[0].contentWindow;
|
||||||
window.addEventListener('message', function (msg) {
|
window.addEventListener('message', function (msg) {
|
||||||
@ -213,8 +350,10 @@ define([
|
|||||||
});
|
});
|
||||||
setTimeout(function () {
|
setTimeout(function () {
|
||||||
if (ooChannel.queue) {
|
if (ooChannel.queue) {
|
||||||
ooChannel.queue.forEach(function (msg) {
|
ooChannel.queue.forEach(function (data) {
|
||||||
send(msg);
|
send(data.msg);
|
||||||
|
ooChannel.lastHash = data.hash;
|
||||||
|
ooChannel.cpIndex++;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}, 2000);
|
}, 2000);
|
||||||
@ -253,7 +392,12 @@ define([
|
|||||||
changesIndex: 2,
|
changesIndex: 2,
|
||||||
locks: [], // XXX take from userdoc?
|
locks: [], // XXX take from userdoc?
|
||||||
excelAdditionalInfo: null
|
excelAdditionalInfo: null
|
||||||
}, null, function () {
|
}, null, function (err, hash) {
|
||||||
|
ooChannel.cpIndex++;
|
||||||
|
ooChannel.lastHash = hash;
|
||||||
|
if (ooChannel.cpIndex % CHECKPOINT_INTERVAL === 0) {
|
||||||
|
makeCheckpoint();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -261,11 +405,11 @@ define([
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
var ooLoaded = false;
|
||||||
var startOO = function (blob, file) {
|
var startOO = function (blob, file) {
|
||||||
if (APP.ooconfig) { return void console.error('already started'); }
|
if (APP.ooconfig) { return void console.error('already started'); }
|
||||||
var url = URL.createObjectURL(blob);
|
var url = URL.createObjectURL(blob);
|
||||||
var lock = /*locked !== common.getMetadataMgr().getNetfluxId() ||*/
|
var lock = readOnly || !common.isLoggedIn();
|
||||||
!common.isLoggedIn();
|
|
||||||
|
|
||||||
// Config
|
// Config
|
||||||
APP.ooconfig = {
|
APP.ooconfig = {
|
||||||
@ -313,51 +457,15 @@ define([
|
|||||||
if (ifr) { ifr.remove(); }
|
if (ifr) { ifr.remove(); }
|
||||||
};
|
};
|
||||||
APP.docEditor = new DocsAPI.DocEditor("cp-app-oo-placeholder", APP.ooconfig);
|
APP.docEditor = new DocsAPI.DocEditor("cp-app-oo-placeholder", APP.ooconfig);
|
||||||
mkChannel();
|
ooLoaded = true;
|
||||||
};
|
makeChannel();
|
||||||
|
|
||||||
var getContent = APP.getContent = function () {
|
|
||||||
try {
|
|
||||||
return window.frames[0].editor.asc_nativeGetFile();
|
|
||||||
} catch (e) {
|
|
||||||
console.error(e);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
var fmConfig = {
|
|
||||||
noHandlers: true,
|
|
||||||
noStore: true,
|
|
||||||
body: $('body'),
|
|
||||||
onUploaded: function (ev, data) {
|
|
||||||
if (!data || !data.url) { return; }
|
|
||||||
common.getSframeChannel().query('Q_OO_SAVE', data, function (err) {
|
|
||||||
if (err) {
|
|
||||||
console.error(err);
|
|
||||||
return void UI.alert(Messages.oo_saveError);
|
|
||||||
}
|
|
||||||
hashes.push(data.url);
|
|
||||||
APP.onLocal();
|
|
||||||
rtChannel.sendMsg(null, getLastCp(), function () {
|
|
||||||
UI.log(Messages.saved);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
APP.FM = common.createFileManager(fmConfig);
|
|
||||||
|
|
||||||
var saveToServer = function () {
|
|
||||||
var text = getContent();
|
|
||||||
var blob = new Blob([text], {type: 'plain/text'});
|
|
||||||
var file = getFileType();
|
|
||||||
blob.name = (metadataMgr.getMetadataLazy().title || file.doc) + '.' + file.type;
|
|
||||||
APP.FM.handleFile(blob);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
var loadLastDocument = function () {
|
var loadLastDocument = function () {
|
||||||
if (!hashes || !hashes.length) { return; }
|
var lastCp = getLastCp();
|
||||||
var last = hashes.slice().pop();
|
if (!lastCp) { return; }
|
||||||
var parsed = Hash.parsePadUrl(last);
|
ooChannel.cpIndex = lastCp.index || 0;
|
||||||
|
var parsed = Hash.parsePadUrl(lastCp.file);
|
||||||
var secret = Hash.getSecrets('file', parsed.hash);
|
var secret = Hash.getSecrets('file', parsed.hash);
|
||||||
if (!secret || !secret.channel) { return; }
|
if (!secret || !secret.channel) { return; }
|
||||||
var hexFileName = secret.channel;
|
var hexFileName = secret.channel;
|
||||||
@ -383,6 +491,7 @@ define([
|
|||||||
xhr.send(null);
|
xhr.send(null);
|
||||||
};
|
};
|
||||||
var loadDocument = function (newPad) {
|
var loadDocument = function (newPad) {
|
||||||
|
if (ooLoaded) { return; }
|
||||||
var type = common.getMetadataMgr().getPrivateData().ooType;
|
var type = common.getMetadataMgr().getPrivateData().ooType;
|
||||||
var file = getFileType();
|
var file = getFileType();
|
||||||
if (!newPad) {
|
if (!newPad) {
|
||||||
@ -432,17 +541,15 @@ define([
|
|||||||
|
|
||||||
var stringifyInner = function () {
|
var stringifyInner = function () {
|
||||||
var obj = {
|
var obj = {
|
||||||
content: {
|
content: content,
|
||||||
channel: channel,
|
|
||||||
hashes: hashes || [],
|
|
||||||
//locked: locked
|
|
||||||
},
|
|
||||||
metadata: metadataMgr.getMetadataLazy()
|
metadata: metadataMgr.getMetadataLazy()
|
||||||
};
|
};
|
||||||
// stringify the json and send it into chainpad
|
// stringify the json and send it into chainpad
|
||||||
return stringify(obj);
|
return stringify(obj);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
APP.getContent = function () { return content; };
|
||||||
|
|
||||||
APP.onLocal = config.onLocal = function () {
|
APP.onLocal = config.onLocal = function () {
|
||||||
if (initializing) { return; }
|
if (initializing) { return; }
|
||||||
if (readOnly) { return; }
|
if (readOnly) { return; }
|
||||||
@ -482,7 +589,9 @@ define([
|
|||||||
|
|
||||||
var $rightside = toolbar.$rightside;
|
var $rightside = toolbar.$rightside;
|
||||||
|
|
||||||
var $save = common.createButton('save', true, {}, saveToServer);
|
var $save = common.createButton('save', true, {}, function () {
|
||||||
|
saveToServer();
|
||||||
|
});
|
||||||
$save.appendTo($rightside);
|
$save.appendTo($rightside);
|
||||||
|
|
||||||
if (common.isLoggedIn()) {
|
if (common.isLoggedIn()) {
|
||||||
@ -520,10 +629,8 @@ define([
|
|||||||
UI.errorLoadingScreen(errorText);
|
UI.errorLoadingScreen(errorText);
|
||||||
throw new Error(errorText);
|
throw new Error(errorText);
|
||||||
}
|
}
|
||||||
hashes = hjson.content && hjson.content.hashes;
|
content = hjson.content || content;
|
||||||
//locked = hjson.content && hjson.content.locked;
|
newDoc = !content.hashes || Object.keys(content.hashes).length === 0;
|
||||||
channel = hjson.content && hjson.content.channel;
|
|
||||||
newDoc = !hashes || hashes.length === 0;
|
|
||||||
} else {
|
} else {
|
||||||
Title.updateTitle(Title.defaultTitle);
|
Title.updateTitle(Title.defaultTitle);
|
||||||
}
|
}
|
||||||
@ -551,15 +658,14 @@ define([
|
|||||||
|
|
||||||
openRtChannel(function () {
|
openRtChannel(function () {
|
||||||
loadDocument(newDoc);
|
loadDocument(newDoc);
|
||||||
|
|
||||||
initializing = false;
|
initializing = false;
|
||||||
|
setMyId();
|
||||||
setEditable(!readOnly);
|
setEditable(!readOnly);
|
||||||
UI.removeLoadingScreen();
|
UI.removeLoadingScreen();
|
||||||
});
|
});
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
var reloadDisplayed = false;
|
|
||||||
config.onRemote = function () {
|
config.onRemote = function () {
|
||||||
if (initializing) { return; }
|
if (initializing) { return; }
|
||||||
var userDoc = APP.realtime.getUserDoc();
|
var userDoc = APP.realtime.getUserDoc();
|
||||||
@ -567,20 +673,7 @@ define([
|
|||||||
if (json.metadata) {
|
if (json.metadata) {
|
||||||
metadataMgr.updateMetadata(json.metadata);
|
metadataMgr.updateMetadata(json.metadata);
|
||||||
}
|
}
|
||||||
/*
|
content = json.content;
|
||||||
var newHashes = (json.content && json.content.hashes) || [];
|
|
||||||
if (newHashes.length !== hashes.length ||
|
|
||||||
stringify(newHashes) !== stringify(hashes)) {
|
|
||||||
hashes = newHashes;
|
|
||||||
if (reloadDisplayed) { return; }
|
|
||||||
reloadDisplayed = true;
|
|
||||||
UI.confirm(Messages.oo_newVersion, function (yes) {
|
|
||||||
reloadDisplayed = false;
|
|
||||||
if (!yes) { return; }
|
|
||||||
common.gotoURL();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
};
|
};
|
||||||
|
|
||||||
config.onAbort = function () {
|
config.onAbort = function () {
|
||||||
|
|||||||
@ -63,7 +63,7 @@ define([
|
|||||||
// XXX add owners?
|
// XXX add owners?
|
||||||
// owners: something...
|
// owners: something...
|
||||||
channel: data.channel,
|
channel: data.channel,
|
||||||
lastCp: data.lastCp,
|
lastCpHash: data.lastCpHash,
|
||||||
padChan: Utils.secret.channel,
|
padChan: Utils.secret.channel,
|
||||||
validateKey: Utils.secret.keys.validateKey
|
validateKey: Utils.secret.keys.validateKey
|
||||||
}
|
}
|
||||||
@ -71,18 +71,22 @@ define([
|
|||||||
});
|
});
|
||||||
sframeChan.on('Q_OO_COMMAND', function (obj, cb) {
|
sframeChan.on('Q_OO_COMMAND', function (obj, cb) {
|
||||||
if (obj.cmd === 'SEND_MESSAGE') {
|
if (obj.cmd === 'SEND_MESSAGE') {
|
||||||
if (obj.data.isCp) {
|
|
||||||
obj.data.isCp += '|' + crypto.encrypt('cp');
|
|
||||||
} else {
|
|
||||||
obj.data.msg = crypto.encrypt(JSON.stringify(obj.data.msg));
|
obj.data.msg = crypto.encrypt(JSON.stringify(obj.data.msg));
|
||||||
}
|
var hash = obj.data.msg.slice(0,64);
|
||||||
|
var _cb = cb;
|
||||||
|
cb = function () {
|
||||||
|
_cb(hash);
|
||||||
|
};
|
||||||
}
|
}
|
||||||
Cryptpad.onlyoffice.execCommand(obj, cb);
|
Cryptpad.onlyoffice.execCommand(obj, cb);
|
||||||
});
|
});
|
||||||
Cryptpad.onlyoffice.onEvent.reg(function (obj) {
|
Cryptpad.onlyoffice.onEvent.reg(function (obj) {
|
||||||
if (obj.ev === 'MESSAGE') {
|
if (obj.ev === 'MESSAGE' && !/^cp\|/.test(obj.data)) {
|
||||||
try {
|
try {
|
||||||
obj.data = JSON.parse(crypto.decrypt(obj.data, Utils.secret.keys.validateKey));
|
obj.data = {
|
||||||
|
msg: JSON.parse(crypto.decrypt(obj.data, Utils.secret.keys.validateKey)),
|
||||||
|
hash: obj.data.slice(0,64)
|
||||||
|
};
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(e);
|
console.error(e);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -454,6 +454,7 @@ define([
|
|||||||
},
|
},
|
||||||
// "priv" is not shared with other users but is needed by the apps
|
// "priv" is not shared with other users but is needed by the apps
|
||||||
priv: {
|
priv: {
|
||||||
|
clientId: clientId,
|
||||||
edPublic: store.proxy.edPublic,
|
edPublic: store.proxy.edPublic,
|
||||||
friends: store.proxy.friends || {},
|
friends: store.proxy.friends || {},
|
||||||
settings: store.proxy.settings,
|
settings: store.proxy.settings,
|
||||||
|
|||||||
@ -1,11 +1,7 @@
|
|||||||
define([
|
define([
|
||||||
'/common/common-util.js',
|
], function () {
|
||||||
], function (Util) {
|
|
||||||
var OO = {};
|
var OO = {};
|
||||||
|
|
||||||
var getHistory = function (ctx, data, clientId, cb) {
|
|
||||||
};
|
|
||||||
|
|
||||||
var openChannel = function (ctx, obj, client, cb) {
|
var openChannel = function (ctx, obj, client, cb) {
|
||||||
var channel = obj.channel;
|
var channel = obj.channel;
|
||||||
var padChan = obj.padChan;
|
var padChan = obj.padChan;
|
||||||
@ -29,7 +25,6 @@ define([
|
|||||||
// ==> Use our netflux ID to create our client ID
|
// ==> Use our netflux ID to create our client ID
|
||||||
if (!c.id) { c.id = chan.wc.myID + '-' + client; }
|
if (!c.id) { c.id = chan.wc.myID + '-' + client; }
|
||||||
|
|
||||||
/// XXX send chan.history to client
|
|
||||||
chan.history.forEach(function (msg) {
|
chan.history.forEach(function (msg) {
|
||||||
ctx.emit('MESSAGE', msg, [client]);
|
ctx.emit('MESSAGE', msg, [client]);
|
||||||
});
|
});
|
||||||
@ -61,17 +56,11 @@ define([
|
|||||||
}
|
}
|
||||||
|
|
||||||
wc.on('join', function () {
|
wc.on('join', function () {
|
||||||
// XXX
|
|
||||||
});
|
});
|
||||||
wc.on('leave', function (peer) {
|
wc.on('leave', function () {
|
||||||
// XXX
|
|
||||||
});
|
});
|
||||||
wc.on('message', function (msg) {
|
wc.on('message', function (msg) {
|
||||||
if (/^cp\|/.test(msg)) {
|
|
||||||
chan.history = [];
|
|
||||||
} else {
|
|
||||||
chan.history.push(msg);
|
chan.history.push(msg);
|
||||||
}
|
|
||||||
ctx.emit('MESSAGE', msg, chan.clients);
|
ctx.emit('MESSAGE', msg, chan.clients);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -79,11 +68,7 @@ define([
|
|||||||
chan.sendMsg = function (msg, cb) {
|
chan.sendMsg = function (msg, cb) {
|
||||||
cb = cb || function () {};
|
cb = cb || function () {};
|
||||||
wc.bcast(msg).then(function () {
|
wc.bcast(msg).then(function () {
|
||||||
if (/^cp\|/.test(msg)) {
|
|
||||||
chan.history = [];
|
|
||||||
} else {
|
|
||||||
chan.history.push(msg);
|
chan.history.push(msg);
|
||||||
}
|
|
||||||
cb();
|
cb();
|
||||||
}, function (err) {
|
}, function (err) {
|
||||||
cb({error: err});
|
cb({error: err});
|
||||||
@ -92,7 +77,7 @@ define([
|
|||||||
|
|
||||||
if (first) {
|
if (first) {
|
||||||
chan.clients = [client];
|
chan.clients = [client];
|
||||||
chan.lastCp = obj.lastCp;
|
chan.lastCpHash = obj.lastCpHash;
|
||||||
first = false;
|
first = false;
|
||||||
cb();
|
cb();
|
||||||
}
|
}
|
||||||
@ -100,7 +85,7 @@ define([
|
|||||||
var hk = network.historyKeeper;
|
var hk = network.historyKeeper;
|
||||||
var cfg = {
|
var cfg = {
|
||||||
validateKey: obj.validateKey,
|
validateKey: obj.validateKey,
|
||||||
lastKnownHash: chan.lastKnownHash,
|
lastKnownHash: chan.lastKnownHash || chan.lastCpHash,
|
||||||
owners: obj.owners,
|
owners: obj.owners,
|
||||||
};
|
};
|
||||||
var msg = ['GET_HISTORY', wc.id, cfg];
|
var msg = ['GET_HISTORY', wc.id, cfg];
|
||||||
@ -137,24 +122,11 @@ define([
|
|||||||
}
|
}
|
||||||
if (parsed.error && parsed.channel) { return; }
|
if (parsed.error && parsed.channel) { return; }
|
||||||
|
|
||||||
var msg = parsed[4];
|
msg = parsed[4];
|
||||||
|
|
||||||
// Keep only the history for our channel
|
// Keep only the history for our channel
|
||||||
if (parsed[3] !== channel) { return; }
|
if (parsed[3] !== channel) { return; }
|
||||||
|
|
||||||
if (chan.lastCp) {
|
|
||||||
if (chan.lastCp === msg.slice(0, 11)) {
|
|
||||||
delete chan.lastCp;
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var isCp = /^cp\|/.test(msg);
|
|
||||||
if (isCp) {
|
|
||||||
chan.history = [];
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
chan.lastKnownHash = msg.slice(0,64);
|
chan.lastKnownHash = msg.slice(0,64);
|
||||||
ctx.emit('MESSAGE', msg, chan.clients);
|
ctx.emit('MESSAGE', msg, chan.clients);
|
||||||
chan.history.push(msg);
|
chan.history.push(msg);
|
||||||
@ -172,6 +144,25 @@ define([
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
var updateHash = function (ctx, data, clientId, cb) {
|
||||||
|
var c = ctx.clients[clientId];
|
||||||
|
if (!c) { return void cb({ error: 'NOT_IN_CHANNEL' }); }
|
||||||
|
var chan = ctx.channels[c.channel];
|
||||||
|
if (!chan) { return void cb({ error: 'INVALID_CHANNEL' }); }
|
||||||
|
var hash = data;
|
||||||
|
var index = -1;
|
||||||
|
chan.history.some(function (msg, idx) {
|
||||||
|
if (msg.slice(0,64) === hash) {
|
||||||
|
index = idx + 1;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (index !== -1) {
|
||||||
|
chan.history = chan.history.slice(index);
|
||||||
|
}
|
||||||
|
cb();
|
||||||
|
};
|
||||||
|
|
||||||
var sendMessage = function (ctx, data, clientId, cb) {
|
var sendMessage = function (ctx, data, clientId, cb) {
|
||||||
var c = ctx.clients[clientId];
|
var c = ctx.clients[clientId];
|
||||||
if (!c) { return void cb({ error: 'NOT_IN_CHANNEL' }); }
|
if (!c) { return void cb({ error: 'NOT_IN_CHANNEL' }); }
|
||||||
@ -214,6 +205,11 @@ define([
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var oldChannel = ctx.clients[clientId].channel;
|
||||||
|
var oldChan = ctx.channels[oldChannel];
|
||||||
|
if (oldChan) {
|
||||||
|
ctx.emit('LEAVE', {id: clientId}, [oldChan.clients[0]]);
|
||||||
|
}
|
||||||
delete ctx.clients[clientId];
|
delete ctx.clients[clientId];
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -240,6 +236,9 @@ define([
|
|||||||
if (cmd === 'SEND_MESSAGE') {
|
if (cmd === 'SEND_MESSAGE') {
|
||||||
return void sendMessage(ctx, data, clientId, cb);
|
return void sendMessage(ctx, data, clientId, cb);
|
||||||
}
|
}
|
||||||
|
if (cmd === 'UPDATE_HASH') {
|
||||||
|
return void updateHash(ctx, data, clientId, cb);
|
||||||
|
}
|
||||||
if (cmd === 'OPEN_CHANNEL') {
|
if (cmd === 'OPEN_CHANNEL') {
|
||||||
return void openChannel(ctx, data, clientId, cb);
|
return void openChannel(ctx, data, clientId, cb);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -95,7 +95,6 @@ define([
|
|||||||
// sframe-boot.js. Then we can start the channel.
|
// sframe-boot.js. Then we can start the channel.
|
||||||
var msgEv = _Util.mkEvent();
|
var msgEv = _Util.mkEvent();
|
||||||
var iframe = $('#sbox-iframe')[0].contentWindow;
|
var iframe = $('#sbox-iframe')[0].contentWindow;
|
||||||
var iframeReady = false;
|
|
||||||
var postMsg = function (data) {
|
var postMsg = function (data) {
|
||||||
iframe.postMessage(data, '*');
|
iframe.postMessage(data, '*');
|
||||||
};
|
};
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user