Merge branch 'staging' into editable-metadata

This commit is contained in:
ansuz 2019-08-16 16:43:42 +02:00
commit 1c55ac15d5
19 changed files with 696 additions and 233 deletions

View File

@ -7,6 +7,7 @@ define(function () {
fileHashKey: 'FS_hash', fileHashKey: 'FS_hash',
// sessionStorage // sessionStorage
newPadPathKey: "newPadPath", newPadPathKey: "newPadPath",
newPadFileData: "newPadFileData",
// Store // Store
displayNameKey: 'cryptpad.username', displayNameKey: 'cryptpad.username',
oldStorageKey: 'CryptPad_RECENTPADS', oldStorageKey: 'CryptPad_RECENTPADS',

View File

@ -15,6 +15,7 @@ define([
}; };
var supportedTypes = [ var supportedTypes = [
'text/plain',
'image/png', 'image/png',
'image/jpeg', 'image/jpeg',
'image/jpg', 'image/jpg',
@ -23,7 +24,12 @@ define([
'application/pdf' 'application/pdf'
]; ];
Thumb.isSupportedType = function (type) { Thumb.isSupportedType = function (file) {
if (!file) { return false; }
var type = file.type;
if (Util.isPlainTextFile(file.type, file.name)) {
type = "text/plain";
}
return supportedTypes.some(function (t) { return supportedTypes.some(function (t) {
return type.indexOf(t) !== -1; return type.indexOf(t) !== -1;
}); });
@ -164,6 +170,26 @@ define([
}); });
}); });
}; };
Thumb.fromPlainTextBlob = function (blob, cb) {
var canvas = document.createElement("canvas");
canvas.width = canvas.height = Thumb.dimension;
var reader = new FileReader();
reader.addEventListener('loadend', function (e) {
var content = e.srcElement.result;
var lines = content.split("\n");
var canvasContext = canvas.getContext("2d");
var fontSize = 4;
canvas.height = (lines.length) * (fontSize + 1);
canvasContext.font = fontSize + 'px monospace';
lines.forEach(function (text, i) {
canvasContext.fillText(text, 5, i * (fontSize + 1));
});
var D = getResizedDimensions(canvas, "txt");
Thumb.fromCanvas(canvas, D, cb);
});
reader.readAsText(blob);
};
Thumb.fromBlob = function (blob, cb) { Thumb.fromBlob = function (blob, cb) {
if (blob.type.indexOf('video/') !== -1) { if (blob.type.indexOf('video/') !== -1) {
return void Thumb.fromVideoBlob(blob, cb); return void Thumb.fromVideoBlob(blob, cb);
@ -171,6 +197,9 @@ define([
if (blob.type.indexOf('application/pdf') !== -1) { if (blob.type.indexOf('application/pdf') !== -1) {
return void Thumb.fromPdfBlob(blob, cb); return void Thumb.fromPdfBlob(blob, cb);
} }
if (Util.isPlainTextFile(blob.type, blob.name)) {
return void Thumb.fromPlainTextBlob(blob, cb);
}
Thumb.fromImageBlob(blob, cb); Thumb.fromImageBlob(blob, cb);
}; };

View File

@ -2301,7 +2301,10 @@ define([
if (!common.isLoggedIn()) { return void cb(); } if (!common.isLoggedIn()) { return void cb(); }
var sframeChan = common.getSframeChannel(); var sframeChan = common.getSframeChannel();
var metadataMgr = common.getMetadataMgr(); var metadataMgr = common.getMetadataMgr();
var privateData = metadataMgr.getPrivateData();
var type = metadataMgr.getMetadataLazy().type; var type = metadataMgr.getMetadataLazy().type;
var fromFileData = privateData.fromFileData;
var $body = $('body'); var $body = $('body');
var $creationContainer = $('<div>', { id: 'cp-creation-container' }).appendTo($body); var $creationContainer = $('<div>', { id: 'cp-creation-container' }).appendTo($body);
@ -2313,7 +2316,8 @@ define([
// Title // Title
//var colorClass = 'cp-icon-color-'+type; //var colorClass = 'cp-icon-color-'+type;
//$creation.append(h('h2.cp-creation-title', Messages.newButtonTitle)); //$creation.append(h('h2.cp-creation-title', Messages.newButtonTitle));
$creation.append(h('h3.cp-creation-title', Messages['button_new'+type])); var newPadH3Title = Messages['button_new' + type];
$creation.append(h('h3.cp-creation-title', newPadH3Title));
//$creation.append(h('h2.cp-creation-title.'+colorClass, Messages.newButtonTitle)); //$creation.append(h('h2.cp-creation-title.'+colorClass, Messages.newButtonTitle));
// Deleted pad warning // Deleted pad warning
@ -2323,7 +2327,7 @@ define([
)); ));
} }
var origin = common.getMetadataMgr().getPrivateData().origin; var origin = privateData.origin;
var createHelper = function (href, text) { var createHelper = function (href, text) {
var q = h('a.cp-creation-help.fa.fa-question-circle', { var q = h('a.cp-creation-help.fa.fa-question-circle', {
title: text, title: text,
@ -2480,7 +2484,26 @@ define([
}); });
if (i < TEMPLATES_DISPLAYED) { $(left).addClass('hidden'); } if (i < TEMPLATES_DISPLAYED) { $(left).addClass('hidden'); }
}; };
redraw(0); if (fromFileData) {
var todo = function (thumbnail) {
allData = [{
name: fromFileData.title,
id: 0,
thumbnail: thumbnail,
icon: h('span.cptools.cptools-file'),
}];
redraw(0);
};
todo();
sframeChan.query("Q_GET_FILE_THUMBNAIL", null, function (err, res) {
if (err || (res && res.error)) { return; }
todo(res.data);
});
}
else {
redraw(0);
}
// Change template selection when Tab is pressed // Change template selection when Tab is pressed
next = function (revert) { next = function (revert) {

View File

@ -325,6 +325,30 @@ define([], function () {
return div.innerText; return div.innerText;
}; };
// return an object containing {name, ext}
// or {} if the name could not be parsed
Util.parseFilename = function (filename) {
if (!filename || !filename.trim()) { return {}; }
var parsedName = /^(\.?.+?)(\.[^.]+)?$/.exec(filename) || [];
return {
name: parsedName[1],
ext: parsedName[2],
};
};
// Tell if a file is plain text from its metadata={title, fileType}
Util.isPlainTextFile = function (type, name) {
// does its type begins with "text/"
if (type && type.indexOf("text/") === 0) { return true; }
// no type and no file extension -> let's guess it's plain text
var parsedName = Util.parseFilename(name);
if (!type && name && !parsedName.ext) { return true; }
// other exceptions
if (type === 'application/x-javascript') { return true; }
if (type === 'application/xml') { return true; }
return false;
};
return Util; return Util;
}); });
}(self)); }(self));

View File

