Merge branch 'staging' into throttle-optimization
commit
e9c28323a7
|
@ -1,7 +1,18 @@
|
|||
// dark #326599
|
||||
// light #4591c4
|
||||
define([], function () {
|
||||
define(['/customize/messages.js'], function (Messages) {
|
||||
var loadingStyle = (function(){/*
|
||||
@font-face {
|
||||
font-family: 'Open Sans';
|
||||
src: url('/bower_components/open-sans-fontface/fonts/Regular/OpenSans-Regular.eot');
|
||||
src: url('/bower_components/open-sans-fontface/fonts/Regular/OpenSans-Regular.eot?#iefix') format('embedded-opentype'),
|
||||
url('/bower_components/open-sans-fontface/fonts/Regular/OpenSans-Regular.woff') format('woff'),
|
||||
url('/bower_components/open-sans-fontface/fonts/Regular/OpenSans-Regular.ttf') format('truetype'),
|
||||
url('/bower_components/open-sans-fontface/fonts/Regular/OpenSans-Regular.svg#OpenSansRegular') format('svg');
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
#cp-loading {
|
||||
visibility: visible;
|
||||
position: fixed;
|
||||
|
@ -19,6 +30,7 @@ define([], function () {
|
|||
flex-flow: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
font: 20px 'Open Sans', 'Helvetica Neue', sans-serif !important;
|
||||
}
|
||||
#cp-loading.cp-loading-hidden {
|
||||
opacity: 0;
|
||||
|
@ -163,35 +175,10 @@ p.cp-password-info{
|
|||
#cp-loading .cp-loading-spinner-container > div {
|
||||
height: 100px;
|
||||
}
|
||||
#cp-loading-tip {
|
||||
position: fixed;
|
||||
z-index: 10000000;
|
||||
top: 80%;
|
||||
left: 0;
|
||||
right: 0;
|
||||
text-align: center;
|
||||
transition: opacity 750ms;
|
||||
transition-delay: 3000ms;
|
||||
}
|
||||
@media screen and (max-height: 600px) {
|
||||
#cp-loading-tip {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
#cp-loading-tip span {
|
||||
background: #222;
|
||||
color: #fafafa;
|
||||
text-align: center;
|
||||
font-size: 1.3em;
|
||||
opacity: 0.7;
|
||||
font-family: 'Open Sans', 'Helvetica Neue', sans-serif;
|
||||
padding: 15px;
|
||||
max-width: 60%;
|
||||
display: inline-block;
|
||||
}
|
||||
.cp-loading-progress {
|
||||
width: 100%;
|
||||
margin: 20px;
|
||||
text-align: center;
|
||||
}
|
||||
.cp-loading-progress p {
|
||||
margin: 5px;
|
||||
|
@ -199,6 +186,31 @@ p.cp-password-info{
|
|||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
.cp-loading-progress-list {
|
||||
text-align: left;
|
||||
display: inline-block;
|
||||
}
|
||||
.cp-loading-progress-list ul {
|
||||
list-style: none;
|
||||
padding-left: 0;
|
||||
}
|
||||
.cp-loading-progress-list li {
|
||||
padding: 0px 5px;
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
}
|
||||
.cp-loading-progress-list li i {
|
||||
width: 22px;
|
||||
}
|
||||
.cp-loading-progress-list li span{
|
||||
margin-left: 10px;
|
||||
}
|
||||
.cp-loading-progress-list li span.percent {
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
.cp-loading-progress-bar {
|
||||
height: 24px;
|
||||
background: white;
|
||||
|
@ -257,10 +269,72 @@ button.primary:hover{
|
|||
'<div class="cp-loading-spinner-container">',
|
||||
'<span class="cp-spinner"></span>',
|
||||
'</div>',
|
||||
'<div class="cp-loading-progress">',
|
||||
'<div class="cp-loading-progress-list"></div>',
|
||||
'<div class="cp-loading-progress-container"></div>',
|
||||
'</div>',
|
||||
'<p id="cp-loading-message"></p>',
|
||||
'</div>'
|
||||
].join('');
|
||||
var built = false;
|
||||
|
||||
var types = ['less', 'drive', 'migrate', 'sf', 'team', 'pad', 'end'];
|
||||
var current;
|
||||
var makeList = function (data) {
|
||||
var c = types.indexOf(data.type);
|
||||
current = c;
|
||||
var getLi = function (i) {
|
||||
var check = (i < c || (i === c && data.progress >= 100)) ? 'fa-check-square-o'
|
||||
: 'fa-square-o';
|
||||
var percentStr = '';
|
||||
if (i === c) {
|
||||
var p = Math.min(Math.floor(data.progress), 100);
|
||||
percentStr = '<span class="percent">('+p+'%)</span>';
|
||||
}
|
||||
return '<li><i class="fa '+check+'"></i><span>'+Messages['loading_state_'+i]+'</span>' + percentStr;
|
||||
};
|
||||
var list = '<ul>';
|
||||
types.forEach(function (el, i) {
|
||||
if (i >= 6) { return; }
|
||||
list += getLi(i);
|
||||
});
|
||||
list += '</ul>';
|
||||
return list;
|
||||
};
|
||||
var makeBar = function (data) {
|
||||
var c = types.indexOf(data.type);
|
||||
var l = types.length;
|
||||
var progress = Math.min(data.progress, 100);
|
||||
var p = (progress / l) + (100 * c / l);
|
||||
var bar = '<div class="cp-loading-progress-bar">'+
|
||||
'<div class="cp-loading-progress-bar-value" style="width:'+p+'%"></div>'+
|
||||
'</div>';
|
||||
return bar;
|
||||
};
|
||||
|
||||
var updateLoadingProgress = function (data) {
|
||||
if (!built) { return; }
|
||||
var c = types.indexOf(data.type);
|
||||
if (c < current) { return console.error(data); }
|
||||
try {
|
||||
document.querySelector('.cp-loading-spinner-container').style.display = 'none';
|
||||
document.querySelector('.cp-loading-progress-list').innerHTML = makeList(data);
|
||||
document.querySelector('.cp-loading-progress-container').innerHTML = makeBar(data);
|
||||
} catch (e) { console.error(e); }
|
||||
};
|
||||
window.CryptPad_updateLoadingProgress = updateLoadingProgress;
|
||||
window.CryptPad_loadingError = function (err) {
|
||||
if (!built) { return; }
|
||||
try {
|
||||
var node = document.querySelector('.cp-loading-progress');
|
||||
if (node.parentNode) { node.parentNode.removeChild(node); }
|
||||
document.querySelector('.cp-loading-spinner-container').setAttribute('style', 'display:none;');
|
||||
document.querySelector('#cp-loading-message').setAttribute('style', 'display:block;');
|
||||
document.querySelector('#cp-loading-message').innerText = err;
|
||||
} catch (e) { console.error(e); }
|
||||
};
|
||||
return function () {
|
||||
built = true;
|
||||
var intr;
|
||||
var append = function () {
|
||||
if (!document.body) { return; }
|
||||
|
|
|
@ -52,13 +52,12 @@ require.config({
|
|||
});
|
||||
|
||||
var req = [
|
||||
'/common/common-util.js',
|
||||
'/customize/application_config.js',
|
||||
'/customize/translations/messages.js'
|
||||
];
|
||||
if (language && map[language]) { req.push('/customize/translations/messages.' + language + '.js'); }
|
||||
|
||||
define(req, function(Util, AppConfig, Default, Language) {
|
||||
define(req, function(AppConfig, Default, Language) {
|
||||
map.en = 'English';
|
||||
var defaultLanguage = 'en';
|
||||
|
||||
|
@ -78,15 +77,15 @@ define(req, function(Util, AppConfig, Default, Language) {
|
|||
|
||||
var extend = function (a, b) {
|
||||
for (var k in b) {
|
||||
if (Util.isObject(b[k])) {
|
||||
a[k] = Util.isObject(a[k]) ? a[k] : {};
|
||||
extend(a[k], b[k]);
|
||||
continue;
|
||||
}
|
||||
if (Array.isArray(b[k])) {
|
||||
a[k] = b[k].slice();
|
||||
continue;
|
||||
}
|
||||
if (b[k] && typeof(b[k]) === "object") {
|
||||
a[k] = (a[k] && typeof(a[k]) === "object" && !Array.isArray(a[k])) ? a[k] : {};
|
||||
extend(a[k], b[k]);
|
||||
continue;
|
||||
}
|
||||
a[k] = b[k] || a[k];
|
||||
}
|
||||
};
|
||||
|
|
|
@ -20,6 +20,22 @@
|
|||
margin: 0 10px;
|
||||
padding: 0;
|
||||
width: ~"calc(100% - 20px)";
|
||||
span.tokenfield-empty {
|
||||
font-size: 14px;
|
||||
font-style: italic;
|
||||
color: lighten(@cryptpad_text_col, 10%);
|
||||
}
|
||||
.cp-tokenfield-container {
|
||||
width: 100%;
|
||||
}
|
||||
.cp-tokenfield-form {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
input {
|
||||
flex: 1;
|
||||
min-width: 0 !important;
|
||||
}
|
||||
}
|
||||
.token {
|
||||
box-sizing: border-box;
|
||||
display: inline-flex;
|
||||
|
|
|
@ -57,9 +57,12 @@ server {
|
|||
add_header Access-Control-Allow-Origin "*";
|
||||
# add_header X-Frame-Options "SAMEORIGIN";
|
||||
|
||||
set $coop '';
|
||||
if ($uri ~ ^\/sheet\/.*$) { set $coop 'same-origin'; }
|
||||
|
||||
# Enable SharedArrayBuffer in Firefox (for .xlsx export)
|
||||
add_header Cross-Origin-Resource-Policy cross-origin;
|
||||
add_header Cross-Origin-Opener-Policy same-origin;
|
||||
add_header Cross-Origin-Opener-Policy $coop;
|
||||
add_header Cross-Origin-Embedder-Policy require-corp;
|
||||
|
||||
# Insert the path to your CryptPad repository root here
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
const Data = module.exports;
|
||||
|
||||
const Meta = require("../metadata");
|
||||
const WriteQueue = require("../write-queue");
|
||||
const Core = require("./core");
|
||||
const Util = require("../common-util");
|
||||
const HK = require("../hk-util");
|
||||
|
@ -53,7 +52,6 @@ Data.getMetadata = function (Env, channel, cb, Server, netfluxId) {
|
|||
value: value
|
||||
}
|
||||
*/
|
||||
var queueMetadata = WriteQueue();
|
||||
Data.setMetadata = function (Env, safeKey, data, cb, Server) {
|
||||
var unsafeKey = Util.unescapeKeyCharacters(safeKey);
|
||||
|
||||
|
@ -63,7 +61,7 @@ Data.setMetadata = function (Env, safeKey, data, cb, Server) {
|
|||
if (!command || typeof (command) !== 'string') { return void cb('INVALID_COMMAND'); }
|
||||
if (Meta.commands.indexOf(command) === -1) { return void cb('UNSUPPORTED_COMMAND'); }
|
||||
|
||||
queueMetadata(channel, function (next) {
|
||||
Env.queueMetadata(channel, function (next) {
|
||||
Data.getMetadataRaw(Env, channel, function (err, metadata) {
|
||||
if (err) {
|
||||
cb(err);
|
||||
|
|
|
@ -162,7 +162,7 @@ Pinning.pinChannel = function (Env, safeKey, channels, cb) {
|
|||
|
||||
// only pin channels which are not already pinned
|
||||
var toStore = channels.filter(function (channel) {
|
||||
return pinned.indexOf(channel) === -1;
|
||||
return channel && pinned.indexOf(channel) === -1;
|
||||
});
|
||||
|
||||
if (toStore.length === 0) {
|
||||
|
@ -204,7 +204,7 @@ Pinning.unpinChannel = function (Env, safeKey, channels, cb) {
|
|||
|
||||
// only unpin channels which are pinned
|
||||
var toStore = channels.filter(function (channel) {
|
||||
return pinned.indexOf(channel) !== -1;
|
||||
return channel && pinned.indexOf(channel) !== -1;
|
||||
});
|
||||
|
||||
if (toStore.length === 0) {
|
||||
|
|
|
@ -48,9 +48,6 @@ Default.httpHeaders = function () {
|
|||
"X-XSS-Protection": "1; mode=block",
|
||||
"X-Content-Type-Options": "nosniff",
|
||||
"Access-Control-Allow-Origin": "*",
|
||||
"Cross-Origin-Resource-Policy": 'cross-origin',
|
||||
"Cross-Origin-Opener-Policy": 'same-origin',
|
||||
"Cross-Origin-Embedder-Policy": 'require-corp',
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -45,6 +45,7 @@ module.exports.create = function (config) {
|
|||
queueStorage: WriteQueue(),
|
||||
queueDeletes: WriteQueue(),
|
||||
queueValidation: WriteQueue(),
|
||||
queueMetadata: WriteQueue(),
|
||||
|
||||
batchIndexReads: BatchRead("HK_GET_INDEX"),
|
||||
batchMetadata: BatchRead('GET_METADATA'),
|
||||
|
|
|
@ -80,6 +80,10 @@ module.exports.create = function (Env, cb) {
|
|||
return void cb();
|
||||
}
|
||||
|
||||
// If the channel is restricted, send the history keeper ID so that they
|
||||
// can try to authenticate
|
||||
allowed.unshift(Env.id);
|
||||
|
||||
// otherwise they're not allowed.
|
||||
// respond with a special error that includes the list of keys
|
||||
// which would be allowed...
|
||||
|
|
16
server.js
16
server.js
|
@ -60,6 +60,10 @@ var app = Express();
|
|||
}
|
||||
}());
|
||||
|
||||
var applyHeaderMap = function (res, map) {
|
||||
for (let header in map) { res.setHeader(header, map[header]); }
|
||||
};
|
||||
|
||||
var setHeaders = (function () {
|
||||
// load the default http headers unless the admin has provided their own via the config file
|
||||
var headers;
|
||||
|
@ -96,14 +100,21 @@ var setHeaders = (function () {
|
|||
}
|
||||
if (Object.keys(headers).length) {
|
||||
return function (req, res) {
|
||||
// apply a bunch of cross-origin headers for XLSX export in FF and printing elsewhere
|
||||
applyHeaderMap(res, {
|
||||
"Cross-Origin-Resource-Policy": 'cross-origin',
|
||||
"Cross-Origin-Opener-Policy": /^\/sheet\//.test(req.url)? 'same-origin': '',
|
||||
"Cross-Origin-Embedder-Policy": 'require-corp',
|
||||
});
|
||||
|
||||
// targeted CSP, generic policies, maybe custom headers
|
||||
const h = [
|
||||
///^\/pad\/inner\.html.*/,
|
||||
/^\/common\/onlyoffice\/.*\/index\.html.*/,
|
||||
/^\/(sheet|ooslide|oodoc)\/inner\.html.*/,
|
||||
].some((regex) => {
|
||||
return regex.test(req.url);
|
||||
}) ? padHeaders : headers;
|
||||
for (let header in h) { res.setHeader(header, h[header]); }
|
||||
applyHeaderMap(res, h);
|
||||
};
|
||||
}
|
||||
return function () {};
|
||||
|
@ -139,6 +150,7 @@ app.use(function (req, res, next) {
|
|||
|
||||
setHeaders(req, res);
|
||||
if (/[\?\&]ver=[^\/]+$/.test(req.url)) { res.setHeader("Cache-Control", "max-age=31536000"); }
|
||||
else { res.setHeader("Cache-Control", "no-cache"); }
|
||||
next();
|
||||
});
|
||||
|
||||
|
|
|
@ -150,6 +150,7 @@ define([
|
|||
}).nThen(function () { cb(); });
|
||||
};
|
||||
|
||||
var idx = 0;
|
||||
module.exports.load = function (url /*:string*/, cb /*:()=>void*/, stack /*:?Array<string>*/) {
|
||||
var btime = stack ? null : +new Date();
|
||||
stack = stack || [];
|
||||
|
@ -163,11 +164,22 @@ define([
|
|||
cb();
|
||||
};
|
||||
stack.push(url);
|
||||
if (window.CryptPad_updateLoadingProgress) {
|
||||
window.CryptPad_updateLoadingProgress({
|
||||
type: 'less',
|
||||
progress: 4*idx++
|
||||
});
|
||||
}
|
||||
cacheGet(url, function (css) {
|
||||
if (css) { return void loadSubmodulesAndInject(css, url, done, stack); }
|
||||
console.debug('CACHE MISS ' + url);
|
||||
((/\.less([\?\#].*)?$/.test(url)) ? loadLess : loadCSS)(url, function (err, css) {
|
||||
if (!css) { return void console.error(err); }
|
||||
if (!css) {
|
||||
if (window.CryptPad_loadingError) {
|
||||
window.CryptPad_loadingError('LESS: ' + (err && err.message));
|
||||
}
|
||||
return void console.error(err);
|
||||
}
|
||||
var output = fixAllURLs(css, url);
|
||||
cachePut(url, output);
|
||||
loadSubmodulesAndInject(output, url, done, stack);
|
||||
|
|
|
@ -280,8 +280,82 @@ define([
|
|||
};
|
||||
|
||||
var $root = $t.parent();
|
||||
|
||||
Messages.add = "Add"; // XXX
|
||||
Messages.edit = "Edit"; // XXX
|
||||
var $input = $root.find('.token-input');
|
||||
var $button = $(h('button.btn.btn-primary', [
|
||||
h('i.fa.fa-plus'),
|
||||
h('span', Messages.add)
|
||||
]));
|
||||
|
||||
|
||||
$button.click(function () {
|
||||
$t.tokenfield('createToken', $input.val());
|
||||
});
|
||||
|
||||
var $container = $(h('span.cp-tokenfield-container'));
|
||||
var $form = $(h('span.cp-tokenfield-form'));
|
||||
$container.insertAfter($input);
|
||||
|
||||
// Fix the UI to keep the "add" or "edit" button at the correct location
|
||||
var isEdit = false;
|
||||
var called = false;
|
||||
var resetUI = function () {
|
||||
called = true;
|
||||
setTimeout(function () {
|
||||
$container.find('.tokenfield-empty').remove();
|
||||
var $tokens = $root.find('.token').prependTo($container);
|
||||
if (!$tokens.length) {
|
||||
$container.prepend(h('span.tokenfield-empty', Messages.kanban_noTags));
|
||||
}
|
||||
$form.append($input);
|
||||
$form.append($button);
|
||||
if (isEdit) { $button.find('span').text(Messages.edit); }
|
||||
else { $button.find('span').text(Messages.add); }
|
||||
$container.append($form);
|
||||
$input.focus();
|
||||
isEdit = false;
|
||||
called = false;
|
||||
});
|
||||
};
|
||||
resetUI();
|
||||
|
||||
$t.on('tokenfield:removedtoken', function () {
|
||||
resetUI();
|
||||
});
|
||||
$t.on('tokenfield:editedtoken', function () {
|
||||
resetUI();
|
||||
});
|
||||
$t.on('tokenfield:createdtoken', function () {
|
||||
$input.val('');
|
||||
resetUI();
|
||||
});
|
||||
$t.on('tokenfield:edittoken', function () {
|
||||
isEdit = true;
|
||||
});
|
||||
|
||||
// Fix UI issue where the input could go outside of the container
|
||||
var MutationObserver = window.MutationObserver;
|
||||
var observer = new MutationObserver(function(mutations) {
|
||||
if (called) { return; }
|
||||
mutations.forEach(function(mutation) {
|
||||
for (var i = 0; i < mutation.addedNodes.length; i++) {
|
||||
if (mutation.addedNodes[i].classList &&
|
||||
mutation.addedNodes[i].classList.contains('token-input')) {
|
||||
resetUI();
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
observer.observe($root[0], {
|
||||
childList: true,
|
||||
subtree: false
|
||||
});
|
||||
|
||||
$t.on('tokenfield:removetoken', function () {
|
||||
$root.find('.token-input').focus();
|
||||
$input.focus();
|
||||
});
|
||||
|
||||
t.preventDuplicates = function (cb) {
|
||||
|
@ -858,35 +932,33 @@ define([
|
|||
|
||||
var LOADING = 'cp-loading';
|
||||
|
||||
var loading = {
|
||||
error: false,
|
||||
driveState: 0,
|
||||
padState: 0
|
||||
};
|
||||
UI.addLoadingScreen = function (config) {
|
||||
config = config || {};
|
||||
var loadingText = config.loadingText;
|
||||
var todo = function () {
|
||||
var $loading = $('#' + LOADING);
|
||||
// Show the loading screen
|
||||
$loading.css('display', '');
|
||||
$loading.removeClass('cp-loading-hidden');
|
||||
$('.cp-loading-spinner-container').show();
|
||||
if (!config.noProgress && !$loading.find('.cp-loading-progress').length) {
|
||||
if (config.newProgress) {
|
||||
// XXX re-add progress bar for step 6 after password prompt for PPP
|
||||
// XXX also burn after reading
|
||||
var progress = h('div.cp-loading-progress', [
|
||||
h('p.cp-loading-progress-drive'),
|
||||
h('p.cp-loading-progress-pad')
|
||||
h('p.cp-loading-progress-list'),
|
||||
h('p.cp-loading-progress-container')
|
||||
]);
|
||||
$(progress).hide();
|
||||
$loading.find('.cp-loading-container').append(progress);
|
||||
} else if (config.noProgress) {
|
||||
$loading.find('.cp-loading-progress').remove();
|
||||
$loading.find('.cp-loading-spinner-container').after(progress);
|
||||
}
|
||||
if (!$loading.find('.cp-loading-progress').length) {
|
||||
// Add spinner
|
||||
$('.cp-loading-spinner-container').show();
|
||||
}
|
||||
// Add loading text
|
||||
if (loadingText) {
|
||||
$('#' + LOADING).find('#cp-loading-message').show().text(loadingText);
|
||||
} else {
|
||||
$('#' + LOADING).find('#cp-loading-message').hide().text('');
|
||||
}
|
||||
loading.error = false;
|
||||
};
|
||||
if ($('#' + LOADING).length) {
|
||||
todo();
|
||||
|
@ -895,57 +967,9 @@ define([
|
|||
todo();
|
||||
}
|
||||
};
|
||||
UI.updateLoadingProgress = function (data, isDrive) {
|
||||
var $loading = $('#' + LOADING);
|
||||
if (!$loading.length || loading.error) { return; }
|
||||
$loading.find('.cp-loading-progress').show();
|
||||
var $progress;
|
||||
if (isDrive) {
|
||||
// Drive state
|
||||
if (loading.driveState === -1) { return; } // Already loaded
|
||||
$progress = $loading.find('.cp-loading-progress-drive');
|
||||
if (!$progress.length) { return; } // Can't find the box to display data
|
||||
|
||||
// If state is -1, remove the box, drive is loaded
|
||||
if (data.state === -1) {
|
||||
loading.driveState = -1;
|
||||
$progress.remove();
|
||||
} else {
|
||||
if (data.state < loading.driveState) { return; } // We should not display old data
|
||||
// Update the current state
|
||||
loading.driveState = data.state;
|
||||
data.progress = data.progress || 100;
|
||||
data.msg = Messages['loading_drive_'+ Math.floor(data.state)] || '';
|
||||
$progress.html(data.msg);
|
||||
if (data.progress) {
|
||||
$progress.append(h('div.cp-loading-progress-bar', [
|
||||
h('div.cp-loading-progress-bar-value', {style: 'width:'+data.progress+'%;'})
|
||||
]));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Pad state
|
||||
if (loading.padState === -1) { return; } // Already loaded
|
||||
$progress = $loading.find('.cp-loading-progress-pad');
|
||||
if (!$progress.length) { return; } // Can't find the box to display data
|
||||
|
||||
// If state is -1, remove the box, pad is loaded
|
||||
if (data.state === -1) {
|
||||
loading.padState = -1;
|
||||
$progress.remove();
|
||||
} else {
|
||||
if (data.state < loading.padState) { return; } // We should not display old data
|
||||
// Update the current state
|
||||
loading.padState = data.state;
|
||||
data.progress = data.progress || 100;
|
||||
data.msg = Messages['loading_pad_'+data.state] || '';
|
||||
$progress.html(data.msg);
|
||||
if (data.progress) {
|
||||
$progress.append(h('div.cp-loading-progress-bar', [
|
||||
h('div.cp-loading-progress-bar-value', {style: 'width:'+data.progress+'%;'})
|
||||
]));
|
||||
}
|
||||
}
|
||||
UI.updateLoadingProgress = function (data) {
|
||||
if (window.CryptPad_updateLoadingProgress) {
|
||||
window.CryptPad_updateLoadingProgress(data);
|
||||
}
|
||||
};
|
||||
UI.removeLoadingScreen = function (cb) {
|
||||
|
@ -954,31 +978,23 @@ define([
|
|||
cb = cb || function () {};
|
||||
if (Test.__ASYNC_BLOCKER__) { Test.__ASYNC_BLOCKER__.pass(); }
|
||||
|
||||
$('#' + LOADING).addClass("cp-loading-hidden");
|
||||
var $loading = $('#' + LOADING);
|
||||
$loading.addClass("cp-loading-hidden"); // Hide the loading screen
|
||||
$loading.find('.cp-loading-progress').remove(); // Remove the progress list
|
||||
setTimeout(cb, 750);
|
||||
loading.error = false;
|
||||
var $tip = $('#cp-loading-tip').css('top', '')
|
||||
// loading.less sets transition-delay: $wait-time
|
||||
// and transition: opacity $fadeout-time
|
||||
.css({
|
||||
'opacity': 0,
|
||||
'pointer-events': 'none',
|
||||
});
|
||||
window.setTimeout(function () {
|
||||
$tip.remove();
|
||||
}, 3750);
|
||||
// jquery.fadeout can get stuck
|
||||
};
|
||||
UI.errorLoadingScreen = function (error, transparent, exitable) {
|
||||
var $loading = $('#' + LOADING);
|
||||
if (!$loading.is(':visible') || $loading.hasClass('cp-loading-hidden')) {
|
||||
UI.addLoadingScreen({hideTips: true});
|
||||
UI.addLoadingScreen();
|
||||
}
|
||||
loading.error = true;
|
||||
// Remove the progress list
|
||||
$loading.find('.cp-loading-progress').remove();
|
||||
// Hide the spinner
|
||||
$('.cp-loading-spinner-container').hide();
|
||||
$('#cp-loading-tip').remove();
|
||||
if (transparent) { $loading.css('opacity', 0.9); }
|
||||
|
||||
// Add the error message
|
||||
var $error = $loading.find('#cp-loading-message').show();
|
||||
if (error instanceof Element) {
|
||||
$error.html('').append(error);
|
||||
|
@ -990,7 +1006,6 @@ define([
|
|||
$(window).keydown(function (e) {
|
||||
if (e.which === 27) {
|
||||
$loading.hide();
|
||||
loading.error = false;
|
||||
if (typeof(exitable) === "function") { exitable(); }
|
||||
}
|
||||
});
|
||||
|
|
|
@ -2531,10 +2531,16 @@ define([
|
|||
|
||||
var submit = function () {
|
||||
var value = $password.find('.cp-password-input').val();
|
||||
UI.addLoadingScreen();
|
||||
UI.addLoadingScreen({newProgress: true});
|
||||
if (window.CryptPad_updateLoadingProgress) {
|
||||
window.CryptPad_updateLoadingProgress({
|
||||
type: 'pad',
|
||||
progress: 0
|
||||
});
|
||||
}
|
||||
common.getSframeChannel().query('Q_PAD_PASSWORD_VALUE', value, function (err, data) {
|
||||
if (!data) {
|
||||
UIElements.displayPasswordPrompt(common, cfg, true);
|
||||
return void UIElements.displayPasswordPrompt(common, cfg, true);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
|
|
@ -1,12 +1,15 @@
|
|||
define([
|
||||
'/bower_components/chainpad-crypto/crypto.js',
|
||||
'/bower_components/chainpad-netflux/chainpad-netflux.js',
|
||||
'/bower_components/netflux-websocket/netflux-client.js',
|
||||
'/common/common-util.js',
|
||||
'/common/common-hash.js',
|
||||
'/common/common-realtime.js',
|
||||
'/common/outer/network-config.js',
|
||||
'/common/pinpad.js',
|
||||
'/bower_components/nthen/index.js',
|
||||
'/bower_components/chainpad/chainpad.dist.js',
|
||||
], function (Crypto, CPNetflux, Util, Hash, Realtime, NetConfig) {
|
||||
], function (Crypto, CPNetflux, Netflux, Util, Hash, Realtime, NetConfig, Pinpad, nThen) {
|
||||
var finish = function (S, err, doc) {
|
||||
if (S.done) { return; }
|
||||
S.cb(err, doc);
|
||||
|
@ -28,6 +31,50 @@ define([
|
|||
}
|
||||
};
|
||||
|
||||
var makeNetwork = function (cb) {
|
||||
var wsUrl = NetConfig.getWebsocketURL();
|
||||
Netflux.connect(wsUrl).then(function (network) {
|
||||
cb(null, network);
|
||||
}, function (err) {
|
||||
cb(err);
|
||||
});
|
||||
};
|
||||
|
||||
var start = function (Session, config) {
|
||||
// Create a network and authenticate with all our keys if necessary,
|
||||
// then start chainpad-netflux
|
||||
nThen(function (waitFor) {
|
||||
if (Session.hasNetwork) { return; }
|
||||
makeNetwork(waitFor(function (err, network) {
|
||||
if (err) { return; }
|
||||
config.network = network;
|
||||
}));
|
||||
}).nThen(function () {
|
||||
Session.realtime = CPNetflux.start(config);
|
||||
});
|
||||
};
|
||||
|
||||
var onRejected = function (config, Session, data, cb) {
|
||||
// Check if we can authenticate
|
||||
if (!Array.isArray(data) || !data.length || data[0].length !== 16) {
|
||||
return void cb(true);
|
||||
}
|
||||
if (!Array.isArray(Session.accessKeys)) { return void cb(true); }
|
||||
|
||||
// Authenticate
|
||||
config.network.historyKeeper = data[0];
|
||||
nThen(function (waitFor) {
|
||||
Session.accessKeys.forEach(function (obj) {
|
||||
Pinpad.create(config.network, obj, waitFor(function (e) {
|
||||
console.log('done', obj);
|
||||
if (e) { console.error(e); }
|
||||
}));
|
||||
});
|
||||
}).nThen(function () {
|
||||
cb();
|
||||
});
|
||||
};
|
||||
|
||||
var makeConfig = function (hash, opt) {
|
||||
var secret;
|
||||
if (typeof(hash) === 'string') {
|
||||
|
@ -67,7 +114,15 @@ define([
|
|||
progress = progress || function () {};
|
||||
|
||||
var config = makeConfig(hash, opt);
|
||||
var Session = { cb: cb, hasNetwork: Boolean(opt.network) };
|
||||
var Session = {
|
||||
cb: cb,
|
||||
accessKeys: opt.accessKeys,
|
||||
hasNetwork: Boolean(opt.network)
|
||||
};
|
||||
|
||||
config.onRejected = function (data, cb) {
|
||||
onRejected(config, Session, data, cb);
|
||||
};
|
||||
|
||||
config.onReady = function (info) {
|
||||
var rt = Session.session = info.realtime;
|
||||
|
@ -95,7 +150,7 @@ define([
|
|||
|
||||
overwrite(config, opt);
|
||||
|
||||
Session.realtime = CPNetflux.start(config);
|
||||
start(Session, config);
|
||||
};
|
||||
|
||||
var put = function (hash, doc, cb, opt) {
|
||||
|
@ -105,7 +160,15 @@ define([
|
|||
opt = opt || {};
|
||||
|
||||
var config = makeConfig(hash, opt);
|
||||
var Session = { cb: cb, hasNetwork: Boolean(opt.network) };
|
||||
var Session = {
|
||||
cb: cb,
|
||||
accessKeys: opt.accessKeys,
|
||||
hasNetwork: Boolean(opt.network)
|
||||
};
|
||||
|
||||
config.onRejected = function (data, cb) {
|
||||
onRejected(config, Session, data, cb);
|
||||
};
|
||||
|
||||
config.onReady = function (info) {
|
||||
var realtime = Session.session = info.realtime;
|
||||
|
@ -126,7 +189,7 @@ define([
|
|||
};
|
||||
overwrite(config, opt);
|
||||
|
||||
Session.session = CPNetflux.start(config);
|
||||
start(Session, config);
|
||||
};
|
||||
|
||||
return {
|
||||
|
|
|
@ -68,6 +68,38 @@ define([
|
|||
}, cb);
|
||||
};
|
||||
|
||||
common.getAccessKeys = function (cb) {
|
||||
var keys = [];
|
||||
Nthen(function (waitFor) {
|
||||
// Push account keys
|
||||
postMessage("GET", {
|
||||
key: ['edPrivate'],
|
||||
}, waitFor(function (obj) {
|
||||
if (obj.error) { return; }
|
||||
try {
|
||||
keys.push({
|
||||
edPrivate: obj,
|
||||
edPublic: Hash.getSignPublicFromPrivate(obj)
|
||||
});
|
||||
} catch (e) { console.error(e); }
|
||||
}));
|
||||
// Push teams keys
|
||||
postMessage("GET", {
|
||||
key: ['teams'],
|
||||
}, waitFor(function (obj) {
|
||||
if (obj.error) { return; }
|
||||
Object.keys(obj || {}).forEach(function (id) {
|
||||
var t = obj[id];
|
||||
var _keys = t.keys.drive || {};
|
||||
if (!_keys.edPrivate) { return; }
|
||||
keys.push(t.keys.drive);
|
||||
});
|
||||
}));
|
||||
}).nThen(function () {
|
||||
cb(keys);
|
||||
});
|
||||
};
|
||||
|
||||
common.makeNetwork = function (cb) {
|
||||
require([
|
||||
'/bower_components/netflux-websocket/netflux-client.js',
|
||||
|
@ -629,6 +661,10 @@ define([
|
|||
optsPut.password = password;
|
||||
}));
|
||||
}
|
||||
common.getAccessKeys(waitFor(function (keys) {
|
||||
optsGet.accessKeys = keys;
|
||||
optsPut.accessKeys = keys;
|
||||
}));
|
||||
}).nThen(function () {
|
||||
Crypt.get(parsed.hash, function (err, val) {
|
||||
if (err) {
|
||||
|
@ -666,19 +702,28 @@ define([
|
|||
password: data.password,
|
||||
initialState: parsed.type === 'poll' ? '{}' : undefined
|
||||
};
|
||||
Crypt.get(parsed.hash, _waitFor(function (err, _val) {
|
||||
if (err) {
|
||||
_waitFor.abort();
|
||||
return void cb(err);
|
||||
}
|
||||
try {
|
||||
val = JSON.parse(_val);
|
||||
fixPadMetadata(val, true);
|
||||
} catch (e) {
|
||||
_waitFor.abort();
|
||||
return void cb(e.message);
|
||||
}
|
||||
}), optsGet);
|
||||
var next = _waitFor();
|
||||
Nthen(function (waitFor) {
|
||||
// Authenticate in case the pad os restricted
|
||||
common.getAccessKeys(waitFor(function (keys) {
|
||||
optsGet.accessKeys = keys;
|
||||
}));
|
||||
}).nThen(function () {
|
||||
Crypt.get(parsed.hash, function (err, _val) {
|
||||
if (err) {
|
||||
_waitFor.abort();
|
||||
return void cb(err);
|
||||
}
|
||||
try {
|
||||
val = JSON.parse(_val);
|
||||
fixPadMetadata(val, true);
|
||||
next();
|
||||
} catch (e) {
|
||||
_waitFor.abort();
|
||||
return void cb(e.message);
|
||||
}
|
||||
}, optsGet);
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -741,9 +786,6 @@ define([
|
|||
}).nThen(function () {
|
||||
Crypt.put(parsed2.hash, JSON.stringify(val), function () {
|
||||
cb();
|
||||
Crypt.get(parsed2.hash, function (err, val) {
|
||||
console.warn(val);
|
||||
});
|
||||
}, optsPut);
|
||||
});
|
||||
|
||||
|
@ -1006,7 +1048,7 @@ define([
|
|||
oldSecret = Hash.getSecrets(parsed.type, parsed.hash, optsGet.password);
|
||||
oldChannel = oldSecret.channel;
|
||||
common.getPadMetadata({channel: oldChannel}, waitFor(function (metadata) {
|
||||
oldMetadata = metadata;
|
||||
oldMetadata = metadata || {};
|
||||
}));
|
||||
common.getMetadata(waitFor(function (err, data) {
|
||||
if (err) {
|
||||
|
@ -1058,6 +1100,11 @@ define([
|
|||
if (expire) {
|
||||
optsPut.metadata.expire = (expire - (+new Date())) / 1000; // Lifetime in seconds
|
||||
}
|
||||
}).nThen(function (waitFor) {
|
||||
common.getAccessKeys(waitFor(function (keys) {
|
||||
optsGet.accessKeys = keys;
|
||||
optsPut.accessKeys = keys;
|
||||
}));
|
||||
}).nThen(function (waitFor) {
|
||||
Crypt.get(parsed.hash, waitFor(function (err, val) {
|
||||
if (err) {
|
||||
|
@ -1074,6 +1121,8 @@ define([
|
|||
}
|
||||
}), optsGet);
|
||||
}).nThen(function (waitFor) {
|
||||
optsPut.metadata.restricted = oldMetadata.restricted;
|
||||
optsPut.metadata.allowed = oldMetadata.allowed;
|
||||
Crypt.put(newHash, cryptgetVal, waitFor(function (err) {
|
||||
if (err) {
|
||||
waitFor.abort();
|
||||
|
@ -1309,11 +1358,17 @@ define([
|
|||
validateKey: newSecret.keys.validateKey
|
||||
},
|
||||
};
|
||||
var optsGet = {};
|
||||
|
||||
Nthen(function (waitFor) {
|
||||
common.getPadAttribute('', waitFor(function (err, _data) {
|
||||
padData = _data;
|
||||
optsGet.password = padData.password;
|
||||
}), href);
|
||||
common.getAccessKeys(waitFor(function (keys) {
|
||||
optsGet.accessKeys = keys;
|
||||
optsPut.accessKeys = keys;
|
||||
}));
|
||||
}).nThen(function (waitFor) {
|
||||
oldSecret = Hash.getSecrets(parsed.type, parsed.hash, padData.password);
|
||||
|
||||
|
@ -1392,9 +1447,7 @@ define([
|
|||
waitFor.abort();
|
||||
return void cb({ error: 'CANT_PARSE' });
|
||||
}
|
||||
}), {
|
||||
password: padData.password
|
||||
});
|
||||
}), optsGet);
|
||||
}).nThen(function (waitFor) {
|
||||
// Re-encrypt rtchannel
|
||||
oldRtChannel = Util.find(cryptgetVal, ['content', 'channel']);
|
||||
|
|
|
@ -4549,6 +4549,9 @@ define([
|
|||
var rEl = manager.find(restorePath);
|
||||
if (manager.isFile(rEl)) {
|
||||
restoreName = manager.getTitle(rEl);
|
||||
} else if (manager.isSharedFolder(rEl)) {
|
||||
var sfData = manager.getSharedFolderData(rEl);
|
||||
restoreName = sfData.title || sfData.lastTitle || Messages.fm_deletedFolder;
|
||||
} else {
|
||||
restoreName = restorePath[1];
|
||||
}
|
||||
|
|
|
@ -1080,6 +1080,11 @@ define([
|
|||
if (data.teamId && s.id !== data.teamId) { return; }
|
||||
if (storeLocally && s.id) { return; }
|
||||
|
||||
// If this is an edit link but we don't have edit rights, this entry is not useful
|
||||
if (h.mode === "edit" && s.id && !s.secondaryKey) {
|
||||
return;
|
||||
}
|
||||
|
||||
var res = s.manager.findChannel(channel, true);
|
||||
if (res.length) {
|
||||
sendTo.push(s.id);
|
||||
|
@ -1373,11 +1378,15 @@ define([
|
|||
}
|
||||
}
|
||||
};
|
||||
var loadUniversal = function (Module, type, waitFor) {
|
||||
var loadUniversal = function (Module, type, waitFor, clientId) {
|
||||
if (store.modules[type]) { return; }
|
||||
store.modules[type] = Module.init({
|
||||
Store: Store,
|
||||
store: store,
|
||||
updateLoadingProgress: function (data) {
|
||||
data.type = "team";
|
||||
postMessage(clientId, 'LOADING_DRIVE', data);
|
||||
},
|
||||
updateMetadata: function () {
|
||||
broadcast([], "UPDATE_METADATA");
|
||||
},
|
||||
|
@ -2480,32 +2489,40 @@ define([
|
|||
addSharedFolderHandler();
|
||||
|
||||
nThen(function (waitFor) {
|
||||
postMessage(clientId, 'LOADING_DRIVE', {
|
||||
state: 2
|
||||
});
|
||||
userObject.migrate(waitFor());
|
||||
}).nThen(function (waitFor) {
|
||||
initAnonRpc(null, null, waitFor());
|
||||
initRpc(null, null, waitFor());
|
||||
postMessage(clientId, 'LOADING_DRIVE', {
|
||||
type: 'migrate',
|
||||
progress: 0
|
||||
});
|
||||
}).nThen(function (waitFor) {
|
||||
Migrate(proxy, waitFor(), function (version, progress) {
|
||||
postMessage(clientId, 'LOADING_DRIVE', {
|
||||
state: (2 + (version / 10)),
|
||||
type: 'migrate',
|
||||
progress: progress
|
||||
});
|
||||
}, store);
|
||||
}).nThen(function (waitFor) {
|
||||
postMessage(clientId, 'LOADING_DRIVE', {
|
||||
state: 3
|
||||
type: 'sf',
|
||||
progress: 0
|
||||
});
|
||||
userObject.fixFiles();
|
||||
SF.loadSharedFolders(Store, store.network, store, userObject, waitFor);
|
||||
SF.loadSharedFolders(Store, store.network, store, userObject, waitFor, function (obj) {
|
||||
var data = {
|
||||
type: 'sf',
|
||||
progress: 100*obj.progress/obj.max
|
||||
};
|
||||
postMessage(clientId, 'LOADING_DRIVE', data);
|
||||
});
|
||||
loadCursor();
|
||||
loadOnlyOffice();
|
||||
loadUniversal(Messenger, 'messenger', waitFor);
|
||||
store.messenger = store.modules['messenger'];
|
||||
loadUniversal(Profile, 'profile', waitFor);
|
||||
loadUniversal(Team, 'team', waitFor);
|
||||
loadUniversal(Team, 'team', waitFor, clientId);
|
||||
loadUniversal(History, 'history', waitFor);
|
||||
cleanFriendRequests();
|
||||
}).nThen(function () {
|
||||
|
@ -2607,6 +2624,12 @@ define([
|
|||
if (!hash) {
|
||||
return void cb({error: '[Store.init] Unable to find or create a drive hash. Aborting...'});
|
||||
}
|
||||
|
||||
var updateProgress = function (data) {
|
||||
data.type = 'drive';
|
||||
postMessage(clientId, 'LOADING_DRIVE', data);
|
||||
};
|
||||
|
||||
// No password for drive
|
||||
var secret = Hash.getSecrets('drive', hash);
|
||||
store.driveChannel = secret.channel;
|
||||
|
@ -2620,6 +2643,7 @@ define([
|
|||
userName: 'fs',
|
||||
logLevel: 1,
|
||||
ChainPad: ChainPad,
|
||||
updateProgress: updateProgress,
|
||||
classic: true,
|
||||
};
|
||||
var rt = window.rt = Listmap.create(listmapConfig);
|
||||
|
@ -2643,7 +2667,6 @@ define([
|
|||
&& !drive['filesData']) {
|
||||
drive[Constants.oldStorageKey] = [];
|
||||
}
|
||||
postMessage(clientId, 'LOADING_DRIVE', { state: 1 });
|
||||
// Drive already exist: return the existing drive, don't load data from legacy store
|
||||
onReady(clientId, returned, cb);
|
||||
})
|
||||
|
|
|
@ -320,9 +320,12 @@ define([
|
|||
- userObject: userObject associated to the main drive
|
||||
- handler: a function (sfid, rt) called for each shared folder loaded
|
||||
*/
|
||||
SF.loadSharedFolders = function (Store, network, store, userObject, waitFor) {
|
||||
SF.loadSharedFolders = function (Store, network, store, userObject, waitFor, progress) {
|
||||
var shared = Util.find(store.proxy, ['drive', UserObject.SHARED_FOLDERS]) || {};
|
||||
var steps = Object.keys(shared).length;
|
||||
var i = 1;
|
||||
var w = waitFor();
|
||||
progress = progress || function () {};
|
||||
nThen(function (waitFor) {
|
||||
Object.keys(shared).forEach(function (id) {
|
||||
var sf = shared[id];
|
||||
|
@ -330,7 +333,13 @@ define([
|
|||
network: network,
|
||||
store: store,
|
||||
isNewChannel: Store.isNewChannel
|
||||
}, id, sf, waitFor());
|
||||
}, id, sf, waitFor(function () {
|
||||
progress({
|
||||
progress: i,
|
||||
max: steps
|
||||
});
|
||||
i++;
|
||||
}));
|
||||
});
|
||||
}).nThen(function () {
|
||||
setTimeout(w);
|
||||
|
|
|
@ -328,7 +328,13 @@ define([
|
|||
ctx.teams[id] = team;
|
||||
registerChangeEvents(ctx, team, proxy);
|
||||
SF.checkMigration(team.secondaryKey, proxy, team.userObject, waitFor());
|
||||
SF.loadSharedFolders(ctx.Store, ctx.store.network, team, team.userObject, waitFor);
|
||||
SF.loadSharedFolders(ctx.Store, ctx.store.network, team,
|
||||
team.userObject, waitFor, function (data) {
|
||||
ctx.progress += 70/(ctx.numberOfTeams * data.max);
|
||||
ctx.updateProgress({
|
||||
progress: ctx.progress
|
||||
});
|
||||
});
|
||||
}).nThen(function () {
|
||||
if (!team.rpc) { return; }
|
||||
var list = getTeamChannelList(ctx, id);
|
||||
|
@ -361,6 +367,9 @@ define([
|
|||
|
||||
};
|
||||
|
||||
// Progress:
|
||||
// One team = (30/(#teams))%
|
||||
// One shared folder = (70/(#teams * #folders))%
|
||||
var openChannel = function (ctx, teamData, id, _cb) {
|
||||
var cb = Util.once(Util.mkAsync(_cb));
|
||||
|
||||
|
@ -526,6 +535,10 @@ define([
|
|||
Feedback.send("TEAM_RIGHTS_OWNER");
|
||||
}
|
||||
}).nThen(function () {
|
||||
ctx.progress += 30/ctx.numberOfTeams;
|
||||
ctx.updateProgress({
|
||||
progress: ctx.progress
|
||||
});
|
||||
onReady(ctx, id, lm, roster, keys, null, cb);
|
||||
});
|
||||
};
|
||||
|
@ -1686,10 +1699,13 @@ define([
|
|||
emit: emit,
|
||||
onReadyHandlers: {},
|
||||
teams: {},
|
||||
updateMetadata: cfg.updateMetadata
|
||||
updateMetadata: cfg.updateMetadata,
|
||||
updateProgress: cfg.updateLoadingProgress,
|
||||
progress: 0
|
||||
};
|
||||
|
||||
var teams = store.proxy.teams = store.proxy.teams || {};
|
||||
ctx.numberOfTeams = Object.keys(teams).length;
|
||||
|
||||
// Listen for changes in our access rights (if another worker receives edit access)
|
||||
ctx.store.proxy.on('change', ['teams'], function (o, n, p) {
|
||||
|
|
|
@ -441,9 +441,9 @@ define([
|
|||
var versionHashEl;
|
||||
var onInit = function () {
|
||||
UI.updateLoadingProgress({
|
||||
state: 2,
|
||||
type: 'pad',
|
||||
progress: 0.1
|
||||
}, false);
|
||||
});
|
||||
stateChange(STATE.INITIALIZING);
|
||||
if ($('.cp-help-container').length) {
|
||||
var privateDat = cpNfInner.metadataMgr.getPrivateData();
|
||||
|
@ -471,8 +471,6 @@ define([
|
|||
var newContentStr = cpNfInner.chainpad.getUserDoc();
|
||||
if (state === STATE.DELETED) { return; }
|
||||
|
||||
UI.updateLoadingProgress({ state: -1 }, false);
|
||||
|
||||
if (toolbar) {
|
||||
// Check if we have a new chainpad instance
|
||||
toolbar.resetChainpad(cpNfInner.chainpad);
|
||||
|
@ -708,9 +706,6 @@ define([
|
|||
nThen(function (waitFor) {
|
||||
UI.addLoadingScreen();
|
||||
SFCommon.create(waitFor(function (c) { common = c; }));
|
||||
UI.updateLoadingProgress({
|
||||
state: 1
|
||||
}, false);
|
||||
}).nThen(function (waitFor) {
|
||||
common.getSframeChannel().onReady(waitFor());
|
||||
}).nThen(function (waitFor) {
|
||||
|
|
|
@ -42,6 +42,9 @@ define([
|
|||
console.error("Require.js threw a Script Error. This probably means you're missing a dependency for CryptPad.\nIt is recommended that the admin of this server runs `bower install && bower update` to get the latest code, then modify their cache version.\nBest of luck,\nThe CryptPad Developers");
|
||||
return void console.log();
|
||||
}
|
||||
if (window.CryptPad_loadingError) {
|
||||
window.CryptPad_loadingError(e);
|
||||
}
|
||||
throw e;
|
||||
};
|
||||
|
||||
|
|
|
@ -140,7 +140,7 @@ define([
|
|||
chainpad.message(content);
|
||||
if (isHistory && updateLoadingProgress) {
|
||||
updateLoadingProgress({
|
||||
state: 2,
|
||||
type: 'pad',
|
||||
progress: isHistory
|
||||
}, false);
|
||||
isHistory++;
|
||||
|
@ -149,6 +149,13 @@ define([
|
|||
});
|
||||
sframeChan.on('EV_RT_READY', function () {
|
||||
if (isReady) { return; }
|
||||
if (updateLoadingProgress) {
|
||||
updateLoadingProgress({
|
||||
type: 'end',
|
||||
progress: 0
|
||||
}, false);
|
||||
isHistory++;
|
||||
}
|
||||
isReady = true;
|
||||
isHistory = false;
|
||||
chainpad.start();
|
||||
|
|
|
@ -131,13 +131,7 @@ define([
|
|||
if (sframeChan) { sframeChan.event('EV_LOADING_INFO', data); }
|
||||
});
|
||||
|
||||
Cryptpad.ready(waitFor(function () {
|
||||
if (sframeChan) {
|
||||
sframeChan.event('EV_LOADING_INFO', {
|
||||
state: -1
|
||||
});
|
||||
}
|
||||
}), {
|
||||
Cryptpad.ready(waitFor(), {
|
||||
driveEvents: cfg.driveEvents,
|
||||
currentPad: currentPad
|
||||
});
|
||||
|
@ -317,10 +311,11 @@ define([
|
|||
return void noPadData('NO_RESULT');
|
||||
}
|
||||
// Data found but weaker? warn
|
||||
expire = res.expire;
|
||||
if (edit && !res.href) {
|
||||
newHref = res.roHref;
|
||||
return;
|
||||
}
|
||||
expire = res.expire;
|
||||
// We have good data, keep the hash in memory
|
||||
newHref = edit ? res.href : (res.roHref || res.href);
|
||||
}));
|
||||
|
@ -1380,8 +1375,10 @@ define([
|
|||
};
|
||||
var i = 0;
|
||||
sframeChan.on('Q_CRYPTGET', function (data, cb) {
|
||||
var keys;
|
||||
var todo = function () {
|
||||
data.opts.network = cgNetwork;
|
||||
data.opts.accessKeys = keys;
|
||||
Cryptget.get(data.hash, function (err, val) {
|
||||
cb({
|
||||
error: err,
|
||||
|
@ -1400,17 +1397,21 @@ define([
|
|||
cgNetwork = undefined;
|
||||
}
|
||||
i++;
|
||||
if (!cgNetwork) {
|
||||
cgNetwork = true;
|
||||
return void Cryptpad.makeNetwork(function (err, nw) {
|
||||
console.log(nw);
|
||||
cgNetwork = nw;
|
||||
todo();
|
||||
});
|
||||
} else if (cgNetwork === true) {
|
||||
return void whenCGReady(todo);
|
||||
}
|
||||
todo();
|
||||
|
||||
Cryptpad.getAccessKeys(function (_keys) {
|
||||
keys = _keys;
|
||||
if (!cgNetwork) {
|
||||
cgNetwork = true;
|
||||
return void Cryptpad.makeNetwork(function (err, nw) {
|
||||
console.log(nw);
|
||||
cgNetwork = nw;
|
||||
todo();
|
||||
});
|
||||
} else if (cgNetwork === true) {
|
||||
return void whenCGReady(todo);
|
||||
}
|
||||
todo();
|
||||
});
|
||||
});
|
||||
sframeChan.on('EV_CRYPTGET_DISCONNECT', function () {
|
||||
if (!cgNetwork) { return; }
|
||||
|
|
|
@ -345,7 +345,13 @@ define([
|
|||
}
|
||||
if (priv.burnAfterReading) {
|
||||
UIElements.displayBurnAfterReadingPage(funcs, waitFor(function () {
|
||||
UI.addLoadingScreen();
|
||||
UI.addLoadingScreen({newProgress: true});
|
||||
if (window.CryptPad_updateLoadingProgress) {
|
||||
window.CryptPad_updateLoadingProgress({
|
||||
type: 'pad',
|
||||
progress: 0
|
||||
});
|
||||
}
|
||||
ctx.sframeChan.event('EV_BURN_AFTER_READING');
|
||||
}));
|
||||
}
|
||||
|
@ -619,6 +625,13 @@ define([
|
|||
}
|
||||
window.CryptPad_sframe_common = true;
|
||||
|
||||
if (window.CryptPad_updateLoadingProgress) {
|
||||
window.CryptPad_updateLoadingProgress({
|
||||
type: 'drive',
|
||||
progress: 0
|
||||
});
|
||||
}
|
||||
|
||||
nThen(function (waitFor) {
|
||||
var msgEv = Util.mkEvent();
|
||||
var iframe = window.parent;
|
||||
|
@ -686,7 +699,8 @@ define([
|
|||
});
|
||||
|
||||
ctx.sframeChan.on('EV_LOADING_INFO', function (data) {
|
||||
UI.updateLoadingProgress(data, 'drive');
|
||||
//UI.updateLoadingProgress(data, 'drive');
|
||||
UI.updateLoadingProgress(data);
|
||||
});
|
||||
|
||||
ctx.sframeChan.on('EV_NEW_VERSION', function () {
|
||||
|
|
|
@ -188,12 +188,12 @@
|
|||
"help_button": "Ohje",
|
||||
"historyText": "Historia",
|
||||
"historyButton": "Näytä asiakirjan historia",
|
||||
"history_next": "Uudempi versio",
|
||||
"history_prev": "Vanhempi versio",
|
||||
"history_next": "Seuraava versio",
|
||||
"history_prev": "Edellinen versio",
|
||||
"history_loadMore": "Lataa lisää historiatietoja",
|
||||
"history_closeTitle": "Sulje historia",
|
||||
"history_restoreTitle": "Palauta asiakirjan valittu versio",
|
||||
"history_restorePrompt": "Oletko varma, että haluat korvata asiakirjan nykyisen version esitetyllä versiolla?",
|
||||
"history_restorePrompt": "Oletko varma, että haluat korvata asiakirjan tämänhetkisen version näytetyllä versiolla?",
|
||||
"history_restoreDone": "Asiakirja palautettu",
|
||||
"history_version": "Versio:",
|
||||
"openLinkInNewTab": "Avaa linkki uuteen välilehteen",
|
||||
|
@ -452,7 +452,7 @@
|
|||
"settings_backupHint": "Varmuuskopioi tai palauta CryptDrivesi sisältö kokonaisuudessaan. Varmuuskopio ei sisällä padiesi sisältöä, ainoastaan niiden käyttöön tarvittavat avaimet.",
|
||||
"settings_backup": "Varmuuskopioi",
|
||||
"settings_restore": "Palauta",
|
||||
"settings_backupHint2": "Lataa kaikkien padiesi nykyinen sisältö. Padit ladataan luettavassa tiedostomuodossa, jos sellainen on saatavilla.",
|
||||
"settings_backupHint2": "Lataa kaikkien asiakirjojen nykyinen sisältö tietokoneellesi. Asiakirjat ladataan muissa sovelluksissa toimivissa tiedostomuodoissa, jos se on mahdollista. Jos sopivaa tiedostomuotoa ei ole saatavilla, asiakirjat ladataan CryptPad-yhteensopivassa tiedostomuodossa.",
|
||||
"settings_backup2": "Lataa oma CryptDrive tietokoneellesi",
|
||||
"settings_backup2Confirm": "Tämä lataa kaikki CryptDrivesi padit ja tiedostot tietokoneellesi. Jos haluat jatkaa, valitse nimi ja paina OK",
|
||||
"settings_exportTitle": "Vie oma CryptDrive",
|
||||
|
@ -1176,9 +1176,9 @@
|
|||
"settings_safeLinksTitle": "Turvalliset linkit",
|
||||
"settings_cat_security": "Luottamuksellisuus",
|
||||
"imprint": "Oikeudellinen huomautus",
|
||||
"oo_sheetMigration_anonymousEditor": "Taulukon muokkaaminen on poistettu käytöstä anonyymeille käyttäjille, kunnes rekisteröitynyt käyttäjä päivittää sen viimeisimpään versioon.",
|
||||
"oo_sheetMigration_anonymousEditor": "Rekisteröitymättömät käyttäjät eivät voi muokata taulukkoa ennen kuin rekisteröitynyt käyttäjä päivittää sen viimeisimpään versioon.",
|
||||
"oo_sheetMigration_complete": "Päivitetty versio saatavilla, paina OK ladataksesi uudelleen.",
|
||||
"oo_sheetMigration_loading": "Päivitetään taulukkoasi viimeisimpään versioon",
|
||||
"oo_sheetMigration_loading": "Päivitetään taulukkoasi viimeisimpään versioon. Ole hyvä ja odota noin 1 minuutti.",
|
||||
"oo_exportInProgress": "Vienti menossa",
|
||||
"oo_importInProgress": "Tuonti menossa",
|
||||
"oo_invalidFormat": "Tätä tiedostoa ei voida tuoda",
|
||||
|
@ -1404,5 +1404,60 @@
|
|||
"readme_cat1_l2": "Avaa padeja CryptDrivestasi: kaksoisnapsauta padin kuvaketta avataksesi sen.",
|
||||
"readme_cat1_l1": "Luo padi: Siirry CryptDriveesi, napsauta {0} ja sitten {1}, ja voit luoda padin.",
|
||||
"readme_cat1": "Tutustu CryptDriveesi",
|
||||
"readme_p2": "Tämä padi toimii pikaisena perehdytyksenä CryptPadin ominaisuuksiin - kuinka tehdä muistiinpanoja, järjestellä niitä ja tehdä yhteistyötä niiden parissa."
|
||||
"readme_p2": "Tämä padi toimii pikaisena perehdytyksenä CryptPadin ominaisuuksiin - kuinka tehdä muistiinpanoja, järjestellä niitä ja tehdä yhteistyötä niiden parissa.",
|
||||
"fm_shareFolderPassword": "Suojaa kansio salasanalla (vapaaehtoinen)",
|
||||
"access_destroyPad": "Tuhoa tämä asiakirja tai kansio lopullisesti",
|
||||
"fm_deletedFolder": "Poistettu kansio",
|
||||
"admin_limitUser": "Käyttäjän julkinen avain",
|
||||
"team_exportButton": "Lataa",
|
||||
"team_exportHint": "Lataa kaikki tiimin CryptDriveen tallennetut asiakirjat tietokoneellesi. Asiakirjat ladataan muissa sovelluksissa toimivissa tiedostomuodoissa, jos se on mahdollista. Jos sopivaa tiedostomuotoa ei ole saatavilla, asiakirjat ladataan CryptPad-yhteensopivassa tiedostomuodossa.",
|
||||
"team_exportTitle": "Lataa tiimin CryptDrive",
|
||||
"admin_cat_quota": "Käyttäjätallennustila",
|
||||
"admin_invalLimit": "Virheellinen arvo kiintiökentässä",
|
||||
"admin_invalKey": "Virheellinen julkinen avain",
|
||||
"admin_limitSetNote": "Huomautus",
|
||||
"admin_limitMB": "Kiintiö (megatavuissa)",
|
||||
"admin_setlimitTitle": "Ota mukautettu kiintiö käyttöön",
|
||||
"admin_setlimitHint": "Aseta mukautettu tallennustilakiintiö käyttäjälle tämän julkisen avaimen avulla. Voit päivittää tai poistaa olemassaolevan tallennustilakiintiön.",
|
||||
"admin_limitNote": "Huomautus: {0}",
|
||||
"admin_limitPlan": "Tilaus: {0}",
|
||||
"admin_defaultlimitHint": "Tallennustilakiintiö käyttäjien ja tiimien CryptDriveille, joilla ei ole erikseen määriteltyjä sääntöjä",
|
||||
"admin_defaultlimitTitle": "Tallennustilakiintiö (Mt)",
|
||||
"admin_getlimitsHint": "Listaa muokatut tallennustilakiintiöt, jotka ovat käytössä CryptPad-palvelimellasi.",
|
||||
"admin_getlimitsTitle": "Muokatut tallennustilakiintiöt",
|
||||
"admin_limit": "Nykyinen rajoitus: {0}",
|
||||
"admin_setlimitButton": "Aseta rajoitus",
|
||||
"admin_registrationAllow": "Avaa",
|
||||
"admin_registrationButton": "Sulje",
|
||||
"admin_registrationTitle": "Sulje rekisteröityminen",
|
||||
"admin_registrationHint": "Älä salli uusien käyttäjien rekisteröitymistä",
|
||||
"snapshots_cantMake": "Tilannevedoksen luominen epäonnistui. Yhteytesi on katkennut.",
|
||||
"snapshots_notFound": "Tämä tilannevedos ei ole enää saatavilla, koska asiakirjan historia on poistettu.",
|
||||
"snapshot_error_exists": "Tästä versiosta on jo olemassa tilannevedos",
|
||||
"snapshots_ooPickVersion": "Valitse versio, jotta voit luoda tilannevedoksen",
|
||||
"oo_version": "Versio: ",
|
||||
"oo_version_latest": "Viimeisin",
|
||||
"snapshots_delete": "Poista",
|
||||
"oo_deletedVersion": "Tämä versio ei ole enää saatavilla historiassa.",
|
||||
"snapshots_close": "Sulje",
|
||||
"snapshots_restore": "Palauta",
|
||||
"snapshots_open": "Avaa",
|
||||
"snapshots_placeholder": "Tilannevedoksen otsikko",
|
||||
"snapshots_new": "Uusi tilannevedos",
|
||||
"snapshots_button": "Tilannevedokset",
|
||||
"snaphot_title": "Tilannevedos",
|
||||
"infobar_versionHash": "Katselet asiakirjan vanhaa versiota ({0}).",
|
||||
"history_restoreDriveDone": "CryptDrive palautettu",
|
||||
"history_restoreDrivePrompt": "Oletko varma, että haluat korvata CryptDriven nykyisen version valitulla versiolla?",
|
||||
"history_restoreDriveTitle": "Palauta CryptDrive valitsemaasi versioon",
|
||||
"history_userNext": "Seuraava laatija",
|
||||
"history_fastNext": "Seuraava muokkaussessio",
|
||||
"history_userPrev": "Edellinen laatija",
|
||||
"history_fastPrev": "Edellinen muokkaussessio",
|
||||
"share_versionHash": "Olet jakamassa valitsemasi historiaversion asiakirjastasi vain luku-tilassa. Tämä antaa myös <b>katseluoikeuden</b> asiakirjan kaikkiin versioihin.",
|
||||
"history_shareTitle": "Jaa linkki tähän versioon",
|
||||
"history_cantRestore": "Palauttaminen epäonnistui. Yhteytesi on katkennut.",
|
||||
"history_close": "Sulje",
|
||||
"history_restore": "Palauta",
|
||||
"share_bar": "Luo linkki"
|
||||
}
|
||||
|
|
|
@ -1459,5 +1459,11 @@
|
|||
"admin_limitUser": "Clé publique de l'utilisateur",
|
||||
"fm_shareFolderPassword": "Protéger ce dossier avec un mot de passe (optionnel)",
|
||||
"access_destroyPad": "Détruire ce document ou dossier définitivement",
|
||||
"fm_deletedFolder": "Dossier supprimé"
|
||||
"fm_deletedFolder": "Dossier supprimé",
|
||||
"loading_state_5": "Reconstruction du document",
|
||||
"loading_state_4": "Chargement des équipes",
|
||||
"loading_state_3": "Chargement des dossiers partagés",
|
||||
"loading_state_2": "Mise à jour du contenu",
|
||||
"loading_state_1": "Chargement du drive",
|
||||
"loading_state_0": "Construction de l'interface"
|
||||
}
|
||||
|
|
|
@ -1459,5 +1459,11 @@
|
|||
"admin_limitUser": "User's public key",
|
||||
"fm_deletedFolder": "Deleted folder",
|
||||
"access_destroyPad": "Destroy this document or folder permanently",
|
||||
"fm_shareFolderPassword": "Protect this folder with a password (optional)"
|
||||
"fm_shareFolderPassword": "Protect this folder with a password (optional)",
|
||||
"loading_state_0": "Build interface",
|
||||
"loading_state_1": "Load drive",
|
||||
"loading_state_2": "Update content",
|
||||
"loading_state_3": "Load shared folders",
|
||||
"loading_state_4": "Load Teams",
|
||||
"loading_state_5": "Reconstruct document"
|
||||
}
|
||||
|
|
|
@ -846,7 +846,8 @@ define([
|
|||
};
|
||||
exp.ownedInTrash = function (isOwned) {
|
||||
return getFiles([TRASH]).map(function (id) {
|
||||
var data = exp.getFileData(id);
|
||||
var data = isSharedFolder(id) ? files[SHARED_FOLDERS][id] : exp.getFileData(id);
|
||||
if (!data) { return; }
|
||||
return isOwned(data.owners) ? data.channel : undefined;
|
||||
}).filter(Boolean);
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue