Make a copy
This commit is contained in:
parent
2cceb54aac
commit
3abe522a9f
@ -2158,6 +2158,17 @@ define([
|
|||||||
if (data.accept) { $input.attr('accept', data.accept); }
|
if (data.accept) { $input.attr('accept', data.accept); }
|
||||||
button.click(function () { $input.click(); });
|
button.click(function () { $input.click(); });
|
||||||
break;
|
break;
|
||||||
|
case 'copy':
|
||||||
|
button = $('<button>', {
|
||||||
|
'class': 'fa fa-clone cp-toolbar-icon-import',
|
||||||
|
title: Messages.makeACopy,
|
||||||
|
}).append($('<span>', {'class': 'cp-toolbar-drawer-element'}).text(Messages.makeACopy));
|
||||||
|
button
|
||||||
|
.click(common.prepareFeedback(type))
|
||||||
|
.click(function () {
|
||||||
|
sframeChan.query('EV_MAKE_A_COPY');
|
||||||
|
});
|
||||||
|
break;
|
||||||
case 'importtemplate':
|
case 'importtemplate':
|
||||||
if (!AppConfig.enableTemplates) { return; }
|
if (!AppConfig.enableTemplates) { return; }
|
||||||
if (!common.isLoggedIn()) { return; }
|
if (!common.isLoggedIn()) { return; }
|
||||||
|
|||||||
@ -543,6 +543,25 @@ define([
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
var fixPadMetadata = function (parsed) {
|
||||||
|
var meta;
|
||||||
|
if (Array.isArray(parsed) && typeof(parsed[3]) === "object") {
|
||||||
|
meta = parsed[3].metadata; // pad
|
||||||
|
} else if (parsed.info) {
|
||||||
|
meta = parsed.info; // poll
|
||||||
|
} else {
|
||||||
|
meta = parsed.metadata;
|
||||||
|
}
|
||||||
|
if (typeof(meta) === "object") {
|
||||||
|
meta.defaultTitle = meta.title || meta.defaultTitle;
|
||||||
|
meta.title = "";
|
||||||
|
delete meta.users;
|
||||||
|
delete meta.chat2;
|
||||||
|
delete meta.chat;
|
||||||
|
delete meta.cursor;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
common.useTemplate = function (data, Crypt, cb, optsPut) {
|
common.useTemplate = function (data, Crypt, cb, optsPut) {
|
||||||
// opts is used to overrides options for chainpad-netflux in cryptput
|
// opts is used to overrides options for chainpad-netflux in cryptput
|
||||||
// it allows us to add owners and expiration time if it is a new file
|
// it allows us to add owners and expiration time if it is a new file
|
||||||
@ -576,24 +595,7 @@ define([
|
|||||||
try {
|
try {
|
||||||
// Try to fix the title before importing the template
|
// Try to fix the title before importing the template
|
||||||
var parsed = JSON.parse(val);
|
var parsed = JSON.parse(val);
|
||||||
var meta;
|
fixPadMetadata(parsed);
|
||||||
if (Array.isArray(parsed) && typeof(parsed[3]) === "object") {
|
|
||||||
meta = parsed[3].metadata; // pad
|
|
||||||
} else if (parsed.info) {
|
|
||||||
meta = parsed.info; // poll
|
|
||||||
} else {
|
|
||||||
meta = parsed.metadata;
|
|
||||||
}
|
|
||||||
if (typeof(meta) === "object") {
|
|
||||||
meta.defaultTitle = meta.title || meta.defaultTitle;
|
|
||||||
meta.title = "";
|
|
||||||
delete meta.users;
|
|
||||||
delete meta.chat2;
|
|
||||||
delete meta.chat;
|
|
||||||
delete meta.cursor;
|
|
||||||
if (data.chat) { meta.chat2 = data.chat; }
|
|
||||||
if (data.cursor) { meta.cursor = data.cursor; }
|
|
||||||
}
|
|
||||||
val = JSON.stringify(parsed);
|
val = JSON.stringify(parsed);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.log("Can't fix template title", e);
|
console.log("Can't fix template title", e);
|
||||||
@ -608,25 +610,57 @@ define([
|
|||||||
var data = common.fromFileData;
|
var data = common.fromFileData;
|
||||||
var parsed = Hash.parsePadUrl(data.href);
|
var parsed = Hash.parsePadUrl(data.href);
|
||||||
var parsed2 = Hash.parsePadUrl(currentPad.href);
|
var parsed2 = Hash.parsePadUrl(currentPad.href);
|
||||||
var hash = parsed.hash;
|
|
||||||
|
if (parsed2.type === 'poll') { optsPut.initialState = '{}'; }
|
||||||
|
|
||||||
|
var val;
|
||||||
|
Nthen(function(_waitFor) {
|
||||||
|
// If pad, use cryptget
|
||||||
|
if (parsed.hashData && parsed.hashData.type === 'pad') {
|
||||||
|
var optsGet = {
|
||||||
|
password: data.password,
|
||||||
|
initialState: parsed.type === 'poll' ? '{}' : undefined
|
||||||
|
};
|
||||||
|
Crypt.get(parsed.hash, _waitFor(function (err, _val) {
|
||||||
|
if (err) {
|
||||||
|
_waitFor.abort();
|
||||||
|
return void cb();
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
val = JSON.parse(_val);
|
||||||
|
fixPadMetadata(val);
|
||||||
|
} catch (e) {
|
||||||
|
_waitFor.abort();
|
||||||
|
return void cb();
|
||||||
|
}
|
||||||
|
}), optsGet);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
var name = data.title;
|
var name = data.title;
|
||||||
var secret = Hash.getSecrets('file', hash, data.password);
|
var secret = Hash.getSecrets(parsed.type, parsed.hash, data.password);
|
||||||
var src = fileHost + Hash.getBlobPathFromHex(secret.channel);
|
var src = fileHost + Hash.getBlobPathFromHex(secret.channel);
|
||||||
var key = secret.keys && secret.keys.cryptKey;
|
var key = secret.keys && secret.keys.cryptKey;
|
||||||
|
|
||||||
var u8;
|
var u8;
|
||||||
var res;
|
var res;
|
||||||
var mode;
|
var mode;
|
||||||
var val;
|
|
||||||
Nthen(function(waitFor) {
|
// Otherwise, it's a text blob "open in code": get blob data & convert format
|
||||||
|
Nthen(function (waitFor) {
|
||||||
Util.fetch(src, waitFor(function (err, _u8) {
|
Util.fetch(src, waitFor(function (err, _u8) {
|
||||||
if (err) { return void waitFor.abort(); }
|
if (err) {
|
||||||
|
_waitFor.abort();
|
||||||
|
return void waitFor.abort();
|
||||||
|
}
|
||||||
u8 = _u8;
|
u8 = _u8;
|
||||||
}));
|
}));
|
||||||
}).nThen(function (waitFor) {
|
}).nThen(function (waitFor) {
|
||||||
require(["/file/file-crypto.js"], waitFor(function (FileCrypto) {
|
require(["/file/file-crypto.js"], waitFor(function (FileCrypto) {
|
||||||
FileCrypto.decrypt(u8, key, waitFor(function (err, _res) {
|
FileCrypto.decrypt(u8, key, waitFor(function (err, _res) {
|
||||||
if (err || !_res.content) { return void waitFor.abort(); }
|
if (err || !_res.content) {
|
||||||
|
_waitFor.abort();
|
||||||
|
return void waitFor.abort();
|
||||||
|
}
|
||||||
res = _res;
|
res = _res;
|
||||||
}));
|
}));
|
||||||
}));
|
}));
|
||||||
@ -658,8 +692,14 @@ define([
|
|||||||
};
|
};
|
||||||
}));
|
}));
|
||||||
reader.readAsText(res.content);
|
reader.readAsText(res.content);
|
||||||
|
}).nThen(_waitFor());
|
||||||
}).nThen(function () {
|
}).nThen(function () {
|
||||||
Crypt.put(parsed2.hash, JSON.stringify(val), cb, optsPut);
|
Crypt.put(parsed2.hash, JSON.stringify(val), function () {
|
||||||
|
cb();
|
||||||
|
Crypt.get(parsed2.hash, function (err, val) {
|
||||||
|
console.warn(val);
|
||||||
|
});
|
||||||
|
}, optsPut);
|
||||||
});
|
});
|
||||||
|
|
||||||
};
|
};
|
||||||
@ -1906,6 +1946,9 @@ define([
|
|||||||
// if a pad is created from a file
|
// if a pad is created from a file
|
||||||
if (sessionStorage[Constants.newPadFileData]) {
|
if (sessionStorage[Constants.newPadFileData]) {
|
||||||
common.fromFileData = JSON.parse(sessionStorage[Constants.newPadFileData]);
|
common.fromFileData = JSON.parse(sessionStorage[Constants.newPadFileData]);
|
||||||
|
var _parsed1 = Hash.parsePadUrl(common.fromFileData.href);
|
||||||
|
var _parsed2 = Hash.parsePadUrl(window.location.href);
|
||||||
|
if (_parsed1.type !== _parsed2.type) { delete common.fromFileData; }
|
||||||
delete sessionStorage[Constants.newPadFileData];
|
delete sessionStorage[Constants.newPadFileData];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -78,6 +78,7 @@ define([
|
|||||||
var faRename = 'fa-pencil';
|
var faRename = 'fa-pencil';
|
||||||
var faColor = 'cptools-palette';
|
var faColor = 'cptools-palette';
|
||||||
var faTrash = 'fa-trash';
|
var faTrash = 'fa-trash';
|
||||||
|
var faCopy = 'fa-clone';
|
||||||
var faDelete = 'fa-eraser';
|
var faDelete = 'fa-eraser';
|
||||||
var faProperties = 'fa-info-circle';
|
var faProperties = 'fa-info-circle';
|
||||||
var faTags = 'fa-hashtag';
|
var faTags = 'fa-hashtag';
|
||||||
@ -431,6 +432,10 @@ define([
|
|||||||
'data-icon': faTags,
|
'data-icon': faTags,
|
||||||
}, Messages.fc_hashtag)),
|
}, Messages.fc_hashtag)),
|
||||||
$separator.clone()[0],
|
$separator.clone()[0],
|
||||||
|
h('li', h('a.cp-app-drive-context-makeacopy.dropdown-item.cp-app-drive-context-editable', {
|
||||||
|
'tabindex': '-1',
|
||||||
|
'data-icon': faCopy,
|
||||||
|
}, Messages.makeACopy)),
|
||||||
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,
|
||||||
@ -1179,6 +1184,9 @@ define([
|
|||||||
if (!metadata || !Util.isPlainTextFile(metadata.fileType, metadata.title)) {
|
if (!metadata || !Util.isPlainTextFile(metadata.fileType, metadata.title)) {
|
||||||
hide.push('openincode');
|
hide.push('openincode');
|
||||||
}
|
}
|
||||||
|
if (!metadata.channel || metadata.channel.length > 32) {
|
||||||
|
hide.push('makeacopy'); // Not for blobs
|
||||||
|
}
|
||||||
} 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
|
||||||
@ -1191,6 +1199,7 @@ define([
|
|||||||
hide.push('openincode');
|
hide.push('openincode');
|
||||||
hide.push('hashtag');
|
hide.push('hashtag');
|
||||||
hide.push('delete');
|
hide.push('delete');
|
||||||
|
hide.push('makeacopy');
|
||||||
//hide.push('deleteowned');
|
//hide.push('deleteowned');
|
||||||
} else { // it's a folder
|
} else { // it's a folder
|
||||||
if (containsFolder) {
|
if (containsFolder) {
|
||||||
@ -1205,6 +1214,7 @@ define([
|
|||||||
hide.push('openincode');
|
hide.push('openincode');
|
||||||
hide.push('properties');
|
hide.push('properties');
|
||||||
hide.push('hashtag');
|
hide.push('hashtag');
|
||||||
|
hide.push('makeacopy');
|
||||||
}
|
}
|
||||||
// If we're in the trash, hide restore and properties for non-root elements
|
// If we're in the trash, hide restore and properties for non-root elements
|
||||||
if (type === "trash" && path && path.length > 4) {
|
if (type === "trash" && path && path.length > 4) {
|
||||||
@ -1241,6 +1251,7 @@ define([
|
|||||||
hide.push('share');
|
hide.push('share');
|
||||||
hide.push('savelocal');
|
hide.push('savelocal');
|
||||||
hide.push('openincode'); // can't because of race condition
|
hide.push('openincode'); // can't because of race condition
|
||||||
|
hide.push('makeacopy');
|
||||||
}
|
}
|
||||||
if (containsFolder && paths.length > 1) {
|
if (containsFolder && paths.length > 1) {
|
||||||
// Cannot open multiple folders
|
// Cannot open multiple folders
|
||||||
@ -1258,11 +1269,11 @@ define([
|
|||||||
break;
|
break;
|
||||||
case 'tree':
|
case 'tree':
|
||||||
show = ['open', 'openro', 'openincode', 'expandall', 'collapseall',
|
show = ['open', 'openro', 'openincode', 'expandall', 'collapseall',
|
||||||
'color', 'download', 'share', 'savelocal', 'rename', 'delete',
|
'color', 'download', 'share', 'savelocal', 'rename', 'delete', 'makeacopy',
|
||||||
'deleteowned', 'removesf', 'properties', 'hashtag'];
|
'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', 'makeacopy'];
|
||||||
break;
|
break;
|
||||||
case 'trashtree': {
|
case 'trashtree': {
|
||||||
show = ['empty'];
|
show = ['empty'];
|
||||||
@ -3977,6 +3988,35 @@ define([
|
|||||||
openFile(el, true);
|
openFile(el, true);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
else if ($this.hasClass('cp-app-drive-context-makeacopy')) {
|
||||||
|
if (paths.length !== 1) { return; }
|
||||||
|
el = manager.find(paths[0].path);
|
||||||
|
var _metadata = manager.getFileData(el);
|
||||||
|
var _simpleData = {
|
||||||
|
title: _metadata.filename || _metadata.title,
|
||||||
|
href: _metadata.href || _metadata.roHref,
|
||||||
|
password: _metadata.password,
|
||||||
|
channel: _metadata.channel,
|
||||||
|
};
|
||||||
|
nThen(function (waitFor) {
|
||||||
|
var path = currentPath;
|
||||||
|
if (path[0] !== ROOT) { path = [ROOT]; }
|
||||||
|
common.sessionStorage.put(Constants.newPadFileData, JSON.stringify(_simpleData), waitFor());
|
||||||
|
common.sessionStorage.put(Constants.newPadPathKey, path, waitFor());
|
||||||
|
common.sessionStorage.put(Constants.newPadTeamKey, APP.team, waitFor());
|
||||||
|
}).nThen(function () {
|
||||||
|
var parsed = Hash.parsePadUrl(_metadata.href || _metadata.roHref);
|
||||||
|
common.openURL(Hash.hashToHref('', parsed.type));
|
||||||
|
// We need to restore sessionStorage for the next time we want to create a pad from this tab
|
||||||
|
// NOTE: the 100ms timeout is to fix a race condition in firefox where sessionStorage
|
||||||
|
// would be deleted before the new tab was created
|
||||||
|
setTimeout(function () {
|
||||||
|
common.sessionStorage.put(Constants.newPadFileData, '', function () {});
|
||||||
|
common.sessionStorage.put(Constants.newPadPathKey, '', function () {});
|
||||||
|
common.sessionStorage.put(Constants.newPadTeamKey, '', function () {});
|
||||||
|
}, 100);
|
||||||
|
});
|
||||||
|
}
|
||||||
else if ($this.hasClass('cp-app-drive-context-openincode')) {
|
else if ($this.hasClass('cp-app-drive-context-openincode')) {
|
||||||
if (paths.length !== 1) { return; }
|
if (paths.length !== 1) { return; }
|
||||||
var p = paths[0];
|
var p = paths[0];
|
||||||
|
|||||||
@ -674,6 +674,9 @@ define([
|
|||||||
$hist.addClass('cp-hidden-if-readonly');
|
$hist.addClass('cp-hidden-if-readonly');
|
||||||
toolbar.$drawer.append($hist);
|
toolbar.$drawer.append($hist);
|
||||||
|
|
||||||
|
var $copy = common.createButton('copy', true);
|
||||||
|
toolbar.$drawer.append($copy);
|
||||||
|
|
||||||
if (!cpNfInner.metadataMgr.getPrivateData().isTemplate) {
|
if (!cpNfInner.metadataMgr.getPrivateData().isTemplate) {
|
||||||
var templateObj = {
|
var templateObj = {
|
||||||
rt: cpNfInner.chainpad,
|
rt: cpNfInner.chainpad,
|
||||||
|
|||||||
@ -801,6 +801,20 @@ define([
|
|||||||
Cryptpad.saveAsTemplate(Cryptget.put, data, cb);
|
Cryptpad.saveAsTemplate(Cryptget.put, data, cb);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
sframeChan.on('EV_MAKE_A_COPY', function () {
|
||||||
|
var data = {
|
||||||
|
channel: secret.channel,
|
||||||
|
href: currentPad.href,
|
||||||
|
password: password,
|
||||||
|
title: currentTitle
|
||||||
|
};
|
||||||
|
sessionStorage[Utils.Constants.newPadFileData] = JSON.stringify(data);
|
||||||
|
window.open(window.location.pathname);
|
||||||
|
setTimeout(function () {
|
||||||
|
delete sessionStorage[Utils.Constants.newPadFileData];
|
||||||
|
}, 100);
|
||||||
|
});
|
||||||
|
|
||||||
// Messaging
|
// Messaging
|
||||||
sframeChan.on('Q_SEND_FRIEND_REQUEST', function (data, cb) {
|
sframeChan.on('Q_SEND_FRIEND_REQUEST', function (data, cb) {
|
||||||
Cryptpad.messaging.sendFriendRequest(data, cb);
|
Cryptpad.messaging.sendFriendRequest(data, cb);
|
||||||
|
|||||||
@ -1184,6 +1184,9 @@ define([
|
|||||||
$rightside.append($templateButton);
|
$rightside.append($templateButton);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var $copy = common.createButton('copy', true);
|
||||||
|
$drawer.append($copy);
|
||||||
|
|
||||||
/* add an export button */
|
/* add an export button */
|
||||||
var $export = common.createButton('export', true, {}, exportFile);
|
var $export = common.createButton('export', true, {}, exportFile);
|
||||||
$drawer.append($export);
|
$drawer.append($export);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user