diff --git a/customize.dist/loading.js b/customize.dist/loading.js index 6e4781aaf..8efca25fd 100644 --- a/customize.dist/loading.js +++ b/customize.dist/loading.js @@ -318,8 +318,8 @@ button:not(.btn).primary:hover{ // Make sure progress doesn't go backward var c = types.indexOf(data.type); - if (c < current) { return console.error(data); } - if (c === current && progress > data.progress) { return console.error(data); } + if (c < current) { return console.debug(data); } + if (c === current && progress > data.progress) { return console.debug(data); } progress = data.progress; try { diff --git a/www/admin/app-admin.less b/www/admin/app-admin.less index fe9121090..a7efc2dad 100644 --- a/www/admin/app-admin.less +++ b/www/admin/app-admin.less @@ -31,6 +31,9 @@ margin-top: 5px; } } + .cp-admin-setlimit-form + button { + margin-top: 5px !important; + } .cp-admin-getlimits { code { cursor: pointer; diff --git a/www/common/application_config_internal.js b/www/common/application_config_internal.js index 3185f2e29..1e848d289 100644 --- a/www/common/application_config_internal.js +++ b/www/common/application_config_internal.js @@ -169,7 +169,7 @@ define(function() { // make them have a very slow loading time. To avoid impacting the user experience // significantly, we're limiting the number of teams per user to 3 by default. // You can change this value here. - //config.maxTeamsSlots = 3; + //config.maxTeamsSlots = 5; // Each team is considered as a registered user by the server. Users and teams are indistinguishable // in the database so teams will offer the same storage limits as users by default. @@ -177,7 +177,7 @@ define(function() { // We're limiting the number of teams each user is able to own to 1 in order to make sure // users don't use "fake" teams (1 member) just to increase their storage limit. // You can change the value here. - // config.maxOwnedTeams = 1; + // config.maxOwnedTeams = 5; return config; }); diff --git a/www/common/common-constants.js b/www/common/common-constants.js index 17db2302c..fdae2b5de 100644 --- a/www/common/common-constants.js +++ b/www/common/common-constants.js @@ -12,8 +12,8 @@ define(['/customize/application_config.js'], function (AppConfig) { tokenKey: 'loginToken', displayPadCreationScreen: 'displayPadCreationScreen', deprecatedKey: 'deprecated', - MAX_TEAMS_SLOTS: AppConfig.maxTeamsSlots || 3, - MAX_TEAMS_OWNED: AppConfig.maxOwnedTeams || 1, + MAX_TEAMS_SLOTS: AppConfig.maxTeamsSlots || 5, + MAX_TEAMS_OWNED: AppConfig.maxOwnedTeams || 5, // Apps criticalApps: ['profile', 'settings', 'debug', 'admin', 'support', 'notifications'] }; diff --git a/www/common/common-ui-elements.js b/www/common/common-ui-elements.js index 81b202ee0..93b9e3648 100644 --- a/www/common/common-ui-elements.js +++ b/www/common/common-ui-elements.js @@ -2552,7 +2552,9 @@ define([ var block = h('div#cp-loading-burn-after-reading', [ info, - button + h('nav', { + style: 'text-align: right' + }, button), ]); UI.errorLoadingScreen(block); }; diff --git a/www/common/inner/share.js b/www/common/inner/share.js index f3ca53f75..2be698d74 100644 --- a/www/common/inner/share.js +++ b/www/common/inner/share.js @@ -345,7 +345,7 @@ define([ localStore.get('hide-alert-shareLinkWarning', function (val) { if (val === '1') { return; } - $(shareLinkWarning).show(); + $(shareLinkWarning).css('display', 'flex'); $(dismissButton).on('click', function () { localStore.put('hide-alert-shareLinkWarning', '1'); diff --git a/www/common/outer/async-store.js b/www/common/outer/async-store.js index afb799990..58fd28e00 100644 --- a/www/common/outer/async-store.js +++ b/www/common/outer/async-store.js @@ -331,6 +331,7 @@ define([ if (!s.rpc) { return void cb({error: 'RPC_NOT_READY'}); } s.rpc.removeOwnedChannel(channel, function (err) { + if (!err) { Cache.clearChannel(channel); } cb({error:err}); }); }; @@ -463,6 +464,7 @@ define([ store.anon_rpc.send("GET_FILE_SIZE", channelId, function (e, response) { if (e) { return void cb({error: e}); } if (response && response.length && typeof(response[0]) === 'number') { + if (response[0] === 0) { Cache.clearChannel(channelId); } return void cb({size: response[0]}); } else { cb({error: 'INVALID_RESPONSE'}); @@ -476,6 +478,7 @@ define([ store.anon_rpc.send("IS_NEW_CHANNEL", channelId, function (e, response) { if (e) { return void cb({error: e}); } if (response && response.length && typeof(response[0]) === 'boolean') { + if (response[0]) { Cache.clearChannel(channelId); } return void cb({ isNew: response[0] }); @@ -2277,6 +2280,9 @@ define([ try { store.onlyoffice.leavePad(chanId); } catch (e) { console.error(e); } + try { + Cache.leaveChannel(chanId); + } catch (e) { console.error(e); } if (!Store.channels[chanId]) { return; } diff --git a/www/common/outer/cache-store.js b/www/common/outer/cache-store.js index 067d2dda7..7a0a50209 100644 --- a/www/common/outer/cache-store.js +++ b/www/common/outer/cache-store.js @@ -91,23 +91,36 @@ define([ array.splice(0, firstCpIdx); }; - S.storeCache = function (id, validateKey, val, cb) { - cb = Util.once(Util.mkAsync(cb || function () {})); + var t = {}; + S.storeCache = function (id, validateKey, val, onError) { + onError = Util.once(Util.mkAsync(onError || function () {})); + + onReady.reg(function () { + + // Make a throttle or use the existing one to avoid calling + // storeCache with the same array multiple times + t[id] = t[id] || Util.throttle(function (validateKey, val, onError) { + if (!allowed) { return void onError('NOCACHE'); } + if (!Array.isArray(val) || !validateKey) { return void onError('EINVAL'); } + checkCheckpoints(val); + cache.setItem(id, { + k: validateKey, + c: val, + t: (+new Date()) // 't' represent the "lastAccess" of this cache (get or set) + }, function (err) { + if (err) { onError(err); } + }); + + }, 50); + t[id](validateKey, val, onError); - onReady.reg(function (allowed) { - if (!allowed) { return void cb('NOCACHE'); } - if (!Array.isArray(val) || !validateKey) { return void cb('EINVAL'); } - checkCheckpoints(val); - cache.setItem(id, { - k: validateKey, - c: val, - t: (+new Date()) // 't' represent the "lastAccess" of this cache (get or set) - }, function (err) { - cb(err); - }); }); }; + S.leaveChannel = function (id) { + delete t[id]; + }; + S.clearChannel = function (id, cb) { cb = Util.once(Util.mkAsync(cb || function () {})); diff --git a/www/common/sframe-common-file.js b/www/common/sframe-common-file.js index 7b8601f13..6a0367b69 100644 --- a/www/common/sframe-common-file.js +++ b/www/common/sframe-common-file.js @@ -1,5 +1,6 @@ define([ 'jquery', + '/api/config', '/file/file-crypto.js', '/common/make-backup.js', '/common/common-thumbnail.js', @@ -12,7 +13,7 @@ define([ '/bower_components/file-saver/FileSaver.min.js', '/bower_components/tweetnacl/nacl-fast.min.js', -], function ($, FileCrypto, MakeBackup, Thumb, UI, UIElements, Util, Hash, h, Messages) { +], function ($, ApiConfig, FileCrypto, MakeBackup, Thumb, UI, UIElements, Util, Hash, h, Messages) { var Nacl = window.nacl; var module = {}; @@ -166,8 +167,12 @@ define([ if (config.onError) { config.onError(e); } if (e === 'TOO_LARGE') { - $pv.text(Messages.upload_tooLargeBrief); - return void UI.alert(Messages.upload_tooLarge); + var privateData = common.getMetadataMgr().getPrivateData(); + var l = privateData.plan ? ApiConfig.premiumUploadSize : false; + l = l || ApiConfig.maxUploadSize || '?'; + var maxSizeStr = Util.bytesToMegabytes(l); + $pv.text(Messages.error); + return void UI.alert(Messages._getKey('upload_tooLargeBrief', [maxSizeStr])); } if (e === 'NOT_ENOUGH_SPACE') { $pv.text(Messages.upload_notEnoughSpaceBrief); diff --git a/www/common/sframe-common-outer.js b/www/common/sframe-common-outer.js index 44cbb3e3c..ca760efb8 100644 --- a/www/common/sframe-common-outer.js +++ b/www/common/sframe-common-outer.js @@ -97,6 +97,7 @@ define([ '/common/common-hash.js', '/common/common-util.js', '/common/common-realtime.js', + '/common/notify.js', '/common/common-constants.js', '/common/common-feedback.js', '/common/outer/local-store.js', @@ -105,7 +106,7 @@ define([ '/common/test.js', '/common/userObject.js', ], waitFor(function (_CpNfOuter, _Cryptpad, _Crypto, _Cryptget, _SFrameChannel, - _SecureIframe, _Messaging, _Notifier, _Hash, _Util, _Realtime, + _SecureIframe, _Messaging, _Notifier, _Hash, _Util, _Realtime, _Notify, _Constants, _Feedback, _LocalStore, _Cache, _AppConfig, _Test, _UserObject) { CpNfOuter = _CpNfOuter; Cryptpad = _Cryptpad; @@ -123,6 +124,7 @@ define([ Utils.LocalStore = _LocalStore; Utils.Cache = _Cache; Utils.UserObject = _UserObject; + Utils.Notify = _Notify; Utils.currentPad = currentPad; AppConfig = _AppConfig; Test = _Test; @@ -480,6 +482,7 @@ define([ // We've received a link without /p/ and it doesn't work without a password: abort return void todo(); } + // Wrong password or deleted file? askPassword(true, passwordCfg); })); @@ -534,6 +537,12 @@ define([ var edPublic, curvePublic, notifications, isTemplate; var settings = {}; var isSafe = ['debug', 'profile', 'drive', 'teams'].indexOf(currentPad.app) !== -1; + + var isDeleted = isNewFile && currentPad.hash.length > 0; + if (isDeleted) { + Utils.Cache.clearChannel(secret.channel); + } + var updateMeta = function () { //console.log('EV_METADATA_UPDATE'); var metaObj; @@ -557,6 +566,7 @@ define([ defaultTitle: defaultTitle, type: cfg.type || parsed.type }; + var notifs = Utils.Notify.isSupported() && Utils.Notify.hasPermission(); var additionalPriv = { app: parsed.type, loggedIn: Utils.LocalStore.isLoggedIn(), @@ -571,13 +581,13 @@ define([ isPresent: parsed.hashData && parsed.hashData.present, isEmbed: parsed.hashData && parsed.hashData.embed, isHistoryVersion: parsed.hashData && parsed.hashData.versionHash, - notifications: Notification && Notification.permission === "granted", + notifications: notifs, accounts: { donateURL: Cryptpad.donateURL, upgradeURL: Cryptpad.upgradeURL }, isNewFile: isNewFile, - isDeleted: isNewFile && currentPad.hash.length > 0, + isDeleted: isDeleted, password: password, channel: secret.channel, enableSF: localStorage.CryptPad_SF === "1", // TODO to remove when enabled by default @@ -1598,6 +1608,7 @@ define([ }); sframeChan.on('Q_ASK_NOTIFICATION', function (data, cb) { + if (!Utils.Notify.isSupported()) { return void cb(false); } Notification.requestPermission(function (s) { cb(s === "granted"); }); diff --git a/www/settings/inner.js b/www/settings/inner.js index b4668efff..b4290becb 100644 --- a/www/settings/inner.js +++ b/www/settings/inner.js @@ -593,8 +593,8 @@ define([ var todo = function () { var val = parseInt($input.val()); + if (typeof(val) !== 'number' || isNaN(val)) { return UI.warn(Messages.error); } if (val === oldVal) { return; } - if (typeof(val) !== 'number') { return UI.warn(Messages.error); } spinner.spin(); common.setAttribute(['general', 'mediatag-size'], val, function (err) { if (err) { @@ -602,6 +602,7 @@ define([ console.error(err); return UI.warn(Messages.error); } + oldVal = val; spinner.done(); UI.log(Messages.saved); }); @@ -616,7 +617,7 @@ define([ common.getAttribute(['general', 'mediatag-size'], function(e, val) { if (e) { return void console.error(e); } - if (typeof(val) !== 'number') { + if (typeof(val) !== 'number' || isNaN(val)) { oldVal = 5; $input.val(5); } else { diff --git a/www/teams/inner.js b/www/teams/inner.js index 7af3d7afc..2c37eabf0 100644 --- a/www/teams/inner.js +++ b/www/teams/inner.js @@ -476,7 +476,7 @@ define([ var getWarningBox = function () { return h('div.alert.alert-warning', { role:'alert' - }, isOwner ? Messages.team_maxOwner : Messages._getKey('team_maxTeams', [MAX_TEAMS_SLOTS])); + }, Messages._getKey('team_maxTeams', [MAX_TEAMS_SLOTS])); }; if (Object.keys(privateData.teams || {}).length >= Constants.MAX_TEAMS_SLOTS || isOwner) { diff --git a/www/whiteboard/inner.js b/www/whiteboard/inner.js index 30c43aef1..e0492309f 100644 --- a/www/whiteboard/inner.js +++ b/www/whiteboard/inner.js @@ -332,7 +332,7 @@ define([ }); }; var MAX_IMAGE_SIZE = 1 * 1024 * 1024; // 1 MB - var maxSizeStr = Messages._getKey('formattedMB', [Util.bytesToMegabytes(MAX_IMAGE_SIZE)]); + var maxSizeStr = Util.bytesToMegabytes(MAX_IMAGE_SIZE); var addImageToCanvas = function (img) { if (img.src && img.src.length > MAX_IMAGE_SIZE) { UI.warn(Messages._getKey('upload_tooLargeBrief', [maxSizeStr]));