@ -21,6 +21,11 @@ define([
S.leave(); S.leave();
} catch (e) { console.log(e); } } catch (e) { console.log(e); }
} }
if (S.realtime && S.realtime.stop) {
try {
S.realtime.stop();
} catch (e) { console.error(e); }
}
var abort = Util.find(S, ['session', 'realtime', 'abort']); var abort = Util.find(S, ['session', 'realtime', 'abort']);
if (typeof(abort) === 'function') { if (typeof(abort) === 'function') {
S.session.realtime.sync(); S.session.realtime.sync();
@ -52,11 +57,12 @@ define([
Object.keys(b).forEach(function (k) { a[k] = b[k]; }); Object.keys(b).forEach(function (k) { a[k] = b[k]; });
}; };
var get = function (hash, cb, opt) { var get = function (hash, cb, opt, progress) {
if (typeof(cb) !== 'function') { if (typeof(cb) !== 'function') {
throw new Error('Cryptget expects a callback'); throw new Error('Cryptget expects a callback');
} }
opt = opt || {}; opt = opt || {};
progress = progress || function () {};
var config = makeConfig(hash, opt); var config = makeConfig(hash, opt);
var Session = { cb: cb, hasNetwork: Boolean(opt.network) }; var Session = { cb: cb, hasNetwork: Boolean(opt.network) };
@ -65,6 +71,7 @@ define([
var rt = Session.session = info.realtime; var rt = Session.session = info.realtime;
Session.network = info.network; Session.network = info.network;
Session.leave = info.leave; Session.leave = info.leave;
progress(1);
finish(Session, void 0, rt.getUserDoc()); finish(Session, void 0, rt.getUserDoc());
}; };
@ -72,6 +79,16 @@ define([
finish(Session, info.error); finish(Session, info.error);
}; };
// We use the new onMessage handler to compute the progress:
// we should receive 2 checkpoints max, so 100 messages max
// We're going to consider that 1 message = 1%, and we'll send 100%
// at the end
var i = 0;
config.onMessage = function () {
i++;
progress(Math.min(0.99, i/100));
};
overwrite(config, opt); overwrite(config, opt);
Session.realtime = CPNetflux.start(config); Session.realtime = CPNetflux.start(config);

View File

@ -571,6 +571,66 @@ define([
}); });
}; };
common.useFile = function (Crypt, cb, optsPut) {
var data = common.fromFileData;
var parsed = Hash.parsePadUrl(data.href);
var parsed2 = Hash.parsePadUrl(window.location.href);
var hash = parsed.hash;
var name = data.title;
var secret = Hash.getSecrets('file', hash, data.password);
var src = Hash.getBlobPathFromHex(secret.channel);
var key = secret.keys && secret.keys.cryptKey;
var u8;
var res;
var mode;
var val;
Nthen(function(waitFor) {
Util.fetch(src, waitFor(function (err, _u8) {
if (err) { return void waitFor.abort(); }
u8 = _u8;
}));
}).nThen(function (waitFor) {
require(["/file/file-crypto.js"], waitFor(function (FileCrypto) {
FileCrypto.decrypt(u8, key, waitFor(function (err, _res) {
if (err || !_res.content) { return void waitFor.abort(); }
res = _res;
}));
}));
}).nThen(function (waitFor) {
var ext = Util.parseFilename(data.title).ext;
if (!ext) {
mode = "text";
return;
}
require(["/common/modes.js"], waitFor(function (Modes) {
Modes.list.some(function (fType) {
if (fType.ext === ext) {
mode = fType.mode;
return true;
}
});
}));
}).nThen(function (waitFor) {
var reader = new FileReader();
reader.addEventListener('loadend', waitFor(function (e) {
val = {
content: e.srcElement.result,
highlightMode: mode,
metadata: {
defaultTitle: name,
title: name,
type: "code",
},
};
}));
reader.readAsText(res.content);
}).nThen(function () {
Crypt.put(parsed2.hash, JSON.stringify(val), cb, optsPut);
});
};
// Forget button // Forget button
common.moveToTrash = function (cb, href) { common.moveToTrash = function (cb, href) {
href = href || window.location.href; href = href || window.location.href;
@ -1274,6 +1334,12 @@ define([
messenger: rdyCfg.messenger, // Boolean messenger: rdyCfg.messenger, // Boolean
driveEvents: rdyCfg.driveEvents // Boolean driveEvents: rdyCfg.driveEvents // Boolean
}; };
// if a pad is created from a file
if (sessionStorage[Constants.newPadFileData]) {
common.fromFileData = JSON.parse(sessionStorage[Constants.newPadFileData]);
delete sessionStorage[Constants.newPadFileData];
}
if (sessionStorage[Constants.newPadPathKey]) { if (sessionStorage[Constants.newPadPathKey]) {
common.initialPath = sessionStorage[Constants.newPadPathKey]; common.initialPath = sessionStorage[Constants.newPadPathKey];
delete sessionStorage[Constants.newPadPathKey]; delete sessionStorage[Constants.newPadPathKey];

View File

@ -1,11 +1,13 @@
define([ define([
'/common/cryptget.js', '/common/cryptget.js',
'/file/file-crypto.js',
'/common/common-hash.js', '/common/common-hash.js',
'/common/sframe-common-file.js', '/common/common-util.js',
'/bower_components/nthen/index.js', '/bower_components/nthen/index.js',
'/bower_components/saferphore/index.js', '/bower_components/saferphore/index.js',
'/bower_components/jszip/dist/jszip.min.js', '/bower_components/jszip/dist/jszip.min.js',
], function (Crypt, Hash, SFCFile, nThen, Saferphore, JsZip) { ], function (Crypt, FileCrypto, Hash, Util, nThen, Saferphore, JsZip) {
var saveAs = window.saveAs;
var sanitize = function (str) { var sanitize = function (str) {
return str.replace(/[\\/?%*:|"<>]/gi, '_')/*.toLowerCase()*/; return str.replace(/[\\/?%*:|"<>]/gi, '_')/*.toLowerCase()*/;
@ -43,6 +45,88 @@ define([
}); });
}; };
var _downloadFile = function (ctx, fData, cb, updateProgress) {
var cancelled = false;
var cancel = function () {
cancelled = true;
};
var parsed = Hash.parsePadUrl(fData.href || fData.roHref);
var hash = parsed.hash;
var name = fData.filename || fData.title;
var secret = Hash.getSecrets('file', hash, fData.password);
var src = Hash.getBlobPathFromHex(secret.channel);
var key = secret.keys && secret.keys.cryptKey;
Util.fetch(src, function (err, u8) {
if (cancelled) { return; }
if (err) { return void cb('E404'); }
FileCrypto.decrypt(u8, key, function (err, res) {
if (cancelled) { return; }
if (err) { return void cb(err); }
if (!res.content) { return void cb('EEMPTY'); }
var dl = function () {
saveAs(res.content, name || res.metadata.name);
};
cb(null, {
metadata: res.metadata,
content: res.content,
download: dl
});
}, updateProgress && updateProgress.progress2);
}, updateProgress && updateProgress.progress);
return {
cancel: cancel
};
};
var _downloadPad = function (ctx, pData, cb, updateProgress) {
var cancelled = false;
var cancel = function () {
cancelled = true;
};
var parsed = Hash.parsePadUrl(pData.href || pData.roHref);
var name = pData.filename || pData.title;
var opts = {
password: pData.password
};
var done = false;
ctx.sframeChan.on("EV_CRYPTGET_PROGRESS", function (data) {
if (done || data.hash !== parsed.hash) { return; }
updateProgress.progress(data.progress);
if (data.progress === 1) {
done = true;
updateProgress.progress2(1);
}
});
ctx.get({
hash: parsed.hash,
opts: opts
}, function (err, val) {
if (cancelled) { return; }
if (err) { return; }
if (!val) { return; }
transform(ctx, parsed.type, val, function (res) {
if (cancelled) { return; }
if (!res.data) { return; }
var dl = function () {
saveAs(res.data, Util.fixFileName(name));
};
cb(null, {
metadata: res.metadata,
content: res.data,
download: dl
});
});
});
return {
cancel: cancel
};
};
// Add a file to the zip. We have to cryptget&transform it if it's a pad // Add a file to the zip. We have to cryptget&transform it if it's a pad
// or fetch&decrypt it if it's a file. // or fetch&decrypt it if it's a file.
var addFile = function (ctx, zip, fData, existingNames) { var addFile = function (ctx, zip, fData, existingNames) {
@ -126,7 +210,7 @@ define([
// Files (mediatags...) // Files (mediatags...)
var todoFile = function () { var todoFile = function () {
var it; var it;
var dl = SFCFile.downloadFile(fData, function (err, res) { var dl = _downloadFile(ctx, fData, function (err, res) {
if (it) { clearInterval(it); } if (it) { clearInterval(it); }
if (err) { return void error(err); } if (err) { return void error(err); }
var opts = { var opts = {
@ -189,6 +273,7 @@ define([
var ctx = { var ctx = {
get: getPad, get: getPad,
data: data.uo.drive, data: data.uo.drive,
folder: data.folder || ctx.data.root,
sf: data.sf, sf: data.sf,
zip: new JsZip(), zip: new JsZip(),
errors: [], errors: [],
@ -197,11 +282,12 @@ define([
max: 0, max: 0,
done: 0 done: 0
}; };
var filesData = data.sharedFolderId && ctx.sf[data.sharedFolderId] ? ctx.sf[data.sharedFolderId].filesData : ctx.data.filesData;
progress('reading', -1); progress('reading', -1);
nThen(function (waitFor) { nThen(function (waitFor) {
ctx.waitFor = waitFor; ctx.waitFor = waitFor;
var zipRoot = ctx.zip.folder('Root'); var zipRoot = ctx.zip.folder('Root');
makeFolder(ctx, ctx.data.root, zipRoot, ctx.data.filesData); makeFolder(ctx, ctx.folder, zipRoot, filesData);
progress('download', {}); progress('download', {});
}).nThen(function () { }).nThen(function () {
console.log(ctx.zip); console.log(ctx.zip);
@ -222,7 +308,33 @@ define([
}; };
}; };
var _downloadFolder = function (ctx, data, cb, updateProgress) {
create(data, ctx.get, function (blob, errors) {
console.error(errors); // TODO show user errors
var dl = function () {
saveAs(blob, data.folderName);
};
cb(null, {download: dl});
}, function (state, progress) {
if (state === "reading") {
updateProgress.folderProgress(0);
}
if (state === "download") {
if (typeof progress.current !== "number") { return; }
updateProgress.folderProgress(progress.current / progress.max);
}
else if (state === "done") {
updateProgress.folderProgress(1);
}
});
};
return { return {
create: create create: create,
downloadFile: _downloadFile,
downloadPad: _downloadPad,
downloadFolder: _downloadFolder,
}; };
}); });

View File

@ -1108,7 +1108,6 @@ define([
var channels = Store.channels = store.channels = {}; var channels = Store.channels = store.channels = {};
Store.joinPad = function (clientId, data) { Store.joinPad = function (clientId, data) {
console.log('joining', data.channel);
var isNew = typeof channels[data.channel] === "undefined"; var isNew = typeof channels[data.channel] === "undefined";
var channel = channels[data.channel] = channels[data.channel] || { var channel = channels[data.channel] = channels[data.channel] || {
queue: [], queue: [],
@ -1189,9 +1188,6 @@ define([
onLeave: function (m) { onLeave: function (m) {
channel.bcast("PAD_LEAVE", m); channel.bcast("PAD_LEAVE", m);
}, },
onAbort: function () {
channel.bcast("PAD_DISCONNECT");
},
onError: function (err) { onError: function (err) {
channel.bcast("PAD_ERROR", err); channel.bcast("PAD_ERROR", err);
delete channels[data.channel]; delete channels[data.channel];
@ -1200,7 +1196,11 @@ define([
channel.bcast("PAD_ERROR", err); channel.bcast("PAD_ERROR", err);
delete channels[data.channel]; delete channels[data.channel];
}, },
onConnectionChange: function () {}, onConnectionChange: function (info) {
if (!info.state) {
channel.bcast("PAD_DISCONNECT");
}
},
crypto: { crypto: {
// The encryption and decryption is done in the outer window. // The encryption and decryption is done in the outer window.
// This async-store only deals with already encrypted messages. // This async-store only deals with already encrypted messages.

View File

@ -1,6 +1,7 @@
define([ define([
'jquery', 'jquery',
'/file/file-crypto.js', '/file/file-crypto.js',
'/common/make-backup.js',
'/common/common-thumbnail.js', '/common/common-thumbnail.js',
'/common/common-interface.js', '/common/common-interface.js',
'/common/common-ui-elements.js', '/common/common-ui-elements.js',
@ -11,9 +12,8 @@ define([
'/bower_components/file-saver/FileSaver.min.js', '/bower_components/file-saver/FileSaver.min.js',
'/bower_components/tweetnacl/nacl-fast.min.js', '/bower_components/tweetnacl/nacl-fast.min.js',
], function ($, FileCrypto, Thumb, UI, UIElements, Util, Hash, h, Messages) { ], function ($, FileCrypto, MakeBackup, Thumb, UI, UIElements, Util, Hash, h, Messages) {
var Nacl = window.nacl; var Nacl = window.nacl;
var saveAs = window.saveAs;
var module = {}; var module = {};
var blobToArrayBuffer = function (blob, cb) { var blobToArrayBuffer = function (blob, cb) {
@ -367,7 +367,7 @@ define([
blobToArrayBuffer(file, function (e, buffer) { blobToArrayBuffer(file, function (e, buffer) {
if (e) { console.error(e); } if (e) { console.error(e); }
file_arraybuffer = buffer; file_arraybuffer = buffer;
if (!Thumb.isSupportedType(file.type)) { return getName(); } if (!Thumb.isSupportedType(file)) { return getName(); }
// make a resized thumbnail from the image.. // make a resized thumbnail from the image..
Thumb.fromBlob(file, function (e, thumb64) { Thumb.fromBlob(file, function (e, thumb64) {
if (e) { console.error(e); } if (e) { console.error(e); }
@ -446,124 +446,108 @@ define([
createUploader(config.dropArea, config.hoverArea, config.body); createUploader(config.dropArea, config.hoverArea, config.body);
var updateProgressbar = function (file, data, downloadFunction, cb) {
if (queue.inProgress) { return; }
queue.inProgress = true;
var id = file.id;
var $row = $table.find('tr[id="'+id+'"]');
var $pv = $row.find('.cp-fileupload-table-progress-value');
var $pb = $row.find('.cp-fileupload-table-progress-container');
var $pc = $row.find('.cp-fileupload-table-progress');
var $link = $row.find('.cp-fileupload-table-link');
var done = function () {
$row.find('.cp-fileupload-table-cancel').text('-');
queue.inProgress = false;
queue.next();
};
var updateDLProgress = function (progressValue) {
var text = Math.round(progressValue * 100) + '%';
text += ' (' + Messages.download_step1 + '...)';
$pv.text(text);
$pb.css({
width: progressValue * $pc.width() + 'px'
});
};
var updateDecryptProgress = function (progressValue) {
var text = Math.round(progressValue*100) + '%';
text += progressValue === 1 ? '' : ' (' + Messages.download_step2 + '...)';
$pv.text(text);
$pb.css({
width: progressValue * $pc.width()+'px'
});
};
var updateProgress = function (progressValue) {
var text = Math.round(progressValue*100) + '%';
$pv.text(text);
$pb.css({
width: progressValue * $pc.width()+'px'
});
};
var ctx = {
get: common.getPad,
sframeChan: sframeChan,
};
downloadFunction(ctx, data, function (err, obj) {
$link.prepend($('<span>', {'class': 'fa fa-external-link'}))
.attr('href', '#')
.click(function (e) {
e.preventDefault();
obj.download();
});
done();
if (obj) { obj.download(); }
cb(err, obj);
}, {
progress: updateDLProgress,
progress2: updateDecryptProgress,
folderProgress: updateProgress,
});
// var $cancel = $('<span>', {'class': 'cp-fileupload-table-cancel-button fa fa-times'}).click(function () {
// dl.cancel();
// $cancel.remove();
// $row.find('.cp-fileupload-table-progress-value').text(Messages.upload_cancelled);
// done();
// });
// $row.find('.cp-fileupload-table-cancel').html('').append($cancel);
$row.find('.cp-fileupload-table-cancel').html('');
};
File.downloadFile = function (fData, cb) { File.downloadFile = function (fData, cb) {
var parsed = Hash.parsePadUrl(fData.href || fData.roHref);
var hash = parsed.hash;
var name = fData.filename || fData.title; var name = fData.filename || fData.title;
var secret = Hash.getSecrets('file', hash, fData.password); common.getFileSize(fData.channel, function (e, data) {
var src = Hash.getBlobPathFromHex(secret.channel);
var key = secret.keys && secret.keys.cryptKey;
common.getFileSize(secret.channel, function (e, data) {
var todo = function (file) {
if (queue.inProgress) { return; }
queue.inProgress = true;
var id = file.id;
var $row = $table.find('tr[id="'+id+'"]');
var $pv = $row.find('.cp-fileupload-table-progress-value');
var $pb = $row.find('.cp-fileupload-table-progress-container');
var $pc = $row.find('.cp-fileupload-table-progress');
var $link = $row.find('.cp-fileupload-table-link');
var done = function () {
$row.find('.cp-fileupload-table-cancel').text('-');
queue.inProgress = false;
queue.next();
};
var updateDLProgress = function (progressValue) {
var text = Math.round(progressValue*100) + '%';
text += ' ('+ Messages.download_step1 +'...)';
$pv.text(text);
$pb.css({
width: progressValue * $pc.width()+'px'
});
};
var updateProgress = function (progressValue) {
var text = Math.round(progressValue*100) + '%';
text += progressValue === 1 ? '' : ' ('+ Messages.download_step2 +'...)';
$pv.text(text);
$pb.css({
width: progressValue * $pc.width()+'px'
});
};
var dl = module.downloadFile(fData, function (err, obj) {
$link.prepend($('<span>', {'class': 'fa fa-external-link'}))
.attr('href', '#')
.click(function (e) {
e.preventDefault();
obj.download();
});
done();
if (obj) { obj.download(); }
cb(err, obj);
}, {
src: src,
key: key,
name: name,
progress: updateDLProgress,
progress2: updateProgress,
});
var $cancel = $('<span>', {'class': 'cp-fileupload-table-cancel-button fa fa-times'}).click(function () {
dl.cancel();
$cancel.remove();
$row.find('.cp-fileupload-table-progress-value').text(Messages.upload_cancelled);
done();
});
$row.find('.cp-fileupload-table-cancel').html('').append($cancel);
};
queue.push({ queue.push({
dl: todo, dl: function (file) { updateProgressbar(file, fData, MakeBackup.downloadFile, cb); },
size: data, size: data,
name: name name: name
}); });
}); });
}; };
File.downloadPad = function (pData, cb) {
queue.push({
dl: function (file) { updateProgressbar(file, pData, MakeBackup.downloadPad, cb); },
size: 0,
name: pData.title,
});
};
File.downloadFolder = function (data, cb) {
queue.push({
dl: function (file) { updateProgressbar(file, data, MakeBackup.downloadFolder, cb); },
size: 0,
name: data.folderName,
});
};
return File; return File;
}; };
module.downloadFile = function (fData, cb, obj) {
var cancelled = false;
var cancel = function () {
cancelled = true;
};
var src, key, name;
if (obj && obj.src && obj.key && obj.name) {
src = obj.src;
key = obj.key;
name = obj.name;
} else {
var parsed = Hash.parsePadUrl(fData.href || fData.roHref);
var hash = parsed.hash;
name = fData.filename || fData.title;
var secret = Hash.getSecrets('file', hash, fData.password);
src = Hash.getBlobPathFromHex(secret.channel);
key = secret.keys && secret.keys.cryptKey;
}
Util.fetch(src, function (err, u8) {
if (cancelled) { return; }
if (err) { return void cb('E404'); }
FileCrypto.decrypt(u8, key, function (err, res) {
if (cancelled) { return; }
if (err) { return void cb(err); }
if (!res.content) { return void cb('EEMPTY'); }
var dl = function () {
saveAs(res.content, name || res.metadata.name);
};
cb(null, {
metadata: res.metadata,
content: res.content,
download: dl
});
}, obj && obj.progress2);
}, obj && obj.progress);
return {
cancel: cancel
};
};
return module; return module;
}); });

View File

@ -319,6 +319,9 @@ define([
channel: secret.channel, channel: secret.channel,
enableSF: localStorage.CryptPad_SF === "1", // TODO to remove when enabled by default enableSF: localStorage.CryptPad_SF === "1", // TODO to remove when enabled by default
devMode: localStorage.CryptPad_dev === "1", devMode: localStorage.CryptPad_dev === "1",
fromFileData: Cryptpad.fromFileData ? {
title: Cryptpad.fromFileData.title
} : undefined,
}; };
if (window.CryptPad_newSharedFolder) { if (window.CryptPad_newSharedFolder) {
additionalPriv.newSharedFolder = window.CryptPad_newSharedFolder; additionalPriv.newSharedFolder = window.CryptPad_newSharedFolder;
@ -359,6 +362,8 @@ define([
sframeChan.event("EV_NEW_VERSION"); sframeChan.event("EV_NEW_VERSION");
}); });
// Put in the following function the RPC queries that should also work in filepicker // Put in the following function the RPC queries that should also work in filepicker
var addCommonRpc = function (sframeChan) { var addCommonRpc = function (sframeChan) {
sframeChan.on('Q_ANON_RPC_MESSAGE', function (data, cb) { sframeChan.on('Q_ANON_RPC_MESSAGE', function (data, cb) {
@ -811,6 +816,22 @@ define([
}); });
}); });
sframeChan.on('Q_GET_FILE_THUMBNAIL', function (data, cb) {
if (!Cryptpad.fromFileData || !Cryptpad.fromFileData.href) {
return void cb({
error: "EINVAL",
});
}
var key = getKey(Cryptpad.fromFileData.href, Cryptpad.fromFileData.channel);
Utils.LocalStore.getThumbnail(key, function (e, data) {
if (data === "EMPTY") { data = null; }
cb({
error: e,
data: data
});
});
});
sframeChan.on('EV_GOTO_URL', function (url) { sframeChan.on('EV_GOTO_URL', function (url) {
if (url) { if (url) {
window.location.href = url; window.location.href = url;
@ -864,6 +885,9 @@ define([
Cryptpad.removeLoginBlock(data, cb); Cryptpad.removeLoginBlock(data, cb);
}); });
// It seems we have performance issues when we open and close a lot of channels over
// the same network, maybe a memory leak. To fix this, we kill and create a new
// network every 30 cryptget calls (1 call = 1 channel)
var cgNetwork; var cgNetwork;
var whenCGReady = function (cb) { var whenCGReady = function (cb) {
if (cgNetwork && cgNetwork !== true) { console.log(cgNetwork); return void cb(); } if (cgNetwork && cgNetwork !== true) { console.log(cgNetwork); return void cb(); }
@ -880,7 +904,12 @@ define([
error: err, error: err,
data: val data: val
}); });
}, data.opts); }, data.opts, function (progress) {
sframeChan.event("EV_CRYPTGET_PROGRESS", {
hash: data.hash,
progress: progress,
});
});
}; };
//return void todo(); //return void todo();
if (i > 30) { if (i > 30) {
@ -1089,11 +1118,11 @@ define([
})); }));
} }
}).nThen(function () { }).nThen(function () {
var cryptputCfg = $.extend(true, {}, rtConfig, {password: password});
if (data.template) { if (data.template) {
// Pass rtConfig to useTemplate because Cryptput will create the file and // Pass rtConfig to useTemplate because Cryptput will create the file and
// we need to have the owners and expiration time in the first line on the // we need to have the owners and expiration time in the first line on the
// server // server
var cryptputCfg = $.extend(true, {}, rtConfig, {password: password});
Cryptpad.useTemplate({ Cryptpad.useTemplate({
href: data.template href: data.template
}, Cryptget, function () { }, Cryptget, function () {
@ -1102,6 +1131,14 @@ define([
}, cryptputCfg); }, cryptputCfg);
return; return;
} }
// if we open a new code from a file
if (Cryptpad.fromFileData) {
Cryptpad.useFile(Cryptget, function () {
startRealtime();
cb();
}, cryptputCfg);
return;
}
// Start realtime outside the iframe and callback // Start realtime outside the iframe and callback
startRealtime(rtConfig); startRealtime(rtConfig);
cb(); cb();

View File

@ -459,6 +459,14 @@ define([
}); });
}; */ }; */
funcs.getPad = function (data, cb) {
ctx.sframeChan.query("Q_CRYPTGET", data, function (err, obj) {
if (err) { return void cb(err); }
if (obj.error) { return void cb(obj.error); }
cb(null, obj.data);
}, { timeout: 60000 });
};
funcs.gotoURL = function (url) { ctx.sframeChan.event('EV_GOTO_URL', url); }; funcs.gotoURL = function (url) { ctx.sframeChan.event('EV_GOTO_URL', url); };
funcs.openURL = function (url) { ctx.sframeChan.event('EV_OPEN_URL', url); }; funcs.openURL = function (url) { ctx.sframeChan.event('EV_OPEN_URL', url); };
funcs.openUnsafeURL = function (url) { funcs.openUnsafeURL = function (url) {

View File

@ -575,7 +575,6 @@ MessengerUI, Messages) {
}; };
var createRequest = function (toolbar, config) { var createRequest = function (toolbar, config) {
console.error('test');
if (!config.metadataMgr) { if (!config.metadataMgr) {
throw new Error("You must provide a `metadataMgr` to display the request access button"); throw new Error("You must provide a `metadataMgr` to display the request access button");
} }

View File

@ -1112,16 +1112,17 @@
"notifications_cat_pads": "Mit mir geteilt", "notifications_cat_pads": "Mit mir geteilt",
"notifications_cat_archived": "Verlauf", "notifications_cat_archived": "Verlauf",
"notifications_dismissAll": "Alle verbergen", "notifications_dismissAll": "Alle verbergen",
"support_notification": "", "support_notification": "Ein Administrator hat dein Support-Ticket beantwortet",
"requestEdit_button": "", "requestEdit_button": "Bearbeitungsrechte anfragen",
"requestEdit_dialog": "", "requestEdit_dialog": "Bist du sicher, dass du den Eigentümer um Bearbeitungsrechte für das Pad bitten möchtest?",
"requestEdit_confirm": "", "requestEdit_confirm": "{1} hat Bearbeitungsrechte für das Pad <b>{0}</b> angefragt. Möchtest du die Rechte vergeben?",
"requestEdit_fromFriend": "", "requestEdit_fromFriend": "Du bist mit {0} befreundet",
"requestEdit_fromStranger": "", "requestEdit_fromStranger": "Du bist <b>nicht</b> mit {0} befreundet",
"requestEdit_viewPad": "", "requestEdit_viewPad": "Pad in neuem Tab öffnen",
"later": "", "later": "Später entscheiden",
"requestEdit_request": "", "requestEdit_request": "{1} möchte das Pad <b>{0}</b> bearbeiten",
"requestEdit_accepted": "", "requestEdit_accepted": "{1} hat dir Bearbeitungsrechte für das Pad <b>{0}</b> gegeben",
"requestEdit_sent": "", "requestEdit_sent": "Anfrage gesendet",
"uploadFolderButton": "" "uploadFolderButton": "Ordner hochladen",
"properties_unknownUser": "{0} unbekannte(r) Benutzer"
} }

View File

@ -1111,5 +1111,18 @@
"admin_supportInitHint": "Vous pouvez configurer une messagerie de support afin de fournir aux utilisateurs de votre instance CryptPad un moyen de vous contacter de manière sécurisée en cas de problème avec leur compte.", "admin_supportInitHint": "Vous pouvez configurer une messagerie de support afin de fournir aux utilisateurs de votre instance CryptPad un moyen de vous contacter de manière sécurisée en cas de problème avec leur compte.",
"admin_supportListHint": "Voici la liste des tickets envoyés par les utilisateurs au support. Tous les administrateurs peuvent voir les tickets et leurs réponses. Un ticket fermé ne peut pas être ré-ouvert. Vous ne pouvez supprimer (ou cacher) que les tickets fermés, et les tickets supprimés restent visible par les autres administrateurs.", "admin_supportListHint": "Voici la liste des tickets envoyés par les utilisateurs au support. Tous les administrateurs peuvent voir les tickets et leurs réponses. Un ticket fermé ne peut pas être ré-ouvert. Vous ne pouvez supprimer (ou cacher) que les tickets fermés, et les tickets supprimés restent visible par les autres administrateurs.",
"support_formHint": "Ce formulaire peut être utilisé pour créer un nouveau ticket de support. Utilisez-le pour contacter les administrateurs de manière sécurisée afin de résoudre un problème ou d'obtenir des renseignements. Merci de ne pas créer de nouveau ticket si vous avez déjà un ticket ouvert concernant le même problème, vous pouvez utiliser le bouton \"Répondre\" dans ce cas.", "support_formHint": "Ce formulaire peut être utilisé pour créer un nouveau ticket de support. Utilisez-le pour contacter les administrateurs de manière sécurisée afin de résoudre un problème ou d'obtenir des renseignements. Merci de ne pas créer de nouveau ticket si vous avez déjà un ticket ouvert concernant le même problème, vous pouvez utiliser le bouton \"Répondre\" dans ce cas.",
"support_listHint": "Voici la liste des tickets envoyés au support, ainsi que les réponses. Un ticket fermé ne peut pas être ré-ouvert, mais il est possible d'en créer un nouveau. Vous pouvez cacher les tickets qui ont été fermés." "support_listHint": "Voici la liste des tickets envoyés au support, ainsi que les réponses. Un ticket fermé ne peut pas être ré-ouvert, mais il est possible d'en créer un nouveau. Vous pouvez cacher les tickets qui ont été fermés.",
"support_notification": "Un administrateur a répondu à votre ticket de support",
"requestEdit_button": "Demander les droits d'édition",
"requestEdit_dialog": "Êtes-vous sûr de vouloir demander les droits d'édition de ce pad au propriétaire ?",
"requestEdit_confirm": "{1} a demandé les droits d'édition pour le pad <b>{1}</b>. Souhaitez-vous leur accorder les droits ?",
"requestEdit_fromFriend": "Vous êtes amis avec {0}",
"requestEdit_fromStranger": "Vous n'êtes <b>pas</b> amis avec {0}",
"requestEdit_viewPad": "Ouvrir le pad dans un nouvel onglet",
"later": "Décider plus tard",
"requestEdit_request": "{1} souhaite éditer le pad <b>{0}</b>",
"requestEdit_accepted": "{1} vous a accordé les droits d'édition du pad <b>{0}</b>",
"requestEdit_sent": "Demande envoyée",
"uploadFolderButton": "Importer un dossier",
"properties_unknownUser": "{0} utilisateur(s) inconnu(s)"
} }

View File

@ -321,6 +321,7 @@
"fm_newButtonTitle": "Create a new pad or folder, import a file in the current folder", "fm_newButtonTitle": "Create a new pad or folder, import a file in the current folder",
"fm_newFolder": "New folder", "fm_newFolder": "New folder",
"fm_newFile": "New pad", "fm_newFile": "New pad",
"fm_morePads": "More pads",
"fm_folder": "Folder", "fm_folder": "Folder",
"fm_sharedFolder": "Shared folder", "fm_sharedFolder": "Shared folder",
"fm_folderName": "Folder name", "fm_folderName": "Folder name",
@ -383,6 +384,7 @@
"fc_color": "Change color", "fc_color": "Change color",
"fc_open": "Open", "fc_open": "Open",
"fc_open_ro": "Open (read-only)", "fc_open_ro": "Open (read-only)",
"fc_openInCode": "Open in Code editor",
"fc_expandAll": "Expand All", "fc_expandAll": "Expand All",
"fc_collapseAll": "Collapse All", "fc_collapseAll": "Collapse All",
"fc_delete": "Move to trash", "fc_delete": "Move to trash",
@ -554,6 +556,10 @@
"upload_modal_title": "File upload options", "upload_modal_title": "File upload options",
"upload_modal_filename": "File name (extension <em>{0}</em> added automatically)", "upload_modal_filename": "File name (extension <em>{0}</em> added automatically)",
"upload_modal_owner": "Owned file", "upload_modal_owner": "Owned file",
"uploadFolder_modal_title": "Folder upload options",
"uploadFolder_modal_filesPassword": "Files password",
"uploadFolder_modal_owner": "Owned files",
"uploadFolder_modal_forceSave": "Store files in your CryptDrive",
"upload_serverError": "Server Error: unable to upload your file at this time.", "upload_serverError": "Server Error: unable to upload your file at this time.",
"upload_uploadPending": "You already have an upload in progress. Cancel it and upload your new file?", "upload_uploadPending": "You already have an upload in progress. Cancel it and upload your new file?",
"upload_success": "Your file ({0}) has been successfully uploaded and added to your drive.", "upload_success": "Your file ({0}) has been successfully uploaded and added to your drive.",
@ -989,6 +995,9 @@
"sharedFolders_create_owned": "Owned folder", "sharedFolders_create_owned": "Owned folder",
"sharedFolders_create_password": "Folder password", "sharedFolders_create_password": "Folder password",
"sharedFolders_share": "Share this URL with other registered users to give them access to the shared folder. Once they open this URL, the shared folder will be added to the root directory of their CryptDrive.", "sharedFolders_share": "Share this URL with other registered users to give them access to the shared folder. Once they open this URL, the shared folder will be added to the root directory of their CryptDrive.",
"convertFolderToSF_SFParent": "This folder cannot be converted to a shared folder in its current location. Move it outside of the containing shared folder to continue.",
"convertFolderToSF_SFChildren": "This folder cannot be converted to a shared folder because it already contains shared folders. Move those Shared folders elsewhere to continue.",
"convertFolderToSF_confirm": "This folder must be converted to a Shared folder for others to view it. Continue?",
"chrome68": "It seems that you're using the browser Chrome or Chromium version 68. It contains a bug resulting in the page turning completely white after a few seconds or the page being unresponsive to clicks. To fix this issue, you can switch to another tab and come back, or try to scroll in the page. This bug should be fixed in the next version of your browser.", "chrome68": "It seems that you're using the browser Chrome or Chromium version 68. It contains a bug resulting in the page turning completely white after a few seconds or the page being unresponsive to clicks. To fix this issue, you can switch to another tab and come back, or try to scroll in the page. This bug should be fixed in the next version of your browser.",
"autostore_file": "file", "autostore_file": "file",
"autostore_sf": "folder", "autostore_sf": "folder",

View File

@ -8,7 +8,11 @@
"drive": "Drive", "drive": "Drive",
"whiteboard": "Whiteboard", "whiteboard": "Whiteboard",
"file": "File", "file": "File",
"media": "Media" "media": "Media",
"kanban": "Kanban",
"todo": "A Fazer",
"contacts": "Contactos",
"sheet": "SpreadSheet (Beta)"
}, },
"button_newpad": "Novo bloco RTF", "button_newpad": "Novo bloco RTF",
"button_newcode": "Novo bloco de código", "button_newcode": "Novo bloco de código",

View File

@ -102,7 +102,7 @@
"forgetPrompt": "Нажав ОК, вы удалите документ в корзину. Уверены?", "forgetPrompt": "Нажав ОК, вы удалите документ в корзину. Уверены?",
"movedToTrash": "Документ был удалён в корзину.<br><a href=\"/drive/\">Доступ к диску</a>", "movedToTrash": "Документ был удалён в корзину.<br><a href=\"/drive/\">Доступ к диску</a>",
"shareButton": "Поделиться", "shareButton": "Поделиться",
"shareSuccess": "Ссылка скопирована в буфер обмена.", "shareSuccess": "Ссылка скопирована в буфер обмена",
"userListButton": "Список пользователей", "userListButton": "Список пользователей",
"chatButton": "Чат", "chatButton": "Чат",
"userAccountButton": "Ваш профиль", "userAccountButton": "Ваш профиль",
@ -139,36 +139,36 @@
"or": "или", "or": "или",
"tags_title": "Теги (только для вас)", "tags_title": "Теги (только для вас)",
"tags_add": "Обновить теги страницы", "tags_add": "Обновить теги страницы",
"tags_searchHint": "Начните поиск в вашем CryptDrive при помощи # чтобы найти пэды с тегами", "tags_searchHint": "Начните поиск в вашем CryptDrive при помощи # чтобы найти пэды с тегами.",
"tags_notShared": "Ваши теги не разделяются с другими пользователями", "tags_notShared": "Ваши теги не разделяются с другими пользователями",
"button_newsheet": "Новый Лист", "button_newsheet": "Новый Лист",
"newButtonTitle": "Создать новый блокнот", "newButtonTitle": "Создать новый документ",
"useTemplateCancel": "Начать заново (Esc)", "useTemplateCancel": "Начать заново (Esc)",
"previewButtonTitle": "Отобразить или скрыть режим предпросмотра разметки", "previewButtonTitle": "Показать или скрыть просмотр Маркдаун разметки",
"printOptions": "Опции расположения", "printOptions": "Настройки размещения",
"printBackgroundValue": "<b>Текущий фон:</b> <em>{0}</em>", "printBackgroundValue": "<b>Текущий фон:</b> <em>{0}</em>",
"printBackgroundNoValue": "<em>Нет отображаемого фонового изображения</em>", "printBackgroundNoValue": "<em>Фоновое изображение не показано</em>",
"tags_duplicate": "Скопировать тег: {0}", "tags_duplicate": "Скопировать метку: {0}",
"tags_noentry": "Вы не можете присвоить тег удалённому блокноту!", "tags_noentry": "Вы не можете присвоить метку удалённому документу!",
"slideOptionsText": "Опции", "slideOptionsText": "Настройки",
"slideOptionsTitle": "Настроить ваши слайды", "slideOptionsTitle": "Настройте ваши слайды",
"slideOptionsButton": "Сохранить (Enter)", "slideOptionsButton": "Сохранить (Ввод)",
"slide_invalidLess": "Неверный настраиваемый стиль", "slide_invalidLess": "Неверный пользовательский стиль",
"languageButton": "Язык", "languageButton": "Язык",
"languageButtonTitle": "Выберите язык, используемый для подсветки синтаксиса", "languageButtonTitle": "Выберите язык для использования подсветки слов",
"themeButton": "Тема", "themeButton": "Тема",
"themeButtonTitle": "Выберите цветовую тему, используемую в редакторе кода и слайдов", "themeButtonTitle": "Выберите цветовую тему для использования в редакторе кода и слайдов",
"editShare": "Редактирование ссылки", "editShare": "Редактируемая ссылка",
"editShareTitle": "Скопировать редактируемую ссылку", "editShareTitle": "Скопировать редактируемую ссылку в буфер обмена",
"editOpen": "Открыть редактируемую ссылку в новой вкладке", "editOpen": "Открыть редактируемую ссылку в новой вкладке",
"editOpenTitle": "Открыть блокнот в режиме редактирования в новой вкладке", "editOpenTitle": "Открыть данный документ для редактирования в новой вкладке",
"viewShare": "Ссылка только для чтения", "viewShare": "Ссылка только для чтения",
"viewShareTitle": "Скопировать ссылку для чтения в буфер обмена", "viewShareTitle": "Скопировать ссылку только для чтения в буфер обмена",
"viewOpen": "Открыть ссылку в режиме чтения в новой вкладке", "viewOpen": "Открыть ссылку только для чтения в новой вкладке",
"viewOpenTitle": "Открыть блокнот в режиме чтения в новой вкладке", "viewOpenTitle": "Открыть данный документ для чтения в новой вкладке",
"fileShare": "Скопировать ссылку", "fileShare": "Скопировать ссылку",
"getEmbedCode": "Получить код для встраивания", "getEmbedCode": "Получить код для встраивания",
"viewEmbedTitle": "Встроить блокнот на внешнюю страницу", "viewEmbedTitle": "Встроить документ во внешнюю страницу",
"notifyJoined": "{0} присоединился к совместной сессии", "notifyJoined": "{0} присоединился к совместной сессии",
"notifyRenamed": "{0} теперь известен как {1}", "notifyRenamed": "{0} теперь известен как {1}",
"notifyLeft": "{0} покинул совместную сессию", "notifyLeft": "{0} покинул совместную сессию",
@ -258,7 +258,7 @@
"profile_fieldSaved": "Сохранено новое значение: {0}", "profile_fieldSaved": "Сохранено новое значение: {0}",
"profile_viewMyProfile": "Посмотреть мой профиль", "profile_viewMyProfile": "Посмотреть мой профиль",
"contacts_title": "Контакты", "contacts_title": "Контакты",
"contacts_added": "Приглашение принято контактом", "contacts_added": "Приглашение принято контактом.",
"contacts_rejected": "Контакт не принял приглашение", "contacts_rejected": "Контакт не принял приглашение",
"contacts_send": "Отправить", "contacts_send": "Отправить",
"contacts_remove": "Убрать этот контакт", "contacts_remove": "Убрать этот контакт",
@ -302,22 +302,22 @@
"crowdfunding_popup_no": "Не сейчас", "crowdfunding_popup_no": "Не сейчас",
"crowdfunding_popup_never": "Не спрашивать меня снова", "crowdfunding_popup_never": "Не спрашивать меня снова",
"markdown_toc": "Содержимое", "markdown_toc": "Содержимое",
"fm_expirablePad": "Этот блокнот удалится через {0}", "fm_expirablePad": "Этот блокнот истечет {0}",
"fileEmbedTitle": "Вставить файл во внешнюю страницу", "fileEmbedTitle": "Встроить файл во внешнюю страницу",
"kanban_removeItemConfirm": "Вы уверенны, что хотите удалить этот пункт?", "kanban_removeItemConfirm": "Вы уверенны, что хотите удалить этот пункт?",
"settings_backup2": "Скачать мой CryptDrive", "settings_backup2": "Скачать мой CryptDrive",
"settings_backup2Confirm": "Это позволит скачать все пэды и файлы с вашего CryptDrive. Если вы хотите продолжить, выберите имя и нажмите OK", "settings_backup2Confirm": "Это позволит скачать все пэды и файлы с вашего CryptDrive. Если вы хотите продолжить, выберите имя и нажмите OK",
"settings_exportTitle": "Экспортировать Ваш CryptDrive", "settings_exportTitle": "Экспортировать Ваш CryptDrive",
"fileEmbedScript": "Чтобы вставить этот файл, включите этот скрипт один раз на своей странице, чтобы загрузить медиатег:", "fileEmbedScript": "Чтобы вставить этот файл, включите этот скрипт один раз на своей странице, чтобы загрузить медиатег:",
"fileEmbedTag": "Затем поместите медиатег в любое место на странице, куда вы хотите его вставить:", "fileEmbedTag": "Затем поместите медиатег в любое место на странице,в которое вы хотите его вставить:",
"pad_mediatagRatio": "Оставить соотношение", "pad_mediatagRatio": "Оставить соотношение",
"kanban_item": "Элемент {0}", "kanban_item": "Элемент {0}",
"poll_p_encryption": "Все ваши данные зашифрованы, доступ к ним имеют только пользователи, имеющие доступ к этой ссылке. Даже сервер не видит, что вы меняете.", "poll_p_encryption": "Все ваши данные зашифрованы, доступ к ним имеют только пользователи, имеющие доступ к этой ссылке. Даже сервер не видит, что вы меняете.",
"wizardLog": "Нажмите кнопку в левом верхнем углу, чтобы вернуться к опросу", "wizardLog": "Нажмите кнопку в левом верхнем углу, чтобы вернуться к опросу",
"poll_bookmark_col": "Добавить этот столбец в закладку, чтобы он всегда был разблокирован и отображался для вас в начале", "poll_bookmark_col": "Добавить этот столбец в закладку, чтобы он всегда был разблокирован и отображался для вас в начале",
"poll_bookmarked_col": "Это твоя колонка закладок. Она всегда будет разблокирована и отображаться для вас в начале.", "poll_bookmarked_col": "Это твоя колонка закладок. Она всегда будет разблокирована и отображаться для вас в начале.",
"poll_wizardDescription": "Автоматическое создавайте несколько опций путем ввода произвольного количества дат и временных сегментов", "poll_wizardDescription": "Автоматически создавайте несколько опций путем ввода произвольного количества дат и временных сегментов",
"poll_comment_disabled": "Опубликуйте этот опрос с помощью кнопки ✓ для включения комментариев", "poll_comment_disabled": "Опубликуйте этот опрос с помощью кнопки ✓ для включения комментариев.",
"oo_cantUpload": "Загрузка запрещена, если присутствуют другие пользователи.", "oo_cantUpload": "Загрузка запрещена, если присутствуют другие пользователи.",
"oo_uploaded": "Ваша загрузка завершена. Нажмите OK, чтобы перезагрузить страницу или отменить, чтобы остаться в режиме чтения.", "oo_uploaded": "Ваша загрузка завершена. Нажмите OK, чтобы перезагрузить страницу или отменить, чтобы остаться в режиме чтения.",
"canvas_imageEmbed": "Вставьте изображение с вашего компьютера", "canvas_imageEmbed": "Вставьте изображение с вашего компьютера",
@ -367,13 +367,13 @@
"fm_padIsOwnedOther": "Этот пэд принадлежит другому пользователю", "fm_padIsOwnedOther": "Этот пэд принадлежит другому пользователю",
"fm_deletedPads": "Эти пэды больше не существуют на сервере, они были удалены с вашего CryptDrive: {0}", "fm_deletedPads": "Эти пэды больше не существуют на сервере, они были удалены с вашего CryptDrive: {0}",
"fm_tags_name": "Имя тэга", "fm_tags_name": "Имя тэга",
"printCSS": "Пользовательские настройки вида (CSS)", "printCSS": "Пользовательские настройки вида (CSS):",
"viewEmbedTag": "Чтобы встроить данный документ вставьте iframe в нужную страницу. Вы можете настроить внешний вид используя CSS и HTML атрибуты. ", "viewEmbedTag": "Чтобы встроить данный документ, вставьте iframe в нужную страницу. Вы можете настроить внешний вид используя CSS и HTML атрибуты.",
"debug_getGraphText": "Это код DOT для генерации графика истории этого документа:", "debug_getGraphText": "Это код DOT для генерации графика истории этого документа:",
"fm_ownedPadsName": "Собственный", "fm_ownedPadsName": "Собственный",
"fm_info_anonymous": "Вы не вошли в учетную запись, поэтому срок действия ваших пэдов истечет через 3 месяца (<a href=\"https://blog.cryptpad.fr/2017/05/17/You-gotta-log-in/\" target=\"_blank\">find out more</a>). Они хранятся в вашем браузере, поэтому очистка истории может привести к их исчезновению..<br><a href=\"/register/\">Sign up</a> or <a href=\"/login/\">Log in</a> to keep them alive.<br>", "fm_info_anonymous": "Вы не вошли в учетную запись, поэтому срок действия ваших пэдов истечет через 3 месяца (<a href=\"https://blog.cryptpad.fr/2017/05/17/You-gotta-log-in/\" target=\"_blank\">find out more</a>). Они хранятся в вашем браузере, поэтому очистка истории может привести к их исчезновению..<br><a href=\"/register/\">Sign up</a> or <a href=\"/login/\">Log in</a> to keep them alive.<br>",
"fm_backup_title": "Резервная ссылка", "fm_backup_title": "Резервная ссылка",
"fm_burnThisDriveButton": "Удалить всю информацию, хранящуюся на CryptPad в браузере.", "fm_burnThisDriveButton": "Удалить всю информацию, хранящуюся от CryptPad в браузере",
"fm_tags_used": "Количество использований", "fm_tags_used": "Количество использований",
"fm_restoreDrive": "Восстановление прежнего состояния диска. Для достижения наилучших результатов не вносите изменения в диск, пока этот процесс не будет завершен.", "fm_restoreDrive": "Восстановление прежнего состояния диска. Для достижения наилучших результатов не вносите изменения в диск, пока этот процесс не будет завершен.",
"fm_passwordProtected": "Этот документ защищен паролем", "fm_passwordProtected": "Этот документ защищен паролем",
@ -415,7 +415,7 @@
"fm_info_sharedFolder": "Это общая папка. Вы не вошли в систему, поэтому можете получить к ней доступ только в режиме только для чтения.<br><a href=\"/register/\">Sign up</a> или <a href=\"/login/\">Log in</a> для импорта на CryptDrive и его изменения.", "fm_info_sharedFolder": "Это общая папка. Вы не вошли в систему, поэтому можете получить к ней доступ только в режиме только для чтения.<br><a href=\"/register/\">Sign up</a> или <a href=\"/login/\">Log in</a> для импорта на CryptDrive и его изменения.",
"fo_moveFolderToChildError": "Вы не можете переместить папку в одну из нее следующую", "fo_moveFolderToChildError": "Вы не можете переместить папку в одну из нее следующую",
"fo_unavailableName": "Файл или папка с таким же именем уже существуют в новом месте. Переименуйте элемент и повторите попытку.", "fo_unavailableName": "Файл или папка с таким же именем уже существуют в новом месте. Переименуйте элемент и повторите попытку.",
"fs_migration": "Ваш CryptDrive обновляется до новой версии. В результате, текущая страница должна быть перезагружена.<br><strong> перезагрузите эту страницу, чтобы продолжить ей пользоваться.</strong>.", "fs_migration": "Ваш CryptDrive обновляется до новой версии. В результате, текущая страница должна быть перезагружена.<br><strong> перезагрузите эту страницу, чтобы продолжить ей пользоваться.</strong>",
"login_accessDrive": "Доступ к хранилищу", "login_accessDrive": "Доступ к хранилищу",
"login_orNoLogin": "или", "login_orNoLogin": "или",
"login_noSuchUser": "Неверный логин или пароль. Попробуйте еще раз или зарегистрируйтесь", "login_noSuchUser": "Неверный логин или пароль. Попробуйте еще раз или зарегистрируйтесь",
@ -448,5 +448,59 @@
"settings_exportWarning": "Примечание: этот инструмент все еще находится в бета-версии и может иметь проблемы со масштабируемостью. Для повышения производительности рекомендуется оставить данную вкладку сфокусированной.", "settings_exportWarning": "Примечание: этот инструмент все еще находится в бета-версии и может иметь проблемы со масштабируемостью. Для повышения производительности рекомендуется оставить данную вкладку сфокусированной.",
"settings_exportCancel": "Вы уверены, что хотите отменить экспорт? В следующий раз вам придется начинать все сначала.", "settings_exportCancel": "Вы уверены, что хотите отменить экспорт? В следующий раз вам придется начинать все сначала.",
"settings_export_reading": "Читаем ваше хранилище...", "settings_export_reading": "Читаем ваше хранилище...",
"settings_export_download": "Скачиваем и расшифровываем ваши документы..." "settings_export_download": "Скачиваем и расшифровываем ваши документы...",
"contacts_request": "<em>{0}</em> хотел бы добавить вас в список контактов. <b>Принять <b>?",
"contacts_confirmRemove": "Вы уверены, что хотите удалить <em>1{0}</em>2 из ваших контактов?",
"register_acceptTerms": "Я принимаю <a href='/terms.html' tabindex='-1'>1 условия пользования</a>",
"register_warning": "Мы не сможем восстановить ваши данные, если вы потеряете пароль, так как мы не имеем доступа к ним.",
"settings_backupCategory": "Резервное копирование",
"settings_backup": "Резервная копия",
"settings_backupHint2": "Загрузите текущее содержимое всех ваших пэдов. Пэды будут загружены в читаемом формате, если такой формат доступен.",
"settings_export_compressing": "Данные сжимаются..",
"settings_export_done": "Ваше скачивание завершено!",
"settings_exportError": "Посмотреть ошибки",
"settings_exportErrorDescription": "Мы не смогли добавить в экспорт следующие документы:",
"settings_exportErrorEmpty": "Этот документ не может быть экспортирован (пустое или недостоверное содержимое).",
"settings_exportErrorMissing": "Этот документ отсутствует на наших серверах (истек или удален владельцем)",
"settings_exportErrorOther": "При попытке экспорта данного документа возникла ошибка: {0}",
"settings_resetNewTitle": "Очистить хриналище",
"settings_resetButton": "Удалить",
"settings_reset": "Удалите все файлы и папки с CryptDrive",
"settings_resetDone": "Ваше хранилище теперь пустое!",
"settings_resetError": "Неправильный текст верификации. Ваш CryptDrive не был изменен.",
"settings_resetTipsAction": "Сброс",
"settings_resetTips": "Подсказки",
"settings_resetTipsButton": "Сброс доступных подсказок в CryptDrive",
"settings_resetTipsDone": "Теперь все подсказки снова видны.",
"settings_thumbnails": "Иконки",
"settings_disableThumbnailsAction": "Отключить создание иконок в вашем хранилище",
"settings_disableThumbnailsDescription": "Иконки автоматически создаются и сохраняются в браузере при посещении нового документа. Вы можете отключить эту функцию здесь.",
"settings_resetThumbnailsAction": "Очистить",
"settings_resetThumbnailsDescription": "Очистить все иконки документов, хранящиеся в вашем браузере.",
"settings_resetThumbnailsDone": "Все иконки были удалены.",
"settings_import": "Импортировать",
"settings_importDone": "Импортирование завершено",
"settings_autostoreTitle": "Хранилище документов в CryptDrive",
"settings_autostoreYes": "Автоматически",
"settings_autostoreNo": "Вручную (никогда не спрашивать)",
"settings_autostoreMaybe": "Вручную (всегда спрашивать)",
"settings_userFeedbackTitle": "Обратная связь",
"settings_userFeedbackHint2": "Содержимое вашего документа никогда не будет передаваться на сервер.",
"fm_alert_anonymous": "Здравствуйте, в настоящее время вы используете CryptPad анонимно, это нормально, но ваши пэды могут быть удалены после периода бездействия. Мы отключили расширенные возможности хранилища для анонимных пользователей, потому что хотим быть уверенными, что это небезопасное место для хранения вещей. Вы можете <a href=\"https://blog.cryptpad.fr/2017/05/17/You-gotta-log-in/\" target=\"_blank\">1читать далее</a>2 о том, почему мы это делаем и почему вам стоит <a href=\"/register/\">зарегистрироваться</a>4 and <a href=\"/login/\">5Log in</a>6.",
"settings_resetPrompt": "Это действие удалит все документы с диска.<br>Вы уверены, что хотите продолжить?<br>Напишите \"<em>Я люблю CryptPad</em>\" для подтверждения.",
"settings_importTitle": "Импортируйте последние документы данного браузера в ваше хранилище",
"settings_importConfirm": "Вы уверены, что хотите импортировать последние документы из этого браузера в хранилище вашего пользователя?",
"settings_userFeedbackHint1": "CryptPad держит очень простую обратную связь с сервером, чтобы мы знали, как улучшить ваше пользование.\n",
"settings_userFeedback": "Включить телеметрию",
"settings_deleteTitle": "Удаление аккаунта",
"settings_deleteHint": "Удаление аккаунта является постоянным. Ваш CryptDrive и список пэдов будут удалены с сервера. Остальные ваши пэды будут удалены через 90 дней, если никто другой не сохранил их в CryptDrive.",
"settings_deleteButton": "Удалить ваш аккаунт",
"settings_deleteModal": "Обменивайтесь следующей информацией с администратором CryptPad, чтобы удалить ваши данные с сервера.",
"settings_deleteConfirm": "Нажмите OK, чтобы удалить ваш аккаунт навсегда. Вы уверены?",
"settings_deleted": "Ваша учетная запись пользователя удалена. Нажмите OK, чтобы перейти на главную страницу.",
"settings_publicSigningKey": "Публичный ключ подписи",
"settings_usage": "Использование",
"settings_usageTitle": "Смотрите общий размер ваших прикрепленных документов в мегабайтах",
"settings_pinningNotAvailable": "Прикрепленные документы доступны только зарегистрированным пользователям.",
"settings_pinningError": "Что-то пошло не так"
} }

View File

@ -82,6 +82,7 @@ define([
var faCollapseAll = 'fa-minus-square-o'; var faCollapseAll = 'fa-minus-square-o';
var faShared = 'fa-shhare-alt'; var faShared = 'fa-shhare-alt';
var faReadOnly = 'fa-eye'; var faReadOnly = 'fa-eye';
var faOpenInCode = 'cptools-code';
var faRename = 'fa-pencil'; var faRename = 'fa-pencil';
var faColor = 'cptools-palette'; var faColor = 'cptools-palette';
var faTrash = 'fa-trash'; var faTrash = 'fa-trash';
@ -91,7 +92,7 @@ define([
var faEmpty = 'fa-trash-o'; var faEmpty = 'fa-trash-o';
var faRestore = 'fa-repeat'; var faRestore = 'fa-repeat';
var faShowParent = 'fa-location-arrow'; var faShowParent = 'fa-location-arrow';
var faDownload = 'cptools-file'; var faDownload = 'fa-download';
var $folderIcon = $('<span>', { var $folderIcon = $('<span>', {
"class": faFolder + " cptools cp-app-drive-icon-folder cp-app-drive-content-icon" "class": faFolder + " cptools cp-app-drive-icon-folder cp-app-drive-content-icon"
}); });
@ -343,6 +344,10 @@ define([
'tabindex': '-1', 'tabindex': '-1',
'data-icon': faReadOnly, 'data-icon': faReadOnly,
}, Messages.fc_open_ro)), }, Messages.fc_open_ro)),
h('li', h('a.cp-app-drive-context-openincode.dropdown-item', {
'tabindex': '-1',
'data-icon': faOpenInCode,
}, Messages.fc_openInCode)),
$separator.clone()[0], $separator.clone()[0],
h('li', h('a.cp-app-drive-context-expandall.dropdown-item', { h('li', h('a.cp-app-drive-context-expandall.dropdown-item', {
'tabindex': '-1', 'tabindex': '-1',
@ -353,22 +358,20 @@ define([
'data-icon': faCollapseAll, 'data-icon': faCollapseAll,
}, Messages.fc_collapseAll)), }, Messages.fc_collapseAll)),
$separator.clone()[0], $separator.clone()[0],
h('li', h('a.cp-app-drive-context-color.dropdown-item.cp-app-drive-context-editable', {
'tabindex': '-1',
'data-icon': faColor,
}, Messages.fc_color)),
h('li', h('a.cp-app-drive-context-download.dropdown-item', {
'tabindex': '-1',
'data-icon': faDownload,
}, Messages.download_mt_button)),
h('li', h('a.cp-app-drive-context-share.dropdown-item', {
'tabindex': '-1',
'data-icon': 'fa-shhare-alt',
}, Messages.shareButton)),
h('li', h('a.cp-app-drive-context-openparent.dropdown-item', { h('li', h('a.cp-app-drive-context-openparent.dropdown-item', {
'tabindex': '-1', 'tabindex': '-1',
'data-icon': faShowParent, 'data-icon': faShowParent,
}, Messages.fm_openParent)), }, Messages.fm_openParent)),
$separator.clone()[0],
h('li', h('a.cp-app-drive-context-share.dropdown-item', {
'tabindex': '-1',
'data-icon': 'fa-shhare-alt',
}, Messages.shareButton)),
h('li', h('a.cp-app-drive-context-download.dropdown-item', {
'tabindex': '-1',
'data-icon': faDownload,
}, Messages.download_mt_button)),
$separator.clone()[0],
h('li', h('a.cp-app-drive-context-newfolder.dropdown-item.cp-app-drive-context-editable', { h('li', h('a.cp-app-drive-context-newfolder.dropdown-item.cp-app-drive-context-editable', {
'tabindex': '-1', 'tabindex': '-1',
'data-icon': faFolder, 'data-icon': faFolder,
@ -377,10 +380,6 @@ define([
'tabindex': '-1', 'tabindex': '-1',
'data-icon': faSharedFolder, 'data-icon': faSharedFolder,
}, Messages.fc_newsharedfolder)), }, Messages.fc_newsharedfolder)),
h('li', h('a.cp-app-drive-context-hashtag.dropdown-item.cp-app-drive-context-editable', {
'tabindex': '-1',
'data-icon': faTags,
}, Messages.fc_hashtag)),
$separator.clone()[0], $separator.clone()[0],
h('li', h('a.cp-app-drive-context-newdoc.dropdown-item.cp-app-drive-context-editable', { h('li', h('a.cp-app-drive-context-newdoc.dropdown-item.cp-app-drive-context-editable', {
'tabindex': '-1', 'tabindex': '-1',
@ -401,7 +400,7 @@ define([
h('a.cp-app-drive-context-newdocmenu.dropdown-item', { h('a.cp-app-drive-context-newdocmenu.dropdown-item', {
'tabindex': '-1', 'tabindex': '-1',
'data-icon': "fa-plus", 'data-icon': "fa-plus",
}, Messages.fm_morePads || "More pads"), //XXX }, Messages.fm_morePads),
h("ul.dropdown-menu", [ h("ul.dropdown-menu", [
h('li', h('a.cp-app-drive-context-newdoc.dropdown-item.cp-app-drive-context-editable', { h('li', h('a.cp-app-drive-context-newdoc.dropdown-item.cp-app-drive-context-editable', {
'tabindex': '-1', 'tabindex': '-1',
@ -439,6 +438,15 @@ define([
'tabindex': '-1', 'tabindex': '-1',
'data-icon': faRename, 'data-icon': faRename,
}, Messages.fc_rename)), }, Messages.fc_rename)),
h('li', h('a.cp-app-drive-context-color.dropdown-item.cp-app-drive-context-editable', {
'tabindex': '-1',
'data-icon': faColor,
}, Messages.fc_color)),
h('li', h('a.cp-app-drive-context-hashtag.dropdown-item.cp-app-drive-context-editable', {
'tabindex': '-1',
'data-icon': faTags,
}, Messages.fc_hashtag)),
$separator.clone()[0],
h('li', h('a.cp-app-drive-context-delete.dropdown-item.cp-app-drive-context-editable', { h('li', h('a.cp-app-drive-context-delete.dropdown-item.cp-app-drive-context-editable', {
'tabindex': '-1', 'tabindex': '-1',
'data-icon': faTrash, 'data-icon': faTrash,
@ -455,6 +463,7 @@ define([
'tabindex': '-1', 'tabindex': '-1',
'data-icon': faDelete, 'data-icon': faDelete,
}, Messages.fc_remove_sharedfolder)), }, Messages.fc_remove_sharedfolder)),
$separator.clone()[0],
h('li', h('a.cp-app-drive-context-properties.dropdown-item', { h('li', h('a.cp-app-drive-context-properties.dropdown-item', {
'tabindex': '-1', 'tabindex': '-1',
'data-icon': faProperties, 'data-icon': faProperties,
@ -1092,7 +1101,8 @@ define([
hide.push('openparent'); hide.push('openparent');
} }
if (!$element.is('.cp-border-color-file')) { if (!$element.is('.cp-border-color-file')) {
hide.push('download'); //hide.push('download');
hide.push('openincode');
} }
if ($element.is('.cp-app-drive-element-file')) { if ($element.is('.cp-app-drive-element-file')) {
// No folder in files // No folder in files
@ -1103,6 +1113,11 @@ define([
} else if ($element.is('.cp-app-drive-element-noreadonly')) { } else if ($element.is('.cp-app-drive-element-noreadonly')) {
hide.push('openro'); // Remove open 'view' mode hide.push('openro'); // Remove open 'view' mode
} }
// if it's not a plain text file
var metadata = manager.getFileData(manager.find(path));
if (!metadata || !Util.isPlainTextFile(metadata.fileType, metadata.title)) {
hide.push('openincode');
}
} else if ($element.is('.cp-app-drive-element-sharedf')) { } else if ($element.is('.cp-app-drive-element-sharedf')) {
if (containsFolder) { if (containsFolder) {
// More than 1 folder selected: cannot create a new subfolder // More than 1 folder selected: cannot create a new subfolder
@ -1112,6 +1127,7 @@ define([
} }
containsFolder = true; containsFolder = true;
hide.push('openro'); hide.push('openro');
hide.push('openincode');
hide.push('hashtag'); hide.push('hashtag');
hide.push('delete'); hide.push('delete');
//hide.push('deleteowned'); //hide.push('deleteowned');
@ -1124,6 +1140,7 @@ define([
} }
containsFolder = true; containsFolder = true;
hide.push('openro'); hide.push('openro');
hide.push('openincode');
hide.push('properties'); hide.push('properties');
hide.push('share'); hide.push('share');
hide.push('hashtag'); hide.push('hashtag');
@ -1157,6 +1174,8 @@ define([
hide.push('openparent'); hide.push('openparent');
hide.push('hashtag'); hide.push('hashtag');
hide.push('download'); hide.push('download');
hide.push('share');
hide.push('openincode'); // can't because of race condition
} }
if (containsFolder && paths.length > 1) { if (containsFolder && paths.length > 1) {
// Cannot open multiple folders // Cannot open multiple folders
@ -1173,7 +1192,7 @@ define([
show = ['newfolder', 'newsharedfolder', 'newdoc']; show = ['newfolder', 'newsharedfolder', 'newdoc'];
break; break;
case 'tree': case 'tree':
show = ['open', 'openro', 'expandall', 'collapseall', 'color', 'download', 'share', 'rename', 'delete', 'deleteowned', 'removesf', 'properties', 'hashtag']; show = ['open', 'openro', 'openincode', 'expandall', 'collapseall', 'color', 'download', 'share', 'rename', 'delete', 'deleteowned', 'removesf', 'properties', 'hashtag'];
break; break;
case 'default': case 'default':
show = ['open', 'openro', 'share', 'openparent', 'delete', 'deleteowned', 'properties', 'hashtag']; show = ['open', 'openro', 'share', 'openparent', 'delete', 'deleteowned', 'properties', 'hashtag'];
@ -3593,11 +3612,32 @@ define([
}); });
}); });
}; };
var downloadFolder = function (folderElement, folderName, sfId) {
var todo = function (data) {
data.folder = folderElement;
data.sharedFolderId = sfId;
data.folderName = Util.fixFileName(folderName) + '.zip';
APP.FM.downloadFolder(data, function (err, obj) {
console.log(err, obj);
console.log('DONE');
});
};
todo({
uo: proxy,
sf: folders,
});
};
$contextMenu.on("click", "a", function(e) { $contextMenu.on("click", "a", function(e) {
e.stopPropagation(); e.stopPropagation();
var paths = $contextMenu.data('paths'); var paths = $contextMenu.data('paths');
var pathsList = []; var pathsList = [];
var type = $contextMenu.attr('data-menu-type'); var type = $contextMenu.attr('data-menu-type');
var $this = $(this);
var el, data; var el, data;
if (paths.length === 0) { if (paths.length === 0) {
@ -3606,11 +3646,11 @@ define([
return; return;
} }
if ($(this).hasClass("cp-app-drive-context-rename")) { if ($this.hasClass("cp-app-drive-context-rename")) {
if (paths.length !== 1) { return; } if (paths.length !== 1) { return; }
displayRenameInput(paths[0].element, paths[0].path); displayRenameInput(paths[0].element, paths[0].path);
} }
else if ($(this).hasClass("cp-app-drive-context-color")) { else if ($this.hasClass("cp-app-drive-context-color")) {
var currentColor = getFolderColor(paths[0].path); var currentColor = getFolderColor(paths[0].path);
pickFolderColor(paths[0].element, currentColor, function (color) { pickFolderColor(paths[0].element, currentColor, function (color) {
paths.forEach(function (p) { paths.forEach(function (p) {
@ -3619,24 +3659,24 @@ define([
refresh(); refresh();
}); });
} }
else if($(this).hasClass("cp-app-drive-context-delete")) { else if($this.hasClass("cp-app-drive-context-delete")) {
if (!APP.loggedIn) { if (!APP.loggedIn) {
return void deletePaths(paths); return void deletePaths(paths);
} }
paths.forEach(function (p) { pathsList.push(p.path); }); paths.forEach(function (p) { pathsList.push(p.path); });
moveElements(pathsList, [TRASH], false, refresh); moveElements(pathsList, [TRASH], false, refresh);
} }
else if ($(this).hasClass('cp-app-drive-context-deleteowned')) { else if ($this.hasClass('cp-app-drive-context-deleteowned')) {
deleteOwnedPaths(paths); deleteOwnedPaths(paths);
} }
else if ($(this).hasClass('cp-app-drive-context-open')) { else if ($this.hasClass('cp-app-drive-context-open')) {
paths.forEach(function (p) { paths.forEach(function (p) {
var $element = p.element; var $element = p.element;
$element.click(); $element.click();
$element.dblclick(); $element.dblclick();
}); });
} }
else if ($(this).hasClass('cp-app-drive-context-openro')) { else if ($this.hasClass('cp-app-drive-context-openro')) {
paths.forEach(function (p) { paths.forEach(function (p) {
var el = manager.find(p.path); var el = manager.find(p.path);
if (paths[0].path[0] === SHARED_FOLDER && APP.newSharedFolder) { if (paths[0].path[0] === SHARED_FOLDER && APP.newSharedFolder) {
@ -3654,10 +3694,29 @@ define([
openFile(null, href); openFile(null, href);
}); });
} }
else if ($(this).hasClass('cp-app-drive-context-expandall') || else if ($this.hasClass('cp-app-drive-context-openincode')) {
$(this).hasClass('cp-app-drive-context-collapseall')) {
if (paths.length !== 1) { return; } if (paths.length !== 1) { return; }
var opened = $(this).hasClass('cp-app-drive-context-expandall'); var p = paths[0];
el = manager.find(p.path);
var metadata = manager.getFileData(el);
var simpleData = {
title: metadata.filename || metadata.title,
href: metadata.href,
password: metadata.password,
channel: metadata.channel,
};
nThen(function (waitFor) {
common.sessionStorage.put(Constants.newPadFileData, JSON.stringify(simpleData), waitFor());
common.sessionStorage.put(Constants.newPadPathKey, currentPath, waitFor());
}).nThen(function () {
common.openURL('/code/');
});
}
else if ($this.hasClass('cp-app-drive-context-expandall') ||
$this.hasClass('cp-app-drive-context-collapseall')) {
if (paths.length !== 1) { return; }
var opened = $this.hasClass('cp-app-drive-context-expandall');
var openRecursive = function (path) { var openRecursive = function (path) {
setFolderOpened(path, opened); setFolderOpened(path, opened);
var folderContent = manager.find(path); var folderContent = manager.find(path);
@ -3680,17 +3739,49 @@ define([
openRecursive(paths[0].path); openRecursive(paths[0].path);
refresh(); refresh();
} }
else if ($(this).hasClass('cp-app-drive-context-download')) {
else if ($this.hasClass('cp-app-drive-context-download')) {
if (paths.length !== 1) { return; } if (paths.length !== 1) { return; }
el = manager.find(paths[0].path); var path = paths[0];
if (!manager.isFile(el)) { return; } el = manager.find(path.path);
data = manager.getFileData(el); // folder
APP.FM.downloadFile(data, function (err, obj) { if (manager.isFolder(el)) {
console.log(err, obj); // folder
console.log('DONE'); var name, folderEl;
}); if (!manager.isSharedFolder(el)) {
name = path.path[path.path.length - 1];
folderEl = el;
downloadFolder(folderEl, name);
}
// shared folder
else {
data = manager.getSharedFolderData(el);
name = data.title;
folderEl = manager.find(path.path.concat("root"));
downloadFolder(folderEl, name, el);
}
}
// file
else if (manager.isFile(el)) {
// imported file
if (path.element.is(".cp-border-color-file")) {
data = manager.getFileData(el);
APP.FM.downloadFile(data, function (err, obj) {
console.log(err, obj);
console.log('DONE');
});
}
// pad
else {
data = manager.getFileData(el);
APP.FM.downloadPad(data, function (err, obj) {
console.log(err, obj);
console.log('DONE');
});
}
}
} }
else if ($(this).hasClass('cp-app-drive-context-share')) { else if ($this.hasClass('cp-app-drive-context-share')) {
if (paths.length !== 1) { return; } if (paths.length !== 1) { return; }
el = manager.find(paths[0].path); el = manager.find(paths[0].path);
var parsed, modal; var parsed, modal;
@ -3741,7 +3832,7 @@ define([
wide: Object.keys(friends).length !== 0 wide: Object.keys(friends).length !== 0
}); });
} }
else if ($(this).hasClass('cp-app-drive-context-newfolder')) { else if ($this.hasClass('cp-app-drive-context-newfolder')) {
if (paths.length !== 1) { return; } if (paths.length !== 1) { return; }
var onFolderCreated = function (err, info) { var onFolderCreated = function (err, info) {
if (err) { return void logError(err); } if (err) { return void logError(err); }
@ -3754,21 +3845,21 @@ define([
} }
manager.addFolder(paths[0].path, null, onFolderCreated); manager.addFolder(paths[0].path, null, onFolderCreated);
} }
else if ($(this).hasClass('cp-app-drive-context-newsharedfolder')) { else if ($this.hasClass('cp-app-drive-context-newsharedfolder')) {
if (paths.length !== 1) { return; } if (paths.length !== 1) { return; }
addSharedFolderModal(function (obj) { addSharedFolderModal(function (obj) {
if (!obj) { return; } if (!obj) { return; }
manager.addSharedFolder(paths[0].path, obj, refresh); manager.addSharedFolder(paths[0].path, obj, refresh);
}); });
} }
else if ($(this).hasClass("cp-app-drive-context-newdoc")) { else if ($this.hasClass("cp-app-drive-context-newdoc")) {
var ntype = $(this).data('type') || 'pad'; var ntype = $this.data('type') || 'pad';
var path2 = manager.isPathIn(currentPath, [TRASH]) ? '' : currentPath; var path2 = manager.isPathIn(currentPath, [TRASH]) ? '' : currentPath;
common.sessionStorage.put(Constants.newPadPathKey, path2, function () { common.sessionStorage.put(Constants.newPadPathKey, path2, function () {
common.openURL('/' + ntype + '/'); common.openURL('/' + ntype + '/');
}); });
} }
else if ($(this).hasClass("cp-app-drive-context-properties")) { else if ($this.hasClass("cp-app-drive-context-properties")) {
if (type === 'trash') { if (type === 'trash') {
var pPath = paths[0].path; var pPath = paths[0].path;
if (paths.length !== 1 || pPath.length !== 4) { return; } if (paths.length !== 1 || pPath.length !== 4) { return; }
@ -3788,7 +3879,7 @@ define([
UI.alert($prop[0], undefined, true); UI.alert($prop[0], undefined, true);
}); });
} }
else if ($(this).hasClass("cp-app-drive-context-hashtag")) { else if ($this.hasClass("cp-app-drive-context-hashtag")) {
if (paths.length !== 1) { return; } if (paths.length !== 1) { return; }
el = manager.find(paths[0].path); el = manager.find(paths[0].path);
data = manager.getFileData(el); data = manager.getFileData(el);
@ -3796,7 +3887,7 @@ define([
var href = data.href || data.roHref; var href = data.href || data.roHref;
common.updateTags(href); common.updateTags(href);
} }
else if ($(this).hasClass("cp-app-drive-context-empty")) { else if ($this.hasClass("cp-app-drive-context-empty")) {
if (paths.length !== 1 || !paths[0].element if (paths.length !== 1 || !paths[0].element
|| !manager.comparePath(paths[0].path, [TRASH])) { || !manager.comparePath(paths[0].path, [TRASH])) {
log(Messages.fm_forbidden); log(Messages.fm_forbidden);
@ -3807,13 +3898,13 @@ define([
manager.emptyTrash(refresh); manager.emptyTrash(refresh);
}); });
} }
else if ($(this).hasClass("cp-app-drive-context-remove")) { else if ($this.hasClass("cp-app-drive-context-remove")) {
return void deletePaths(paths); return void deletePaths(paths);
} }
else if ($(this).hasClass("cp-app-drive-context-removesf")) { else if ($this.hasClass("cp-app-drive-context-removesf")) {
return void deletePaths(paths); return void deletePaths(paths);
} }
else if ($(this).hasClass("cp-app-drive-context-restore")) { else if ($this.hasClass("cp-app-drive-context-restore")) {
if (paths.length !== 1) { return; } if (paths.length !== 1) { return; }
var restorePath = paths[0].path; var restorePath = paths[0].path;
var restoreName = paths[0].path[paths[0].path.length - 1]; var restoreName = paths[0].path[paths[0].path.length - 1];
@ -3830,7 +3921,7 @@ define([
manager.restore(restorePath, refresh); manager.restore(restorePath, refresh);
}); });
} }
else if ($(this).hasClass("cp-app-drive-context-openparent")) { else if ($this.hasClass("cp-app-drive-context-openparent")) {
if (paths.length !== 1) { return; } if (paths.length !== 1) { return; }
var parentPath = paths[0].path.slice(); var parentPath = paths[0].path.slice();
if (manager.isInTrashRoot(parentPath)) { parentPath = [TRASH]; } if (manager.isInTrashRoot(parentPath)) { parentPath = [TRASH]; }

View File

@ -12,7 +12,7 @@ define([
'/customize/credential.js', '/customize/credential.js',
'/customize/application_config.js', '/customize/application_config.js',
'/api/config', '/api/config',
'/settings/make-backup.js', '/common/make-backup.js',
'/common/common-feedback.js', '/common/common-feedback.js',
'/common/jscolor.js', '/common/jscolor.js',
@ -1083,18 +1083,9 @@ define([
var exportDrive = function () { var exportDrive = function () {
Feedback.send('FULL_DRIVE_EXPORT_START'); Feedback.send('FULL_DRIVE_EXPORT_START');
var todo = function (data, filename) { var todo = function (data, filename) {
var getPad = function (data, cb) {
sframeChan.query("Q_CRYPTGET", data, function (err, obj) {
if (err) { return void cb(err); }
if (obj.error) { return void cb(obj.error); }
cb(null, obj.data);
}, { timeout: 60000 });
};
var ui = createExportUI(); var ui = createExportUI();
var bu = Backup.create(data, getPad, function (blob, errors) { var bu = Backup.create(data, common.getPad, function (blob, errors) {
console.log(blob);
saveAs(blob, filename); saveAs(blob, filename);
sframeChan.event('EV_CRYPTGET_DISCONNECT'); sframeChan.event('EV_CRYPTGET_DISCONNECT');
ui.complete(function () { ui.complete(function () {