diff --git a/customize.dist/ckeditor-config.js b/customize.dist/ckeditor-config.js index 5c4940c52..7939f70f7 100644 --- a/customize.dist/ckeditor-config.js +++ b/customize.dist/ckeditor-config.js @@ -11,6 +11,8 @@ CKEDITOR.editorConfig = function( config ) { config.removePlugins= 'resize,elementspath'; config.resize_enabled= false; //bottom-bar config.extraPlugins= 'autolink,colorbutton,colordialog,font,indentblock,justify,mediatag,print,blockbase64,mathjax,wordcount'; + // FIXME translation for default? updating to a newer CKEditor seems like it will add 'default' by default + config.fontSize_sizes = '(Default)/unset;8/8px;9/9px;10/10px;11/11px;12/12px;14/14px;16/16px;18/18px;20/20px;22/22px;24/24px;26/26px;28/28px;36/36px;48/48px;72/72px'; config.toolbarGroups= [ // {"name":"clipboard","groups":["clipboard","undo"]}, //{"name":"editing","groups":["find","selection"]}, diff --git a/customize.dist/pages.js b/customize.dist/pages.js index 63cbbf154..e271dd74b 100644 --- a/customize.dist/pages.js +++ b/customize.dist/pages.js @@ -107,7 +107,7 @@ define([ ])*/ ]) ]), - h('div.cp-version-footer', "CryptPad v3.15.0 (PigFootedBandicoot)") + h('div.cp-version-footer', "CryptPad v3.16.0 (Quagga)") ]); }; diff --git a/customize.dist/src/less2/include/toolbar.less b/customize.dist/src/less2/include/toolbar.less index 49654dc56..73e608c4a 100644 --- a/customize.dist/src/less2/include/toolbar.less +++ b/customize.dist/src/less2/include/toolbar.less @@ -1179,6 +1179,7 @@ &.fa-download { order: 2; } &.fa-upload { order: 3; } &.fa-print { order: 4; } + &.fa-arrows-h { order: 5; } &.fa-cog { order: 5; } &.fa-info-circle { order: 6; } &.fa-help { order: 7; } diff --git a/lib/historyKeeper.js b/lib/historyKeeper.js index ff0327751..aa320f4b6 100644 --- a/lib/historyKeeper.js +++ b/lib/historyKeeper.js @@ -259,7 +259,7 @@ module.exports.create = function (config, cb) { throw new Error(err); } })); - }).nThen(function (w) { + }).nThen(function () { if (config.disableIntegratedTasks) { return; } config.intervals = config.intervals || {}; diff --git a/lib/hk-util.js b/lib/hk-util.js index 0e79c0691..3b8c07e09 100644 --- a/lib/hk-util.js +++ b/lib/hk-util.js @@ -665,31 +665,17 @@ const handleGetHistoryRange = function (Env, Server, seq, userId, parsed) { } Server.send(userId, [seq, 'ACK']); - Env.getOlderHistory(channelName, oldestKnownHash, function (err, messages) { + Env.getOlderHistory(channelName, oldestKnownHash, desiredMessages, desiredCheckpoint, function (err, toSend) { if (err && err.code !== 'ENOENT') { Env.Log.error("HK_GET_OLDER_HISTORY", err); } - if (!Array.isArray(messages)) { messages = []; } - - // FIXME this reduction could be done in the worker instead of the main process - var toSend = []; - if (typeof (desiredMessages) === "number") { - toSend = messages.slice(-desiredMessages); - } else { - let cpCount = 0; - for (var i = messages.length - 1; i >= 0; i--) { - if (/^cp\|/.test(messages[i][4]) && i !== (messages.length - 1)) { - cpCount++; - } - toSend.unshift(messages[i]); - if (cpCount >= desiredCheckpoint) { break; } - } + if (Array.isArray(toSend)) { + toSend.forEach(function (msg) { + Server.send(userId, [0, HISTORY_KEEPER_ID, 'MSG', userId, + JSON.stringify(['HISTORY_RANGE', txid, msg])]); + }); } - toSend.forEach(function (msg) { - Server.send(userId, [0, HISTORY_KEEPER_ID, 'MSG', userId, - JSON.stringify(['HISTORY_RANGE', txid, msg])]); - }); Server.send(userId, [0, HISTORY_KEEPER_ID, 'MSG', userId, JSON.stringify(['HISTORY_RANGE_END', txid, channelName]) diff --git a/lib/storage/file.js b/lib/storage/file.js index 00222c3f6..db7871ef0 100644 --- a/lib/storage/file.js +++ b/lib/storage/file.js @@ -27,7 +27,7 @@ const CHANNEL_WRITE_WINDOW = 300000; them. The tradeoff with this timeout is that some functions, the stream, and and the timeout itself are stored in memory. A longer timeout uses more memory and running out of memory will also kill the server. */ -const STREAM_CLOSE_TIMEOUT = 300000; +const STREAM_CLOSE_TIMEOUT = 120000; /* The above timeout closes the stream, but apparently that doesn't always work. We set yet another timeout to allow the runtime to gracefully close the stream @@ -83,15 +83,31 @@ var channelExists = function (filepath, cb) { const destroyStream = function (stream) { if (!stream) { return; } - try { stream.close(); } catch (err) { console.error(err); } + try { + stream.close(); + if (stream.closed && stream.fd === null) { return; } + } catch (err) { + console.error(err); + } setTimeout(function () { try { stream.destroy(); } catch (err) { console.error(err); } }, STREAM_DESTROY_TIMEOUT); }; +/* + accept a stream, an id (used as a label) and an optional number of milliseconds + + return a function which ignores all arguments + and first tries to gracefully close a stream + then destroys it after a period if the close was not successful + if the function is not called within the specified number of milliseconds + then it will be called implicitly with an error to indicate + that it was run because it timed out + +*/ const ensureStreamCloses = function (stream, id, ms) { return Util.bake(Util.mkTimeout(Util.once(function (err) { - destroyStream(stream, id); + destroyStream(stream); if (err) { // this can only be a timeout error... console.log("stream close error:", err, id); @@ -106,7 +122,7 @@ const ensureStreamCloses = function (stream, id, ms) { // it also allows the handler to abort reading at any time const readMessagesBin = (env, id, start, msgHandler, cb) => { const stream = Fs.createReadStream(mkPath(env, id), { start: start }); - const finish = ensureStreamCloses(stream, id); + const finish = ensureStreamCloses(stream, '[readMessagesBin:' + id + ']'); return void readFileBin(stream, msgHandler, function (err) { cb(err); finish(); @@ -117,7 +133,7 @@ const readMessagesBin = (env, id, start, msgHandler, cb) => { // returns undefined if the first message was not an object (not an array) var getMetadataAtPath = function (Env, path, _cb) { const stream = Fs.createReadStream(path, { start: 0 }); - const finish = ensureStreamCloses(stream, path); + const finish = ensureStreamCloses(stream, '[getMetadataAtPath:' + path + ']'); var cb = Util.once(Util.mkAsync(Util.both(_cb, finish)), function () { throw new Error("Multiple Callbacks"); }); @@ -203,7 +219,7 @@ var clearChannel = function (env, channelId, _cb) { */ var readMessages = function (path, msgHandler, _cb) { var stream = Fs.createReadStream(path, { start: 0}); - const finish = ensureStreamCloses(stream, path); + const finish = ensureStreamCloses(stream, '[readMessages:' + path + ']'); var cb = Util.once(Util.mkAsync(Util.both(finish, _cb))); return readFileBin(stream, function (msgObj, readMore) { @@ -231,7 +247,7 @@ var getDedicatedMetadata = function (env, channelId, handler, _cb) { var metadataPath = mkMetadataPath(env, channelId); var stream = Fs.createReadStream(metadataPath, {start: 0}); - const finish = ensureStreamCloses(stream, metadataPath); + const finish = ensureStreamCloses(stream, '[getDedicatedMetadata:' + metadataPath + ']'); var cb = Util.both(finish, _cb); readFileBin(stream, function (msgObj, readMore) { diff --git a/lib/workers/db-worker.js b/lib/workers/db-worker.js index 0f3d3b87f..d80c2dc21 100644 --- a/lib/workers/db-worker.js +++ b/lib/workers/db-worker.js @@ -222,10 +222,10 @@ const computeMetadata = function (data, cb) { const getOlderHistory = function (data, cb) { const oldestKnownHash = data.hash; const channelName = data.channel; + const desiredMessages = data.desiredMessages; + const desiredCheckpoint = data.desiredCheckpoint; - //const store = Env.store; - //const Log = Env.Log; - var messageBuffer = []; + var messages = []; var found = false; store.getMessages(channelName, function (msgStr) { if (found) { return; } @@ -246,9 +246,22 @@ const getOlderHistory = function (data, cb) { if (hash === oldestKnownHash) { found = true; } - messageBuffer.push(parsed); + messages.push(parsed); }, function (err) { - cb(err, messageBuffer); + var toSend = []; + if (typeof (desiredMessages) === "number") { + toSend = messages.slice(-desiredMessages); + } else { + let cpCount = 0; + for (var i = messages.length - 1; i >= 0; i--) { + if (/^cp\|/.test(messages[i][4]) && i !== (messages.length - 1)) { + cpCount++; + } + toSend.unshift(messages[i]); + if (cpCount >= desiredCheckpoint) { break; } + } + } + cb(err, toSend); }); }; diff --git a/lib/workers/index.js b/lib/workers/index.js index cc11d538b..6a163cadc 100644 --- a/lib/workers/index.js +++ b/lib/workers/index.js @@ -250,12 +250,14 @@ Workers.initialize = function (Env, config, _cb) { }); }; - Env.getOlderHistory = function (channel, oldestKnownHash, cb) { + Env.getOlderHistory = function (channel, oldestKnownHash, desiredMessages, desiredCheckpoint, cb) { Env.store.getWeakLock(channel, function (next) { sendCommand({ channel: channel, command: "GET_OLDER_HISTORY", hash: oldestKnownHash, + desiredMessages: desiredMessages, + desiredCheckpoint: desiredCheckpoint, }, Util.both(next, cb)); }); }; diff --git a/package-lock.json b/package-lock.json index cefaca30d..5c5c2bc1c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "cryptpad", - "version": "3.15.0", + "version": "3.16.0", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index cd684660f..d5e019ad1 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "cryptpad", "description": "realtime collaborative visual editor with zero knowlege server", - "version": "3.15.0", + "version": "3.16.0", "license": "AGPL-3.0+", "repository": { "type": "git", diff --git a/www/admin/index.html b/www/admin/index.html index 79a96c97b..c59dd8edc 100644 --- a/www/admin/index.html +++ b/www/admin/index.html @@ -6,7 +6,7 @@ - +