mirror of
https://github.com/cryptpad/cryptpad.git
synced 2026-09-14 11:05:41 +05:00
feat(storage): office apps history refactor
This commit is contained in:
parent
efabdfe00d
commit
f9f5963da8
@ -210,6 +210,9 @@
|
||||
flex: 1;
|
||||
background-color: @history_userBg1;
|
||||
border: 2px solid @history_userBg1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
&:nth-child(2n) {
|
||||
background-color: @history_userBg2;
|
||||
border: 2px solid @history_userBg2;
|
||||
@ -217,7 +220,7 @@
|
||||
&.cp-selected {
|
||||
border: 2px solid @cryptpad_text_col;
|
||||
position: relative;
|
||||
svg {
|
||||
svg:not([data-snapshot]) {
|
||||
position: absolute;
|
||||
margin: 0;
|
||||
left: 50%;
|
||||
@ -225,6 +228,10 @@
|
||||
transform: translateX(-50%)
|
||||
}
|
||||
}
|
||||
svg[data-snapshot] {
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
.cp-history-timeline-users {
|
||||
|
||||
@ -219,12 +219,16 @@ const addLinkedDocument = (env, channelId, type, data, cb) => {
|
||||
} else if (type === 'media') {
|
||||
if (data.length !== 48) { return void cb('EINVAL'); }
|
||||
content.media ||= [];
|
||||
if (content.media.includes(data)) { return void cb(); }
|
||||
if (content.media.includes(data)) {
|
||||
return void cb(void 0, content);
|
||||
}
|
||||
content.media.push(data);
|
||||
} else if (type === 'channels') {
|
||||
if (data.length !== 32) { return void cb('EINVAL'); }
|
||||
content.channels ||= [];
|
||||
if (content.channels.includes(data)) { return void cb(); }
|
||||
if (content.channels.includes(data)) {
|
||||
return void cb(void 0, content);
|
||||
}
|
||||
content.channels.push(data);
|
||||
}
|
||||
writeLinkedFile(env, path, content, cb);
|
||||
|
||||
@ -41,6 +41,9 @@ const factory = (Feedback) => {
|
||||
channel: channel,
|
||||
};
|
||||
} else { // same channel existing tab
|
||||
setTimeout(() => {
|
||||
ctx.emit('READY', chan.clients, [client]);
|
||||
});
|
||||
return void cb();
|
||||
}
|
||||
|
||||
|
||||
@ -14,6 +14,73 @@ define([
|
||||
//var ChainPad = window.ChainPad;
|
||||
var History = {};
|
||||
|
||||
History.loadHistoryData = (cfg) => {
|
||||
const {
|
||||
sframeChan, mainRtChannel, hashes, sortedCp, downloadId,
|
||||
currentCp, nextCp
|
||||
} = cfg;
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
// New CP: use this cp's rtChannel
|
||||
if (currentCp?.rtChannel) {
|
||||
// Load all messages from currentCp.rtChannel
|
||||
sframeChan.query('Q_GET_FULL_HISTORY', {
|
||||
channel: currentCp.rtChannel,
|
||||
isDownload: downloadId,
|
||||
full: true
|
||||
}, function (err, data) {
|
||||
if (err) { return void reject(err); }
|
||||
resolve(data);
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// Old CP or no CP: use mainRtChannel
|
||||
|
||||
// No CP and no nextCp hash
|
||||
if (!currentCp && !nextCp?.hash) {
|
||||
// Load all messages from mainRtChannel
|
||||
sframeChan.query('Q_GET_FULL_HISTORY', {
|
||||
channel: mainRtChannel,
|
||||
isDownload: downloadId,
|
||||
full: true
|
||||
}, function (err, data) {
|
||||
if (err) { return void reject(err); }
|
||||
resolve(data);
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// If we have a startHash or an endHash, use
|
||||
// the GET_HISTORY_RANGE command
|
||||
let startHash = currentCp?.hash || 'NONE';
|
||||
let endHash = nextCp?.hash;
|
||||
|
||||
if (currentCp?.hash || nextCp?.hash) {
|
||||
sframeChan.query('Q_GET_HISTORY_RANGE', {
|
||||
channel: mainRtChannel,
|
||||
lastKnownHash: endHash,
|
||||
toHash: startHash,
|
||||
isDownload: downloadId,
|
||||
}, function (err, data) {
|
||||
if (err || !Array.isArray(data.messages)) {
|
||||
return void reject(err || 'EINVAL');
|
||||
}
|
||||
let msgs = data.messages;
|
||||
if (data.messages[0].serverHash === startHash) {
|
||||
msgs.shift();
|
||||
}
|
||||
resolve(msgs);
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
reject('INVALID_CP');
|
||||
});
|
||||
|
||||
|
||||
};
|
||||
|
||||
History.create = function (common, config) {
|
||||
if (!config.$toolbar) { return void console.error("config.$toolbar is undefined");}
|
||||
if (History.loading) { return void console.error("History is already being loaded..."); }
|
||||
@ -26,6 +93,7 @@ define([
|
||||
throw new Error("Missing config element");
|
||||
}
|
||||
|
||||
const metadataMgr = common.getMetadataMgr();
|
||||
|
||||
const ooMessages = {};
|
||||
|
||||
@ -64,79 +132,14 @@ define([
|
||||
let currentCp = hashes[cpId];
|
||||
let nextCp = hashes[sortedCp[cpIdx + 1]];
|
||||
|
||||
// New CP: use this cp's rtChannel
|
||||
|
||||
if (currentCp?.rtChannel) {
|
||||
// Load all messages from currentCp.rtChannel
|
||||
sframeChan.query('Q_GET_FULL_HISTORY', {
|
||||
channel: currentCp.rtChannel,
|
||||
full: true
|
||||
}, function (err, data) {
|
||||
if (err) { return void reject(err); }
|
||||
data.unshift(void 0);
|
||||
ooMessages[cpId] = data;
|
||||
resolve(data);
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// Old CP or no CP: use mainRtChannel
|
||||
|
||||
// No CP and no nextCp hash
|
||||
if (!currentCp && !nextCp?.hash) {
|
||||
// Load all messages from mainRtChannel
|
||||
sframeChan.query('Q_GET_FULL_HISTORY', {
|
||||
channel: mainRtChannel,
|
||||
full: true
|
||||
}, function (err, data) {
|
||||
if (err) { return void reject(err); }
|
||||
data.unshift(void 0);
|
||||
ooMessages[cpId] = data;
|
||||
resolve(data);
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// If we have a startHash or an endHash, use
|
||||
// the GET_HISTORY_RANGE command
|
||||
/**
|
||||
* startHash is the first element to load from history
|
||||
* - 'NONE' means load from the start of the file
|
||||
* - otherwise load from the given hash
|
||||
*/
|
||||
let startHash = currentCp?.hash || 'NONE';
|
||||
/**
|
||||
* endHash is the last (most recent) element to load
|
||||
* - undefined means load until the end of the file
|
||||
* - if nextCp doesn't exist or is on the new format
|
||||
* - otherwise load until the given hash
|
||||
*/
|
||||
let endHash = nextCp?.hash;
|
||||
|
||||
|
||||
// Old CP or no CP and nextCp hash
|
||||
if (currentCp?.hash || nextCp?.hash) {
|
||||
// Load all messages of mainRtChannel from "hash" to nextCp.hash
|
||||
sframeChan.query('Q_GET_HISTORY_RANGE', {
|
||||
channel: mainRtChannel,
|
||||
lastKnownHash: endHash,
|
||||
toHash: startHash,
|
||||
}, function (err, data) {
|
||||
if (err || !Array.isArray(data.messages)) {
|
||||
return void reject(err || 'EINVAL');
|
||||
}
|
||||
let msgs = data.messages;
|
||||
if (data.messages[0].serverHash === startHash) {
|
||||
msgs.shift();
|
||||
}
|
||||
msgs.unshift(void 0);
|
||||
ooMessages[cpId] = msgs;
|
||||
resolve(msgs);
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
reject('INVALID_CP');
|
||||
History.loadHistoryData({
|
||||
sframeChan,
|
||||
mainRtChannel, hashes, sortedCp, currentCp, nextCp
|
||||
}).then(data => {
|
||||
data.unshift(void 0);
|
||||
ooMessages[cpId] = data;
|
||||
resolve(data);
|
||||
}).catch(reject);
|
||||
});
|
||||
};
|
||||
|
||||
@ -178,23 +181,38 @@ define([
|
||||
$timeline.empty();
|
||||
const msgs = getCpMsgs();
|
||||
const cp = hashes[getCpId()];
|
||||
|
||||
const md = Util.clone(metadataMgr.getMetadata());
|
||||
const snapshots = md?.snapshots || {};
|
||||
|
||||
const els = msgs.map((msg, i) => {
|
||||
const selected = i === msgIdx;
|
||||
const selClass = selected ? '.cp-selected' : '';
|
||||
const content = selected ? Icons.get('chevron-down', {})
|
||||
: undefined;
|
||||
let title = `${getCpId()}.${i}`
|
||||
|
||||
const s = snapshots[title];
|
||||
|
||||
if (msg?.time) {
|
||||
title += ' - ' + new Date(msg.time).toLocaleString();
|
||||
} else if (i === 0 && cp?.time) {
|
||||
title += ' - ' + new Date(cp.time).toLocaleString();
|
||||
}
|
||||
|
||||
let snap;
|
||||
if (s) {
|
||||
if (s?.title) { title += `\n${Util.fixHTML(s.title)}`; }
|
||||
snap = Icons.get('snapshot', {'data-snapshot': '1'});
|
||||
}
|
||||
|
||||
return h('span.cp-history-bar-el'+selClass, {
|
||||
title,
|
||||
'data-msg': i
|
||||
}, content);
|
||||
}, [content, snap]);
|
||||
});
|
||||
$timeline.append(els);
|
||||
|
||||
updateNavButtons();
|
||||
};
|
||||
|
||||
@ -404,9 +422,12 @@ define([
|
||||
onKeyUp = function (e) { e.stopPropagation(); };
|
||||
$(window).on('keydown', onKeyDown).on('keyup', onKeyUp).focus();
|
||||
|
||||
$timeline.on('click', '.cp-history-bar-el', (ev) => {
|
||||
const target = ev.target;
|
||||
$timeline.on('click', '.cp-history-bar-el', (ev, el) => {
|
||||
let target = ev.target;
|
||||
if (!target) { return; }
|
||||
if (!target.classList.contains('cp-history-bar-el')) {
|
||||
target = $(target).closest('.cp-history-bar-el')[0];
|
||||
}
|
||||
const attr = target?.attributes?.getNamedItem('data-msg');
|
||||
const idx = Number(attr?.value || 0);
|
||||
if (idx > msgIdx) {
|
||||
@ -424,9 +445,6 @@ define([
|
||||
});
|
||||
});
|
||||
$(snapshot).click(function () {
|
||||
// XXX
|
||||
/*
|
||||
if (cpIndex === -1 && msgIndex === -1) { return void UI.warn(Messages.snapshots_ooPickVersion); }
|
||||
var input = h('input', {
|
||||
placeholder: Messages.snapshots_placeholder
|
||||
});
|
||||
@ -448,14 +466,14 @@ define([
|
||||
onClick: function () {
|
||||
var val = $input.val();
|
||||
if (!val) { return true; }
|
||||
msgs = ooMessages[id];
|
||||
const patch = getCurrentMsg();
|
||||
config.makeSnapshot(val, function (err) {
|
||||
if (err) { return; }
|
||||
$input.val('');
|
||||
UI.log(Messages.saved);
|
||||
}, {
|
||||
hash: getVersion(position),
|
||||
time: currentTime || patch && patch.time || 0
|
||||
hash: getCurrentVersion(),
|
||||
time: patch?.time || +new Date()
|
||||
});
|
||||
},
|
||||
keys: [13],
|
||||
@ -465,7 +483,6 @@ define([
|
||||
setTimeout(function () {
|
||||
$input.focus();
|
||||
});
|
||||
*/
|
||||
});
|
||||
|
||||
// Close & restore buttons
|
||||
@ -494,9 +511,7 @@ define([
|
||||
msgIdx = msgs.length - 1;
|
||||
showVersion();
|
||||
updateTimeline();
|
||||
});
|
||||
|
||||
|
||||
}).catch(err => { console.error(err); });
|
||||
};
|
||||
|
||||
return History;
|
||||
|
||||
@ -144,6 +144,17 @@ define([
|
||||
return w.editor || w.editorCell;
|
||||
};
|
||||
|
||||
const addOfficeJS = (version) => {
|
||||
if (typeof(version) === 'number') {
|
||||
version = `v${version}/`;
|
||||
}
|
||||
var s = h('script', {
|
||||
type:'text/javascript',
|
||||
src: ApiConfig.httpSafeOrigin + '/common/onlyoffice/dist/'+version+'web-apps/apps/api/documents/api.js?' + APP.urlArgs
|
||||
});
|
||||
$('#cp-app-oo-editor').append(s);
|
||||
};
|
||||
|
||||
var setEditable = function (state, force) {
|
||||
$('#cp-app-oo-editor').find('#cp-app-oo-offline').remove();
|
||||
/*
|
||||
@ -623,6 +634,14 @@ define([
|
||||
|
||||
if (APP.docEditor) { APP.docEditor.destroyEditor(); } // Kill the old editor
|
||||
$('iframe[name="frameEditor"]').after(h('div#cp-app-oo-placeholder-a')).remove();
|
||||
|
||||
const v = cpData.version || content.version;
|
||||
if (v && v !== APP.currentOOVersion) {
|
||||
$('#cp-app-oo-editor').find('script').remove();
|
||||
addOfficeJS(v);
|
||||
APP.currentOOVersion = v;
|
||||
}
|
||||
|
||||
ooLoaded = false;
|
||||
oldLocks = {};
|
||||
Object.keys(pendingChanges).forEach(function (key) {
|
||||
@ -811,56 +830,44 @@ define([
|
||||
|
||||
var openVersionHash = function (version) {
|
||||
readOnly = true;
|
||||
var hashes = content.hashes || {};
|
||||
var sortedCp = sortCpIndex(hashes);
|
||||
var s = version.split('.');
|
||||
var v = parseInt(s[1]);
|
||||
const hashes = content.hashes || {};
|
||||
const sortedCp = sortCpIndex(hashes);
|
||||
|
||||
const s = version.split('.');
|
||||
if (s.length !== 2) { return UI.errorLoadingScreen(Messages.error); }
|
||||
|
||||
const cpId = Number(s[0]);
|
||||
const cp = hashes[cpId] || {};
|
||||
let cpId = Number(s[0]);
|
||||
if (APP.isDownload) { cpId = sortedCp[sortedCp.length - 1]; }
|
||||
const currentCp = hashes[cpId] || {};
|
||||
|
||||
const cpIdx = sortedCp.indexOf(cpId);
|
||||
const nextCpId = sortedCp[cpidx + 1];
|
||||
const nextCp = sortedCp[cpIdx + 1];
|
||||
|
||||
var minor = Number(s[1]) + 1;
|
||||
let minor = Number(s[1]);
|
||||
if (APP.isDownload) { minor = undefined; }
|
||||
|
||||
var toHash = cp.hash || 'NONE';
|
||||
var fromHash = nextCpId ? hashes[nextCpId].hash : 'NONE';
|
||||
|
||||
// XXX XXX HISTORY
|
||||
// if (cp.file && !cp.hash) {} // new format, full history...
|
||||
sframeChan.query('Q_GET_HISTORY_RANGE', {
|
||||
channel: content.channel,
|
||||
lastKnownHash: fromHash,
|
||||
toHash: toHash,
|
||||
isDownload: APP.isDownload
|
||||
}, function (err, data) {
|
||||
if (err) { console.error(err); return void UI.errorLoadingScreen(Messages.error); }
|
||||
if (!Array.isArray(data.messages)) {
|
||||
console.error('Not an array');
|
||||
return void UI.errorLoadingScreen(Messages.error);
|
||||
}
|
||||
|
||||
// The first "cp" in history is the empty doc. It doesn't include the first patch
|
||||
// of the history
|
||||
var messages = data.messages;
|
||||
|
||||
History.loadHistoryData({
|
||||
sframeChan,
|
||||
mainRtChannel: content.channel,
|
||||
hashes: content.hashes,
|
||||
downloadId: APP.isDownload,
|
||||
sortedCp, currentCp, nextCp
|
||||
}).then(messages => {
|
||||
// Parse messages
|
||||
messages.forEach(function (obj) {
|
||||
try { obj.msg = JSON.parse(obj.msg); } catch (e) { console.error(e); }
|
||||
});
|
||||
|
||||
// The version exists if we have results in the "messages" array
|
||||
// or if we requested a x.0 version
|
||||
var exists = !Number(s[1]) || messages.length;
|
||||
var exists = !minor || messages.length;
|
||||
var vHashEl;
|
||||
|
||||
if (!privateData.embed) {
|
||||
var vTime = (messages[messages.length - 1] || {}).time;
|
||||
var vTime = (messages[minor - 1] || currentCp)?.time;
|
||||
var vTimeStr = vTime ? new Date(vTime).toLocaleString()
|
||||
: 'v' + privateData.ooVersionHash;
|
||||
var vTxt = Messages._getKey('infobar_versionHash', [vTimeStr]);
|
||||
var vTxt = Messages._getKey('infobar_versionHash', [vTimeStr]);
|
||||
|
||||
// If we expected patched and we don't have any, it means this part
|
||||
// of the history has been deleted
|
||||
@ -876,29 +883,32 @@ define([
|
||||
|
||||
if (!exists) { return void UI.removeLoadingScreen(); }
|
||||
|
||||
loadLastDocument(cp)
|
||||
.then(({blob, fileType}) => {
|
||||
// XXX HISTORY minor.... ?
|
||||
ooChannel.queue = messages.slice(1, minor+1);
|
||||
resetData(blob, fileType, cp);
|
||||
APP.history = true;
|
||||
loadLastDocument(currentCp)
|
||||
.then(({blob, fileType}) => {
|
||||
ooChannel.queue = messages.slice(0, minor);
|
||||
console.error(ooChannel.queue.slice());
|
||||
resetData(blob, fileType, currentCp);
|
||||
UI.removeLoadingScreen();
|
||||
})
|
||||
.catch(() => {
|
||||
if (cp.hash && vHashEl) {
|
||||
// We requested a checkpoint but we can't find it...
|
||||
UI.removeLoadingScreen();
|
||||
})
|
||||
.catch(() => {
|
||||
if (cp.hash && vHashEl) {
|
||||
// We requested a checkpoint but we can't find it...
|
||||
UI.removeLoadingScreen();
|
||||
vHashEl.innerText = Messages.oo_deletedVersion;
|
||||
$(vHashEl).removeClass('alert-warning').addClass('alert-danger');
|
||||
return;
|
||||
}
|
||||
var file = getFileType();
|
||||
var type = common.getMetadataMgr().getPrivateData().ooType;
|
||||
if (APP.downloadType) { type = APP.downloadType; }
|
||||
var blob = loadInitDocument(type, true);
|
||||
ooChannel.queue = file.doc === 'spreadsheet' ? messages.slice(0, v) : messages.slice(0, v+1);
|
||||
resetData(blob, file, {});
|
||||
UI.removeLoadingScreen();
|
||||
});
|
||||
vHashEl.innerText = Messages.oo_deletedVersion;
|
||||
$(vHashEl).removeClass('alert-warning').addClass('alert-danger');
|
||||
return;
|
||||
}
|
||||
var file = getFileType();
|
||||
var type = common.getMetadataMgr().getPrivateData().ooType;
|
||||
if (APP.downloadType) { type = APP.downloadType; }
|
||||
var blob = loadInitDocument(type, true);
|
||||
ooChannel.queue = messages.slice(0, minor);
|
||||
resetData(blob, file, {});
|
||||
UI.removeLoadingScreen();
|
||||
});
|
||||
}).catch(err => {
|
||||
if (err) { console.error(err); return void UI.errorLoadingScreen(Messages.error); }
|
||||
});
|
||||
};
|
||||
|
||||
@ -1116,6 +1126,8 @@ define([
|
||||
};
|
||||
// Update the locks status in onlyoffice
|
||||
var handleNewLocks = function (o, n) {
|
||||
if (APP.history) { return; }
|
||||
|
||||
var hasNew = false;
|
||||
// Check if we have at least one new lock
|
||||
Object.keys(n || {}).some(function (id) {
|
||||
@ -1156,7 +1168,7 @@ define([
|
||||
var users = Object.keys(metadataMgr.getMetadata().users);
|
||||
Object.keys(locks).forEach(function (id) {
|
||||
var nId = id.slice(0,32);
|
||||
if (users.indexOf(nId) === -1) {
|
||||
if (users.indexOf(nId) === -1 || APP.history) {
|
||||
// Offline locks: support old format
|
||||
var l = (locks[id] && !locks[id].block) ? getUserLock(id) : [locks[id]];
|
||||
ooChannel.send({
|
||||
@ -3004,6 +3016,7 @@ Uncaught TypeError: Cannot read property 'calculatedType' of null
|
||||
APP.onLocal = config.onLocal = function () {
|
||||
if (initializing) { return; }
|
||||
if (readOnly) { return; }
|
||||
if (APP.history) { return; }
|
||||
|
||||
// Update metadata
|
||||
var content = stringifyInner();
|
||||
@ -3155,11 +3168,8 @@ Uncaught TypeError: Cannot read property 'calculatedType' of null
|
||||
readOnly = true;
|
||||
var version = (!content.version || content.version === 1) ? 'v1/' :
|
||||
(content.version <= 3 ? 'v2b/' : OOCurrentVersion.currentVersion + '/');
|
||||
var s = h('script', {
|
||||
type:'text/javascript',
|
||||
src: ApiConfig.httpSafeOrigin + '/common/onlyoffice/dist/'+version+'web-apps/apps/api/documents/api.js?' + APP.urlArgs
|
||||
});
|
||||
$('#cp-app-oo-editor').empty().append(h('div#cp-app-oo-placeholder-a')).append(s);
|
||||
$('#cp-app-oo-editor').empty().append(h('div#cp-app-oo-placeholder-a'));
|
||||
addOfficeJS(version);
|
||||
|
||||
var hashes = content.hashes || {};
|
||||
var idx = sortCpIndex(hashes);
|
||||
@ -3283,10 +3293,11 @@ Uncaught TypeError: Cannot read property 'calculatedType' of null
|
||||
ooChannel.queue = [];
|
||||
ooChannel.ready = false;
|
||||
// Fill the queue and then load the last CP
|
||||
//rtChannel.getHistory(function () {
|
||||
|
||||
rtChannel.getHistory(function () {
|
||||
var lastCp = getLastCp();
|
||||
loadCp(lastCp, true);
|
||||
//});
|
||||
});
|
||||
};
|
||||
|
||||
var deleteSnapshot = function (hash) {
|
||||
@ -3556,14 +3567,6 @@ Uncaught TypeError: Cannot read property 'calculatedType' of null
|
||||
checkLinkedDocs();
|
||||
}
|
||||
|
||||
Object.keys(content.hashes).forEach(id => {
|
||||
let cpData = content.hashes[id];
|
||||
if (!cpData.rtChannel) { return; }
|
||||
delete cpData.index;
|
||||
delete cpData.hash;
|
||||
});
|
||||
APP.onLocal();
|
||||
|
||||
APP.startNew = isNew;
|
||||
|
||||
var version = OOCurrentVersion.currentVersion + '/';
|
||||
@ -3681,11 +3684,9 @@ APP.onLocal();
|
||||
checkCheckpoint();
|
||||
}
|
||||
|
||||
var s = h('script', {
|
||||
type:'text/javascript',
|
||||
src: ApiConfig.httpSafeOrigin + '/common/onlyoffice/dist/'+version+'web-apps/apps/api/documents/api.js?' + APP.urlArgs
|
||||
});
|
||||
$('#cp-app-oo-editor').append(s);
|
||||
addOfficeJS(version);
|
||||
|
||||
APP.currentOOVersion = content.version || 1;
|
||||
|
||||
if (metadataMgr.getPrivateData().burnAfterReading && content && content.channel) {
|
||||
sframeChan.event('EV_BURN_PAD', content.channel);
|
||||
@ -3735,6 +3736,7 @@ APP.onLocal();
|
||||
common.openCursorChannel(APP.onLocal);
|
||||
cursor = common.createCursor(APP.onLocal);
|
||||
cursor.onCursorUpdate(function (data) {
|
||||
if (APP.history) { return; }
|
||||
// Leaving user
|
||||
if (data && data.leave && data.id) {
|
||||
// When a netflux user leaves, remove all their cursors
|
||||
@ -4018,6 +4020,8 @@ APP.onLocal();
|
||||
|
||||
content = json.content;
|
||||
|
||||
if (APP.history) { return; }
|
||||
|
||||
if (content.saveLock && wasLocked !== content.saveLock) {
|
||||
// Someone new is creating a checkpoint: fix the sheets ids
|
||||
fixSheets();
|
||||
|
||||
@ -1716,12 +1716,18 @@ define([
|
||||
|
||||
// History
|
||||
sframeChan.on('Q_GET_FULL_HISTORY', function (data, cb) {
|
||||
var crypto = Crypto.createEncryptor(secret.keys);
|
||||
let nSecret = secret;
|
||||
if (data.isDownload && ooDownloadData[data.isDownload]) {
|
||||
var ooData = ooDownloadData[data.isDownload];
|
||||
delete ooDownloadData[data.isDownload];
|
||||
nSecret = Utils.Hash.getSecrets('sheet', ooData.hash, ooData.password);
|
||||
}
|
||||
var crypto = Crypto.createEncryptor(nSecret.keys);
|
||||
Cryptpad.getFullHistory({
|
||||
debug: data?.debug,
|
||||
full: data?.full,
|
||||
channel: data.channel || secret.channel,
|
||||
validateKey: secret.keys.validateKey
|
||||
channel: data.channel || nSecret.channel,
|
||||
validateKey: nSecret.keys.validateKey
|
||||
}, function (encryptedMsgs) {
|
||||
var nt = nThen;
|
||||
var decryptedMsgs = [];
|
||||
|
||||
2
www/common/worker.bundle.min.js
vendored
2
www/common/worker.bundle.min.js
vendored
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue
Block a user