Merge branch 'newShare' into staging
commit
4faad7ba83
|
@ -229,181 +229,7 @@ define([
|
|||
};
|
||||
};
|
||||
|
||||
|
||||
var createShareWithFriends = function (config, onShare, linkGetter) {
|
||||
var common = config.common;
|
||||
var sframeChan = common.getSframeChannel();
|
||||
var title = config.title;
|
||||
var friends = config.friends || {};
|
||||
var teams = config.teams || {};
|
||||
var myName = common.getMetadataMgr().getUserData().name;
|
||||
var order = [];
|
||||
|
||||
var smallCurves = Object.keys(friends).map(function (c) {
|
||||
return friends[c].curvePublic.slice(0,8);
|
||||
});
|
||||
|
||||
var div = h('div.contains-nav');
|
||||
var $div = $(div);
|
||||
// Replace "copy link" by "share with friends" if at least one friend is selected
|
||||
// Also create the "share with friends" button if it doesn't exist
|
||||
var refreshButtons = function () {
|
||||
var $nav = $div.closest('.alertify').find('nav');
|
||||
|
||||
var friendMode = $div.find('.cp-usergrid-user.cp-selected').length;
|
||||
if (friendMode) {
|
||||
$nav.find('button.cp-share-with-friends').prop('disabled', '');
|
||||
} else {
|
||||
$nav.find('button.cp-share-with-friends').prop('disabled', 'disabled');
|
||||
}
|
||||
};
|
||||
|
||||
config.noInclude = true;
|
||||
Object.keys(friends).forEach(function (curve) {
|
||||
var data = friends[curve];
|
||||
if (curve.length > 40 && data.notifications) { return; }
|
||||
delete friends[curve];
|
||||
});
|
||||
|
||||
var others = [];
|
||||
if (Object.keys(friends).length) {
|
||||
var friendsList = UIElements.getUserGrid(Messages.share_linkFriends, {
|
||||
common: common,
|
||||
data: friends,
|
||||
noFilter: false,
|
||||
large: true
|
||||
}, refreshButtons);
|
||||
var friendDiv = friendsList.div;
|
||||
$div.append(friendDiv);
|
||||
others = friendsList.icons;
|
||||
}
|
||||
|
||||
if (Object.keys(teams).length) {
|
||||
var teamsList = UIElements.getUserGrid(Messages.share_linkTeam, {
|
||||
common: common,
|
||||
noFilter: true,
|
||||
large: true,
|
||||
data: teams
|
||||
}, refreshButtons);
|
||||
$div.append(teamsList.div);
|
||||
}
|
||||
|
||||
var shareButton = {
|
||||
className: 'primary cp-share-with-friends',
|
||||
name: Messages.share_withFriends,
|
||||
onClick: function () {
|
||||
var href;
|
||||
NThen(function (waitFor) {
|
||||
var w = waitFor();
|
||||
// linkGetter can be async if this is a burn after reading URL
|
||||
var res = linkGetter({}, function (url) {
|
||||
if (!url) {
|
||||
waitFor.abort();
|
||||
return;
|
||||
}
|
||||
href = url;
|
||||
setTimeout(w);
|
||||
});
|
||||
if (res && /^http/.test(res)) {
|
||||
href = Hash.getRelativeHref(res);
|
||||
setTimeout(w);
|
||||
return;
|
||||
}
|
||||
}).nThen(function () {
|
||||
var $friends = $div.find('.cp-usergrid-user.cp-selected');
|
||||
$friends.each(function (i, el) {
|
||||
var curve = $(el).attr('data-curve');
|
||||
var ed = $(el).attr('data-ed');
|
||||
var friend = curve && friends[curve];
|
||||
var team = teams[ed];
|
||||
// If the selected element is a friend or a team without edit right,
|
||||
// send a notification
|
||||
var mailbox = friend || ((team && team.viewer) ? team : undefined);
|
||||
if (mailbox) { // Friend
|
||||
if (friends[curve] && !mailbox.notifications) { return; }
|
||||
if (mailbox.notifications && mailbox.curvePublic) {
|
||||
common.mailbox.sendTo("SHARE_PAD", {
|
||||
href: href,
|
||||
password: config.password,
|
||||
isTemplate: config.isTemplate,
|
||||
name: myName,
|
||||
title: title
|
||||
}, {
|
||||
viewed: team && team.id,
|
||||
channel: mailbox.notifications,
|
||||
curvePublic: mailbox.curvePublic
|
||||
});
|
||||
return;
|
||||
}
|
||||
}
|
||||
// If it's a team with edit right, add the pad directly
|
||||
if (!team) { return; }
|
||||
sframeChan.query('Q_STORE_IN_TEAM', {
|
||||
href: href,
|
||||
password: config.password,
|
||||
path: config.isTemplate ? ['template'] : undefined,
|
||||
title: title,
|
||||
teamId: team.id
|
||||
}, function (err) {
|
||||
if (err) { return void console.error(err); }
|
||||
});
|
||||
});
|
||||
|
||||
UI.findCancelButton().click();
|
||||
|
||||
// Update the "recently shared with" array:
|
||||
// Get the selected curves
|
||||
var curves = $friends.toArray().map(function (el) {
|
||||
return ($(el).attr('data-curve') || '').slice(0,8);
|
||||
}).filter(function (x) { return x; });
|
||||
// Prepend them to the "order" array
|
||||
Array.prototype.unshift.apply(order, curves);
|
||||
order = Util.deduplicateString(order);
|
||||
// Make sure we don't have "old" friends and save
|
||||
order = order.filter(function (curve) {
|
||||
return smallCurves.indexOf(curve) !== -1;
|
||||
});
|
||||
common.setAttribute(['general', 'share-friends'], order);
|
||||
if (onShare) {
|
||||
onShare.fire();
|
||||
}
|
||||
});
|
||||
},
|
||||
keys: [13]
|
||||
};
|
||||
|
||||
common.getAttribute(['general', 'share-friends'], function (err, val) {
|
||||
order = val || [];
|
||||
// Sort friends by "recently shared with"
|
||||
others.sort(function (a, b) {
|
||||
var ca = ($(a).attr('data-curve') || '').slice(0,8);
|
||||
var cb = ($(b).attr('data-curve') || '').slice(0,8);
|
||||
if (!ca && !cb) { return 0; }
|
||||
if (!ca) { return 1; }
|
||||
if (!cb) { return -1; }
|
||||
var ia = order.indexOf(ca);
|
||||
var ib = order.indexOf(cb);
|
||||
if (ia === -1 && ib === -1) { return 0; }
|
||||
if (ia === -1) { return 1; }
|
||||
if (ib === -1) { return -1; }
|
||||
return ia - ib;
|
||||
});
|
||||
// Reorder the friend icons
|
||||
others.forEach(function (el, i) {
|
||||
$(el).attr('data-order', i).css('order', i);
|
||||
});
|
||||
// Display them
|
||||
$(friendDiv).find('.cp-usergrid-grid').detach();
|
||||
$(friendDiv).append(h('div.cp-usergrid-grid', others));
|
||||
refreshButtons();
|
||||
});
|
||||
return {
|
||||
content: div,
|
||||
buttons: [shareButton]
|
||||
};
|
||||
};
|
||||
|
||||
var noContactsMessage = function(common){
|
||||
UIElements.noContactsMessage = function (common) {
|
||||
var metadataMgr = common.getMetadataMgr();
|
||||
var data = metadataMgr.getUserData();
|
||||
var origin = metadataMgr.getPrivateData().origin;
|
||||
|
@ -446,655 +272,6 @@ define([
|
|||
}
|
||||
};
|
||||
|
||||
var getEditableTeams = function (common, config) {
|
||||
var privateData = common.getMetadataMgr().getPrivateData();
|
||||
var teamsData = Util.tryParse(JSON.stringify(privateData.teams)) || {};
|
||||
var teams = {};
|
||||
Object.keys(teamsData).forEach(function (id) {
|
||||
// config.teamId only exists when we're trying to share a pad from a team drive
|
||||
// In this case, we don't want to share the pad with the current team
|
||||
if (config.teamId && config.teamId === id) { return; }
|
||||
var t = teamsData[id];
|
||||
teams[t.edPublic] = {
|
||||
viewer: !teamsData[id].hasSecondaryKey,
|
||||
notifications: t.notifications,
|
||||
curvePublic: t.curvePublic,
|
||||
displayName: t.name,
|
||||
edPublic: t.edPublic,
|
||||
avatar: t.avatar,
|
||||
id: id
|
||||
};
|
||||
});
|
||||
return teams;
|
||||
};
|
||||
var makeBurnAfterReadingUrl = function (common, href, channel, cb) {
|
||||
var keyPair = Hash.generateSignPair();
|
||||
var parsed = Hash.parsePadUrl(href);
|
||||
var newHref = parsed.getUrl({
|
||||
ownerKey: keyPair.safeSignKey
|
||||
});
|
||||
var sframeChan = common.getSframeChannel();
|
||||
var rtChannel;
|
||||
NThen(function (waitFor) {
|
||||
if (parsed.type !== "sheet") { return; }
|
||||
common.getPadAttribute('rtChannel', waitFor(function (err, chan) {
|
||||
rtChannel = chan;
|
||||
}));
|
||||
}).nThen(function (waitFor) {
|
||||
sframeChan.query('Q_SET_PAD_METADATA', {
|
||||
channel: channel,
|
||||
command: 'ADD_OWNERS',
|
||||
value: [keyPair.validateKey]
|
||||
}, waitFor(function (err) {
|
||||
if (err) {
|
||||
waitFor.abort();
|
||||
UI.warn(Messages.error);
|
||||
}
|
||||
}));
|
||||
if (rtChannel) {
|
||||
sframeChan.query('Q_SET_PAD_METADATA', {
|
||||
channel: rtChannel,
|
||||
command: 'ADD_OWNERS',
|
||||
value: [keyPair.validateKey]
|
||||
}, waitFor(function (err) {
|
||||
if (err) {
|
||||
console.error(err);
|
||||
}
|
||||
}));
|
||||
}
|
||||
}).nThen(function () {
|
||||
cb(newHref);
|
||||
});
|
||||
};
|
||||
UIElements.createShareModal = function (config) {
|
||||
var origin = config.origin;
|
||||
var pathname = config.pathname;
|
||||
var hashes = config.hashes;
|
||||
var common = config.common;
|
||||
|
||||
if (!hashes || (!hashes.editHash && !hashes.viewHash)) { return; }
|
||||
|
||||
// check if the pad is password protected
|
||||
var hash = hashes.editHash || hashes.viewHash;
|
||||
var href = origin + pathname + '#' + hash;
|
||||
var parsedHref = Hash.parsePadUrl(href);
|
||||
var hasPassword = parsedHref.hashData.password;
|
||||
|
||||
var makeFaqLink = function () {
|
||||
var link = h('span', [
|
||||
h('i.fa.fa-question-circle'),
|
||||
h('a', {href: '#'}, Messages.passwordFaqLink)
|
||||
]);
|
||||
$(link).click(function () {
|
||||
common.openURL(config.origin + "/faq.html#security-pad_password");
|
||||
});
|
||||
return link;
|
||||
};
|
||||
|
||||
|
||||
var parsed = Hash.parsePadUrl(pathname);
|
||||
var canPresent = ['code', 'slide'].indexOf(parsed.type) !== -1;
|
||||
var canBAR = parsed.type !== 'drive';
|
||||
|
||||
var burnAfterReading = (hashes.viewHash && canBAR) ?
|
||||
UI.createRadio('accessRights', 'cp-share-bar', Messages.burnAfterReading_linkBurnAfterReading, false, {
|
||||
mark: {tabindex:1},
|
||||
label: {style: "display: none;"}
|
||||
}) : undefined;
|
||||
var rights = h('div.msg.cp-inline-radio-group', [
|
||||
h('label', Messages.share_linkAccess),
|
||||
h('div.radio-group',[
|
||||
UI.createRadio('accessRights', 'cp-share-editable-false',
|
||||
Messages.share_linkView, true, { mark: {tabindex:1} }),
|
||||
canPresent ? UI.createRadio('accessRights', 'cp-share-present',
|
||||
Messages.share_linkPresent, false, { mark: {tabindex:1} }) : undefined,
|
||||
UI.createRadio('accessRights', 'cp-share-editable-true',
|
||||
Messages.share_linkEdit, false, { mark: {tabindex:1} })]),
|
||||
burnAfterReading
|
||||
]);
|
||||
|
||||
// Burn after reading
|
||||
// Check if we are an owner of this pad. If we are, we can show the burn after reading option.
|
||||
// When BAR is selected, display a red message indicating the consequence and add
|
||||
// the options to generate the BAR url
|
||||
var barAlert = h('div.alert.alert-danger.cp-alertify-bar-selected', {
|
||||
style: 'display: none;'
|
||||
}, Messages.burnAfterReading_warningLink);
|
||||
var channel = Hash.getSecrets('pad', hash, config.password).channel;
|
||||
common.getPadMetadata({
|
||||
channel: channel
|
||||
}, function (obj) {
|
||||
if (!obj || obj.error) { return; }
|
||||
var priv = common.getMetadataMgr().getPrivateData();
|
||||
// Not an owner: don't display the burn after reading option
|
||||
if (!Array.isArray(obj.owners) || obj.owners.indexOf(priv.edPublic) === -1) {
|
||||
$(burnAfterReading).remove();
|
||||
return;
|
||||
}
|
||||
// When the burn after reading option is selected, transform the modal buttons
|
||||
$(burnAfterReading).css({
|
||||
display: 'flex'
|
||||
});
|
||||
});
|
||||
|
||||
var $rights = $(rights);
|
||||
|
||||
var saveValue = function () {
|
||||
var edit = Util.isChecked($rights.find('#cp-share-editable-true'));
|
||||
var present = Util.isChecked($rights.find('#cp-share-present'));
|
||||
common.setAttribute(['general', 'share'], {
|
||||
edit: edit,
|
||||
present: present
|
||||
});
|
||||
};
|
||||
|
||||
var burnAfterReadingUrl;
|
||||
|
||||
var getLinkValue = function (initValue, cb) {
|
||||
var val = initValue || {};
|
||||
var edit = val.edit !== undefined ? val.edit : Util.isChecked($rights.find('#cp-share-editable-true'));
|
||||
var embed = val.embed;
|
||||
var present = val.present !== undefined ? val.present : Util.isChecked($rights.find('#cp-share-present'));
|
||||
var burnAfterReading = Util.isChecked($rights.find('#cp-share-bar'));
|
||||
if (burnAfterReading && !burnAfterReadingUrl) {
|
||||
if (cb) { // Called from the contacts tab, "share" button
|
||||
var barHref = origin + pathname + '#' + (hashes.viewHash || hashes.editHash);
|
||||
return makeBurnAfterReadingUrl(common, barHref, channel, function (url) {
|
||||
cb(url);
|
||||
});
|
||||
}
|
||||
return Messages.burnAfterReading_generateLink;
|
||||
}
|
||||
var hash = (!hashes.viewHash || (edit && hashes.editHash)) ? hashes.editHash : hashes.viewHash;
|
||||
var href = burnAfterReading ? burnAfterReadingUrl : (origin + pathname + '#' + hash);
|
||||
var parsed = Hash.parsePadUrl(href);
|
||||
return origin + parsed.getUrl({embed: embed, present: present});
|
||||
};
|
||||
|
||||
var makeCancelButton = function() {
|
||||
return {
|
||||
className: 'cancel',
|
||||
name: Messages.cancel,
|
||||
onClick: function () {},
|
||||
keys: [27]
|
||||
};
|
||||
};
|
||||
|
||||
// Share link tab
|
||||
var linkContent = config.sharedFolder ? [
|
||||
h('label', Messages.sharedFolders_share),
|
||||
h('br'),
|
||||
] : [
|
||||
UI.createCheckbox('cp-share-embed', Messages.share_linkEmbed, false, { mark: {tabindex:1} }),
|
||||
];
|
||||
linkContent.push(h('div.cp-spacer'));
|
||||
linkContent.push(UI.dialog.selectableArea('', { id: 'cp-share-link-preview', tabindex: 1, rows:3}));
|
||||
|
||||
// Show alert if the pad is password protected
|
||||
if (hasPassword) {
|
||||
linkContent.push(h('div.alert.alert-primary', [
|
||||
h('i.fa.fa-lock'),
|
||||
Messages.share_linkPasswordAlert, h('br'),
|
||||
makeFaqLink()
|
||||
]));
|
||||
}
|
||||
|
||||
// warning about sharing links
|
||||
var localStore = window.cryptpadStore;
|
||||
var dismissButton = h('span.fa.fa-times');
|
||||
var shareLinkWarning = h('div.alert.alert-warning.dismissable',
|
||||
{ style: 'display: none;' },
|
||||
[
|
||||
h('span.cp-inline-alert-text', Messages.share_linkWarning),
|
||||
dismissButton
|
||||
]);
|
||||
linkContent.push(shareLinkWarning);
|
||||
|
||||
localStore.get('hide-alert-shareLinkWarning', function (val) {
|
||||
if (val === '1') { return; }
|
||||
$(shareLinkWarning).show();
|
||||
|
||||
$(dismissButton).on('click', function () {
|
||||
localStore.put('hide-alert-shareLinkWarning', '1');
|
||||
$(shareLinkWarning).remove();
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
linkContent.push($(barAlert).clone()[0]); // Burn after reading
|
||||
|
||||
var link = h('div.cp-share-modal', linkContent);
|
||||
var $link = $(link);
|
||||
|
||||
var linkButtons = [
|
||||
makeCancelButton(),
|
||||
!config.sharedFolder && {
|
||||
className: 'secondary cp-nobar',
|
||||
name: Messages.share_linkOpen,
|
||||
onClick: function () {
|
||||
saveValue();
|
||||
var v = getLinkValue({
|
||||
embed: Util.isChecked($link.find('#cp-share-embed'))
|
||||
});
|
||||
window.open(v);
|
||||
return true;
|
||||
},
|
||||
keys: [[13, 'ctrl']]
|
||||
}, {
|
||||
className: 'primary cp-nobar',
|
||||
name: Messages.share_linkCopy,
|
||||
onClick: function () {
|
||||
saveValue();
|
||||
var v = getLinkValue({
|
||||
embed: Util.isChecked($link.find('#cp-share-embed'))
|
||||
});
|
||||
var success = Clipboard.copy(v);
|
||||
if (success) { UI.log(Messages.shareSuccess); }
|
||||
},
|
||||
keys: [13]
|
||||
}, {
|
||||
className: 'primary cp-bar',
|
||||
name: 'GENERATE LINK',
|
||||
onClick: function () {
|
||||
var barHref = origin + pathname + '#' + (hashes.viewHash || hashes.editHash);
|
||||
makeBurnAfterReadingUrl(common, barHref, channel, function (url) {
|
||||
burnAfterReadingUrl = url;
|
||||
$rights.find('input[type="radio"]').trigger('change');
|
||||
});
|
||||
return true;
|
||||
},
|
||||
keys: []
|
||||
}
|
||||
];
|
||||
|
||||
var frameLink = UI.dialog.customModal(link, {
|
||||
buttons: linkButtons,
|
||||
onClose: config.onClose,
|
||||
});
|
||||
$(frameLink).find('.cp-bar').hide();
|
||||
|
||||
// Share with contacts tab
|
||||
|
||||
var teams = getEditableTeams(common, config);
|
||||
config.teams = teams;
|
||||
var hasFriends = Object.keys(config.friends || {}).length ||
|
||||
Object.keys(teams).length;
|
||||
var onFriendShare = Util.mkEvent();
|
||||
|
||||
|
||||
var friendsObject = hasFriends ? createShareWithFriends(config, onFriendShare, getLinkValue) : noContactsMessage(common);
|
||||
var friendsList = friendsObject.content;
|
||||
|
||||
onFriendShare.reg(saveValue);
|
||||
|
||||
var contactsContent = h('div.cp-share-modal');
|
||||
var $contactsContent = $(contactsContent);
|
||||
|
||||
$contactsContent.append(friendsList);
|
||||
|
||||
// Show alert if the pad is password protected
|
||||
if (hasPassword) {
|
||||
$contactsContent.append(h('div.alert.alert-primary', [
|
||||
h('i.fa.fa-unlock'),
|
||||
Messages.share_contactPasswordAlert, h('br'),
|
||||
makeFaqLink()
|
||||
]));
|
||||
}
|
||||
|
||||
$(contactsContent).append($(barAlert).clone()); // Burn after reading
|
||||
|
||||
var contactButtons = friendsObject.buttons;
|
||||
contactButtons.unshift(makeCancelButton());
|
||||
|
||||
var onShowContacts = function () {
|
||||
if (!hasFriends) {
|
||||
$rights.hide();
|
||||
}
|
||||
};
|
||||
|
||||
var frameContacts = UI.dialog.customModal(contactsContent, {
|
||||
buttons: contactButtons,
|
||||
onClose: config.onClose,
|
||||
});
|
||||
|
||||
// Embed tab
|
||||
var getEmbedValue = function () {
|
||||
var url = getLinkValue({
|
||||
embed: true
|
||||
});
|
||||
return '<iframe src="' + url + '"></iframe>';
|
||||
};
|
||||
var embedContent = [
|
||||
h('p', Messages.viewEmbedTag),
|
||||
UI.dialog.selectableArea(getEmbedValue(), { id: 'cp-embed-link-preview', tabindex: 1, rows: 3})
|
||||
];
|
||||
|
||||
// Show alert if the pad is password protected
|
||||
if (hasPassword) {
|
||||
embedContent.push(h('div.alert.alert-primary', [
|
||||
h('i.fa.fa-lock'), ' ',
|
||||
Messages.share_embedPasswordAlert, h('br'),
|
||||
makeFaqLink()
|
||||
]));
|
||||
}
|
||||
|
||||
var embedButtons = [
|
||||
makeCancelButton(), {
|
||||
className: 'primary',
|
||||
name: Messages.share_linkCopy,
|
||||
onClick: function () {
|
||||
var v = getEmbedValue();
|
||||
var success = Clipboard.copy(v);
|
||||
if (success) { UI.log(Messages.shareSuccess); }
|
||||
},
|
||||
keys: [13]
|
||||
}];
|
||||
|
||||
var onShowEmbed = function () {
|
||||
$rights.find('#cp-share-bar').closest('label').hide();
|
||||
$rights.find('input[type="radio"]:enabled').first().prop('checked', 'checked');
|
||||
$rights.find('input[type="radio"]').trigger('change');
|
||||
};
|
||||
|
||||
var embed = h('div.cp-share-modal', embedContent);
|
||||
var $embed = $(embed);
|
||||
|
||||
var frameEmbed = UI.dialog.customModal(embed, {
|
||||
buttons: embedButtons,
|
||||
onClose: config.onClose,
|
||||
});
|
||||
|
||||
// update values for link and embed preview when radio btns change
|
||||
$embed.find('#cp-embed-link-preview').val(getEmbedValue());
|
||||
$link.find('#cp-share-link-preview').val(getLinkValue());
|
||||
$rights.find('input[type="radio"]').on('change', function () {
|
||||
$link.find('#cp-share-link-preview').val(getLinkValue({
|
||||
embed: Util.isChecked($link.find('#cp-share-embed'))
|
||||
}));
|
||||
// Hide or show the burn after reading alert
|
||||
if (Util.isChecked($rights.find('#cp-share-bar')) && !burnAfterReadingUrl) {
|
||||
$('.cp-alertify-bar-selected').show();
|
||||
// Show burn after reading button
|
||||
$('.alertify').find('.cp-bar').show();
|
||||
$('.alertify').find('.cp-nobar').hide();
|
||||
return;
|
||||
}
|
||||
$embed.find('#cp-embed-link-preview').val(getEmbedValue());
|
||||
// Hide burn after reading button
|
||||
$('.alertify').find('.cp-nobar').show();
|
||||
$('.alertify').find('.cp-bar').hide();
|
||||
$('.cp-alertify-bar-selected').hide();
|
||||
});
|
||||
$link.find('input[type="checkbox"]').on('change', function () {
|
||||
$link.find('#cp-share-link-preview').val(getLinkValue({
|
||||
embed: Util.isChecked($link.find('#cp-share-embed'))
|
||||
}));
|
||||
});
|
||||
|
||||
|
||||
// Create modal
|
||||
var resetTab = function () {
|
||||
$rights.show();
|
||||
$rights.find('label.cp-radio').show();
|
||||
};
|
||||
var tabs = [{
|
||||
title: Messages.share_contactCategory,
|
||||
icon: "fa fa-address-book",
|
||||
content: frameContacts,
|
||||
active: hasFriends,
|
||||
onShow: onShowContacts,
|
||||
onHide: resetTab
|
||||
}, {
|
||||
title: Messages.share_linkCategory,
|
||||
icon: "fa fa-link",
|
||||
content: frameLink,
|
||||
active: !hasFriends
|
||||
}, {
|
||||
title: Messages.share_embedCategory,
|
||||
icon: "fa fa-code",
|
||||
content: frameEmbed,
|
||||
onShow: onShowEmbed,
|
||||
onHide: resetTab
|
||||
}];
|
||||
if (typeof(AppConfig.customizeShareOptions) === 'function') {
|
||||
AppConfig.customizeShareOptions(hashes, tabs, {
|
||||
type: 'DEFAULT',
|
||||
origin: origin,
|
||||
pathname: pathname
|
||||
});
|
||||
}
|
||||
|
||||
var modal = UI.dialog.tabs(tabs);
|
||||
$(modal).find('.alertify-tabs-titles').after(rights);
|
||||
|
||||
// disable edit share options if you don't have edit rights
|
||||
if (!hashes.editHash) {
|
||||
$rights.find('#cp-share-editable-false').attr('checked', true);
|
||||
$rights.find('#cp-share-editable-true').removeAttr('checked').attr('disabled', true);
|
||||
} else if (!hashes.viewHash) {
|
||||
$rights.find('#cp-share-editable-false').removeAttr('checked').attr('disabled', true);
|
||||
$rights.find('#cp-share-present').removeAttr('checked').attr('disabled', true);
|
||||
$rights.find('#cp-share-editable-true').attr('checked', true);
|
||||
}
|
||||
|
||||
common.getAttribute(['general', 'share'], function (err, val) {
|
||||
val = val || {};
|
||||
if (val.present && canPresent) {
|
||||
$rights.find('#cp-share-editable-false').prop('checked', false);
|
||||
$rights.find('#cp-share-editable-true').prop('checked', false);
|
||||
$rights.find('#cp-share-present').prop('checked', true);
|
||||
} else if ((val.edit === false && hashes.viewHash) || !hashes.editHash) {
|
||||
$rights.find('#cp-share-editable-false').prop('checked', true);
|
||||
$rights.find('#cp-share-editable-true').prop('checked', false);
|
||||
$rights.find('#cp-share-present').prop('checked', false);
|
||||
} else {
|
||||
$rights.find('#cp-share-editable-true').prop('checked', true);
|
||||
$rights.find('#cp-share-editable-false').prop('checked', false);
|
||||
$rights.find('#cp-share-present').prop('checked', false);
|
||||
}
|
||||
delete val.embed;
|
||||
if (!canPresent) {
|
||||
delete val.present;
|
||||
}
|
||||
$link.find('#cp-share-link-preview').val(getLinkValue(val));
|
||||
});
|
||||
common.getMetadataMgr().onChange(function () {
|
||||
// "hashes" is only available is the secure "share" app
|
||||
var _hashes = common.getMetadataMgr().getPrivateData().hashes;
|
||||
if (!_hashes) { return; }
|
||||
hashes = _hashes;
|
||||
$link.find('#cp-share-link-preview').val(getLinkValue());
|
||||
});
|
||||
return modal;
|
||||
};
|
||||
|
||||
UIElements.createFileShareModal = function (config) {
|
||||
var origin = config.origin;
|
||||
var pathname = config.pathname;
|
||||
var hashes = config.hashes;
|
||||
var common = config.common;
|
||||
var fileData = config.fileData;
|
||||
|
||||
if (!hashes.fileHash) { throw new Error("You must provide a file hash"); }
|
||||
var url = origin + pathname + '#' + hashes.fileHash;
|
||||
|
||||
// check if the file is password protected
|
||||
var parsedHref = Hash.parsePadUrl(url);
|
||||
var hasPassword = parsedHref.hashData.password;
|
||||
|
||||
var makeFaqLink = function () {
|
||||
var link = h('span', [
|
||||
h('i.fa.fa-question-circle'),
|
||||
h('a', {href: '#'}, Messages.passwordFaqLink)
|
||||
]);
|
||||
$(link).click(function () {
|
||||
common.openURL(config.origin + "/faq.html#security-pad_password");
|
||||
});
|
||||
return link;
|
||||
};
|
||||
|
||||
var getLinkValue = function () { return url; };
|
||||
|
||||
var makeCancelButton = function() {
|
||||
return {className: 'cancel',
|
||||
name: Messages.cancel,
|
||||
onClick: function () {},
|
||||
keys: [27]};
|
||||
};
|
||||
|
||||
// Share link tab
|
||||
var linkContent = [
|
||||
UI.dialog.selectableArea(getLinkValue(), { id: 'cp-share-link-preview', tabindex: 1, rows:2 })
|
||||
];
|
||||
|
||||
// Show alert if the pad is password protected
|
||||
if (hasPassword) {
|
||||
linkContent.push(h('div.alert.alert-primary', [
|
||||
h('i.fa.fa-lock'),
|
||||
Messages.share_linkPasswordAlert, h('br'),
|
||||
makeFaqLink()
|
||||
]));
|
||||
}
|
||||
|
||||
// warning about sharing links
|
||||
var localStore = window.cryptpadStore;
|
||||
var dismissButton = h('span.fa.fa-times');
|
||||
var shareLinkWarning = h('div.alert.alert-warning.dismissable',
|
||||
{ style: 'display: none;' },
|
||||
[
|
||||
h('span.cp-inline-alert-text', Messages.share_linkWarning),
|
||||
dismissButton
|
||||
]);
|
||||
linkContent.push(shareLinkWarning);
|
||||
|
||||
localStore.get('hide-alert-shareLinkWarning', function (val) {
|
||||
if (val === '1') { return; }
|
||||
$(shareLinkWarning).show();
|
||||
|
||||
$(dismissButton).on('click', function () {
|
||||
localStore.put('hide-alert-shareLinkWarning', '1');
|
||||
$(shareLinkWarning).remove();
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
var link = h('div.cp-share-modal', linkContent);
|
||||
|
||||
var linkButtons = [
|
||||
makeCancelButton(),
|
||||
{
|
||||
className: 'primary',
|
||||
name: Messages.share_linkCopy,
|
||||
onClick: function () {
|
||||
var v = getLinkValue();
|
||||
var success = Clipboard.copy(v);
|
||||
if (success) { UI.log(Messages.shareSuccess);
|
||||
}
|
||||
},
|
||||
keys: [13]
|
||||
}
|
||||
];
|
||||
|
||||
var frameLink = UI.dialog.customModal(link, {
|
||||
buttons: linkButtons,
|
||||
onClose: config.onClose,
|
||||
});
|
||||
|
||||
// share with contacts tab
|
||||
var teams = getEditableTeams(common, config);
|
||||
config.teams = teams;
|
||||
var hasFriends = Object.keys(config.friends || {}).length ||
|
||||
Object.keys(teams).length;
|
||||
|
||||
var friendsObject = hasFriends ? createShareWithFriends(config, null, getLinkValue) : noContactsMessage(common);
|
||||
var friendsList = friendsObject.content;
|
||||
|
||||
var contactsContent = h('div.cp-share-modal');
|
||||
var $contactsContent = $(contactsContent);
|
||||
$contactsContent.append(friendsList);
|
||||
|
||||
// Show alert if the pad is password protected
|
||||
if (hasPassword) {
|
||||
$contactsContent.append(h('div.alert.alert-primary', [
|
||||
h('i.fa.fa-unlock'),
|
||||
Messages.share_contactPasswordAlert, h('br'),
|
||||
makeFaqLink()
|
||||
]));
|
||||
}
|
||||
|
||||
var contactButtons = friendsObject.buttons;
|
||||
contactButtons.unshift(makeCancelButton());
|
||||
|
||||
var frameContacts = UI.dialog.customModal(contactsContent, {
|
||||
buttons: contactButtons,
|
||||
onClose: config.onClose,
|
||||
});
|
||||
|
||||
|
||||
// Embed tab
|
||||
var embed = h('div.cp-share-modal', [
|
||||
h('p', Messages.fileEmbedScript),
|
||||
UI.dialog.selectable(common.getMediatagScript()),
|
||||
h('p', Messages.fileEmbedTag),
|
||||
UI.dialog.selectable(common.getMediatagFromHref(fileData)),
|
||||
]);
|
||||
|
||||
// Show alert if the pad is password protected
|
||||
if (hasPassword) {
|
||||
embed.append(h('div.alert.alert-primary', [
|
||||
h('i.fa.fa-lock'), ' ',
|
||||
Messages.share_embedPasswordAlert, h('br'),
|
||||
makeFaqLink()
|
||||
]));
|
||||
}
|
||||
|
||||
var embedButtons = [{
|
||||
className: 'cancel',
|
||||
name: Messages.cancel,
|
||||
onClick: function () {},
|
||||
keys: [27]
|
||||
}, {
|
||||
className: 'primary',
|
||||
name: Messages.share_mediatagCopy,
|
||||
onClick: function () {
|
||||
var v = common.getMediatagFromHref(fileData);
|
||||
var success = Clipboard.copy(v);
|
||||
if (success) { UI.log(Messages.shareSuccess); }
|
||||
},
|
||||
keys: [13]
|
||||
}];
|
||||
var frameEmbed = UI.dialog.customModal(embed, {
|
||||
buttons: embedButtons,
|
||||
onClose: config.onClose,
|
||||
});
|
||||
|
||||
// Create modal
|
||||
var tabs = [{
|
||||
title: Messages.share_contactCategory,
|
||||
icon: "fa fa-address-book",
|
||||
content: frameContacts,
|
||||
active: hasFriends,
|
||||
}, {
|
||||
title: Messages.share_linkCategory,
|
||||
icon: "fa fa-link",
|
||||
content: frameLink,
|
||||
active: !hasFriends
|
||||
}, {
|
||||
title: Messages.share_embedCategory,
|
||||
icon: "fa fa-code",
|
||||
content: frameEmbed
|
||||
}];
|
||||
if (typeof(AppConfig.customizeShareOptions) === 'function') {
|
||||
AppConfig.customizeShareOptions(hashes, tabs, {
|
||||
type: 'FILE',
|
||||
origin: origin,
|
||||
pathname: pathname
|
||||
});
|
||||
}
|
||||
var modal = UI.dialog.tabs(tabs);
|
||||
return modal;
|
||||
};
|
||||
|
||||
UIElements.createInviteTeamModal = function (config) {
|
||||
var common = config.common;
|
||||
var hasFriends = Object.keys(config.friends || {}).length !== 0;
|
||||
|
@ -1159,7 +336,7 @@ define([
|
|||
buttons: contactsButtons
|
||||
};
|
||||
};
|
||||
var friendsObject = hasFriends ? getContacts() : noContactsMessage(common);
|
||||
var friendsObject = hasFriends ? getContacts() : UIElements.noContactsMessage(common);
|
||||
var friendsList = friendsObject.content;
|
||||
var contactsButtons = friendsObject.buttons;
|
||||
contactsButtons.unshift({
|
||||
|
|
|
@ -10,6 +10,7 @@ define([
|
|||
'/common/common-constants.js',
|
||||
'/common/common-feedback.js',
|
||||
|
||||
'/common/inner/share.js',
|
||||
'/common/inner/access.js',
|
||||
'/common/inner/properties.js',
|
||||
|
||||
|
@ -29,6 +30,7 @@ define([
|
|||
UI,
|
||||
Constants,
|
||||
Feedback,
|
||||
Share,
|
||||
Access,
|
||||
Properties,
|
||||
nThen,
|
||||
|
@ -2009,26 +2011,25 @@ define([
|
|||
if (!parsed.hash && !roParsed.hash) { return void console.error("Invalid href: "+(data.href || data.roHref)); }
|
||||
var friends = common.getFriends();
|
||||
var ro = folders[id] && folders[id].version >= 2;
|
||||
var modal = UIElements.createShareModal({
|
||||
teamId: APP.team,
|
||||
origin: APP.origin,
|
||||
pathname: "/drive/",
|
||||
friends: friends,
|
||||
title: data.title,
|
||||
password: data.password,
|
||||
sharedFolder: true,
|
||||
common: common,
|
||||
hashes: {
|
||||
editHash: parsed.hash,
|
||||
viewHash: ro && roParsed.hash,
|
||||
}
|
||||
});
|
||||
// If we're a viewer and this is an old shared folder (no read-only mode), we
|
||||
// can't share the read-only URL and we don't have access to the edit one.
|
||||
// We should hide the share button.
|
||||
if (!modal) { return; }
|
||||
if (!data.href && !ro) { return; }
|
||||
$shareBlock.click(function () {
|
||||
UI.openCustomModal(modal);
|
||||
Share.getShareModal(common, {
|
||||
teamId: APP.team,
|
||||
origin: APP.origin,
|
||||
pathname: "/drive/",
|
||||
friends: friends,
|
||||
title: data.title,
|
||||
password: data.password,
|
||||
sharedFolder: true,
|
||||
common: common,
|
||||
hashes: {
|
||||
editHash: parsed.hash,
|
||||
viewHash: ro && roParsed.hash,
|
||||
}
|
||||
});
|
||||
});
|
||||
$container.append($shareBlock);
|
||||
return $shareBlock;
|
||||
|
@ -3664,14 +3665,6 @@ define([
|
|||
if (!readOnlyFolder) {
|
||||
createNewButton(isInRoot, APP.toolbar.$bottomL);
|
||||
}
|
||||
/*
|
||||
// The share button is not displayed anymore in the toolbar: users can't know
|
||||
// if they're going to share the current shared folder or the selected pad
|
||||
if (sfId) {
|
||||
createShareButton(sfId, APP.toolbar.$bottomL);
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
if (APP.mobile()) {
|
||||
var $context = $('<button>', {
|
||||
|
@ -4338,7 +4331,7 @@ define([
|
|||
else if ($this.hasClass('cp-app-drive-context-share')) {
|
||||
if (paths.length !== 1) { return; }
|
||||
el = manager.find(paths[0].path);
|
||||
var parsed, modal;
|
||||
var parsed;
|
||||
var friends = common.getFriends();
|
||||
var anonDrive = manager.isPathIn(currentPath, [FILES_DATA]) && !APP.loggedIn;
|
||||
|
||||
|
@ -4410,9 +4403,10 @@ define([
|
|||
sharedFolder: sf,
|
||||
common: common
|
||||
};
|
||||
modal = padType === 'file' ? UIElements.createFileShareModal(padData)
|
||||
: UIElements.createShareModal(padData);
|
||||
UI.openCustomModal(modal);
|
||||
if (padType === 'file') {
|
||||
return void Share.getFileShareModal(common, padData);
|
||||
}
|
||||
Share.getShareModal(common, padData);
|
||||
}
|
||||
}
|
||||
else if ($this.hasClass('cp-app-drive-context-savelocal')) {
|
||||
|
@ -4784,7 +4778,7 @@ define([
|
|||
placeholder: Messages.settings_changePasswordNew,
|
||||
style: 'flex: 1;'
|
||||
});
|
||||
var passwordOk = h('button.btn', Messages.properties_changePasswordButton);
|
||||
var passwordOk = h('button.btn.btn-secondary', Messages.properties_changePasswordButton);
|
||||
var changePass = h('span.cp-password-container', [
|
||||
newPassword,
|
||||
passwordOk
|
||||
|
|
|
@ -110,6 +110,10 @@ define([
|
|||
waitFor.abort();
|
||||
return void cb(e);
|
||||
}
|
||||
if (c && c.content && c.buttons) {
|
||||
obj.buttons = c.buttons;
|
||||
c = c.content;
|
||||
}
|
||||
var node = (c instanceof $) ? c[0] : c;
|
||||
tabs[i] = {
|
||||
content: c && UI.dialog.customModal(node, {
|
||||
|
@ -120,6 +124,9 @@ define([
|
|||
}
|
||||
}),
|
||||
disabled: !c,
|
||||
active: obj.active,
|
||||
onShow: obj.onShow,
|
||||
onHide: obj.onHide,
|
||||
title: obj.title,
|
||||
icon: obj.icon
|
||||
};
|
||||
|
|
|
@ -0,0 +1,853 @@
|
|||
define([
|
||||
'jquery',
|
||||
'/common/common-util.js',
|
||||
'/common/common-hash.js',
|
||||
'/common/common-interface.js',
|
||||
'/common/common-ui-elements.js',
|
||||
'/common/inner/common-modal.js',
|
||||
'/common/hyperscript.js',
|
||||
'/common/clipboard.js',
|
||||
'/customize/messages.js',
|
||||
'/bower_components/nthen/index.js',
|
||||
], function ($, Util, Hash, UI, UIElements, Modal, h, Clipboard,
|
||||
Messages, nThen) {
|
||||
var Share = {};
|
||||
|
||||
var createShareWithFriends = function (config, onShare, linkGetter) {
|
||||
var common = config.common;
|
||||
var sframeChan = common.getSframeChannel();
|
||||
var title = config.title;
|
||||
var friends = config.friends || {};
|
||||
var teams = config.teams || {};
|
||||
var myName = common.getMetadataMgr().getUserData().name;
|
||||
var order = [];
|
||||
|
||||
var smallCurves = Object.keys(friends).map(function (c) {
|
||||
return friends[c].curvePublic.slice(0,8);
|
||||
});
|
||||
|
||||
var div = h('div.contains-nav');
|
||||
var $div = $(div);
|
||||
// Replace "copy link" by "share with friends" if at least one friend is selected
|
||||
// Also create the "share with friends" button if it doesn't exist
|
||||
var refreshButtons = function () {
|
||||
var $nav = $div.closest('.alertify').find('nav');
|
||||
|
||||
var friendMode = $div.find('.cp-usergrid-user.cp-selected').length;
|
||||
if (friendMode) {
|
||||
$nav.find('button.cp-share-with-friends').prop('disabled', '');
|
||||
} else {
|
||||
$nav.find('button.cp-share-with-friends').prop('disabled', 'disabled');
|
||||
}
|
||||
};
|
||||
|
||||
config.noInclude = true;
|
||||
Object.keys(friends).forEach(function (curve) {
|
||||
var data = friends[curve];
|
||||
if (curve.length > 40 && data.notifications) { return; }
|
||||
delete friends[curve];
|
||||
});
|
||||
|
||||
var others = [];
|
||||
if (Object.keys(friends).length) {
|
||||
var friendsList = UIElements.getUserGrid(Messages.share_linkFriends, {
|
||||
common: common,
|
||||
data: friends,
|
||||
noFilter: false,
|
||||
large: true
|
||||
}, refreshButtons);
|
||||
var friendDiv = friendsList.div;
|
||||
$div.append(friendDiv);
|
||||
others = friendsList.icons;
|
||||
}
|
||||
|
||||
if (Object.keys(teams).length) {
|
||||
var teamsList = UIElements.getUserGrid(Messages.share_linkTeam, {
|
||||
common: common,
|
||||
noFilter: true,
|
||||
large: true,
|
||||
data: teams
|
||||
}, refreshButtons);
|
||||
$div.append(teamsList.div);
|
||||
}
|
||||
|
||||
var shareButton = {
|
||||
className: 'primary cp-share-with-friends',
|
||||
name: Messages.share_withFriends,
|
||||
onClick: function () {
|
||||
var href;
|
||||
nThen(function (waitFor) {
|
||||
var w = waitFor();
|
||||
// linkGetter can be async if this is a burn after reading URL
|
||||
var res = linkGetter({}, function (url) {
|
||||
if (!url) {
|
||||
waitFor.abort();
|
||||
return;
|
||||
}
|
||||
href = url;
|
||||
setTimeout(w);
|
||||
});
|
||||
if (res && /^http/.test(res)) {
|
||||
href = Hash.getRelativeHref(res);
|
||||
setTimeout(w);
|
||||
return;
|
||||
}
|
||||
}).nThen(function () {
|
||||
var $friends = $div.find('.cp-usergrid-user.cp-selected');
|
||||
$friends.each(function (i, el) {
|
||||
var curve = $(el).attr('data-curve');
|
||||
var ed = $(el).attr('data-ed');
|
||||
var friend = curve && friends[curve];
|
||||
var team = teams[ed];
|
||||
// If the selected element is a friend or a team without edit right,
|
||||
// send a notification
|
||||
var mailbox = friend || ((team && team.viewer) ? team : undefined);
|
||||
if (mailbox) { // Friend
|
||||
if (friends[curve] && !mailbox.notifications) { return; }
|
||||
if (mailbox.notifications && mailbox.curvePublic) {
|
||||
common.mailbox.sendTo("SHARE_PAD", {
|
||||
href: href,
|
||||
password: config.password,
|
||||
isTemplate: config.isTemplate,
|
||||
name: myName,
|
||||
title: title
|
||||
}, {
|
||||
viewed: team && team.id,
|
||||
channel: mailbox.notifications,
|
||||
curvePublic: mailbox.curvePublic
|
||||
});
|
||||
return;
|
||||
}
|
||||
}
|
||||
// If it's a team with edit right, add the pad directly
|
||||
if (!team) { return; }
|
||||
sframeChan.query('Q_STORE_IN_TEAM', {
|
||||
href: href,
|
||||
password: config.password,
|
||||
path: config.isTemplate ? ['template'] : undefined,
|
||||
title: title,
|
||||
teamId: team.id
|
||||
}, function (err) {
|
||||
if (err) { return void console.error(err); }
|
||||
});
|
||||
});
|
||||
|
||||
UI.findCancelButton().click();
|
||||
|
||||
// Update the "recently shared with" array:
|
||||
// Get the selected curves
|
||||
var curves = $friends.toArray().map(function (el) {
|
||||
return ($(el).attr('data-curve') || '').slice(0,8);
|
||||
}).filter(function (x) { return x; });
|
||||
// Prepend them to the "order" array
|
||||
Array.prototype.unshift.apply(order, curves);
|
||||
order = Util.deduplicateString(order);
|
||||
// Make sure we don't have "old" friends and save
|
||||
order = order.filter(function (curve) {
|
||||
return smallCurves.indexOf(curve) !== -1;
|
||||
});
|
||||
common.setAttribute(['general', 'share-friends'], order);
|
||||
if (onShare) {
|
||||
onShare.fire();
|
||||
}
|
||||
});
|
||||
},
|
||||
keys: [13]
|
||||
};
|
||||
|
||||
common.getAttribute(['general', 'share-friends'], function (err, val) {
|
||||
order = val || [];
|
||||
// Sort friends by "recently shared with"
|
||||
others.sort(function (a, b) {
|
||||
var ca = ($(a).attr('data-curve') || '').slice(0,8);
|
||||
var cb = ($(b).attr('data-curve') || '').slice(0,8);
|
||||
if (!ca && !cb) { return 0; }
|
||||
if (!ca) { return 1; }
|
||||
if (!cb) { return -1; }
|
||||
var ia = order.indexOf(ca);
|
||||
var ib = order.indexOf(cb);
|
||||
if (ia === -1 && ib === -1) { return 0; }
|
||||
if (ia === -1) { return 1; }
|
||||
if (ib === -1) { return -1; }
|
||||
return ia - ib;
|
||||
});
|
||||
// Reorder the friend icons
|
||||
others.forEach(function (el, i) {
|
||||
$(el).attr('data-order', i).css('order', i);
|
||||
});
|
||||
// Display them
|
||||
$(friendDiv).find('.cp-usergrid-grid').detach();
|
||||
$(friendDiv).append(h('div.cp-usergrid-grid', others));
|
||||
refreshButtons();
|
||||
});
|
||||
return {
|
||||
content: div,
|
||||
buttons: [shareButton]
|
||||
};
|
||||
};
|
||||
|
||||
var getEditableTeams = function (common, config) {
|
||||
var privateData = common.getMetadataMgr().getPrivateData();
|
||||
var teamsData = Util.tryParse(JSON.stringify(privateData.teams)) || {};
|
||||
var teams = {};
|
||||
Object.keys(teamsData).forEach(function (id) {
|
||||
// config.teamId only exists when we're trying to share a pad from a team drive
|
||||
// In this case, we don't want to share the pad with the current team
|
||||
if (config.teamId && config.teamId === id) { return; }
|
||||
var t = teamsData[id];
|
||||
teams[t.edPublic] = {
|
||||
viewer: !teamsData[id].hasSecondaryKey,
|
||||
notifications: t.notifications,
|
||||
curvePublic: t.curvePublic,
|
||||
displayName: t.name,
|
||||
edPublic: t.edPublic,
|
||||
avatar: t.avatar,
|
||||
id: id
|
||||
};
|
||||
});
|
||||
return teams;
|
||||
};
|
||||
var makeBurnAfterReadingUrl = function (common, href, channel, cb) {
|
||||
var keyPair = Hash.generateSignPair();
|
||||
var parsed = Hash.parsePadUrl(href);
|
||||
var newHref = parsed.getUrl({
|
||||
ownerKey: keyPair.safeSignKey
|
||||
});
|
||||
var sframeChan = common.getSframeChannel();
|
||||
var rtChannel;
|
||||
nThen(function (waitFor) {
|
||||
if (parsed.type !== "sheet") { return; }
|
||||
common.getPadAttribute('rtChannel', waitFor(function (err, chan) {
|
||||
rtChannel = chan;
|
||||
}));
|
||||
}).nThen(function (waitFor) {
|
||||
sframeChan.query('Q_SET_PAD_METADATA', {
|
||||
channel: channel,
|
||||
command: 'ADD_OWNERS',
|
||||
value: [keyPair.validateKey]
|
||||
}, waitFor(function (err) {
|
||||
if (err) {
|
||||
waitFor.abort();
|
||||
UI.warn(Messages.error);
|
||||
}
|
||||
}));
|
||||
if (rtChannel) {
|
||||
sframeChan.query('Q_SET_PAD_METADATA', {
|
||||
channel: rtChannel,
|
||||
command: 'ADD_OWNERS',
|
||||
value: [keyPair.validateKey]
|
||||
}, waitFor(function (err) {
|
||||
if (err) { console.error(err); }
|
||||
}));
|
||||
}
|
||||
}).nThen(function () {
|
||||
cb(newHref);
|
||||
});
|
||||
};
|
||||
|
||||
var makeFaqLink = function (opts) {
|
||||
var link = h('span', [
|
||||
h('i.fa.fa-question-circle'),
|
||||
h('a', {href: '#'}, Messages.passwordFaqLink)
|
||||
]);
|
||||
$(link).click(function () {
|
||||
opts.common.openURL(opts.origin + "/faq.html#security-pad_password");
|
||||
});
|
||||
return link;
|
||||
};
|
||||
|
||||
var makeCancelButton = function() {
|
||||
return {
|
||||
className: 'cancel',
|
||||
name: Messages.cancel,
|
||||
onClick: function () {},
|
||||
keys: [27]
|
||||
};
|
||||
};
|
||||
|
||||
var getContactsTab = function (Env, data, opts, _cb) {
|
||||
var cb = Util.once(Util.mkAsync(_cb));
|
||||
var common = Env.common;
|
||||
|
||||
var hasFriends = opts.hasFriends;
|
||||
var onFriendShare = Util.mkEvent();
|
||||
|
||||
var friendsObject = hasFriends ? createShareWithFriends(opts, onFriendShare, opts.getLinkValue) : UIElements.noContactsMessage(common);
|
||||
var friendsList = friendsObject.content;
|
||||
|
||||
onFriendShare.reg(opts.saveValue);
|
||||
|
||||
var contactsContent = h('div.cp-share-modal');
|
||||
var $contactsContent = $(contactsContent);
|
||||
$contactsContent.append(friendsList);
|
||||
|
||||
// Show alert if the pad is password protected
|
||||
if (opts.hasPassword) {
|
||||
$contactsContent.append(h('div.alert.alert-primary', [
|
||||
h('i.fa.fa-unlock'),
|
||||
Messages.share_contactPasswordAlert, h('br'),
|
||||
makeFaqLink(opts)
|
||||
]));
|
||||
}
|
||||
|
||||
// Burn after reading warning
|
||||
if (opts.barAlert) { $contactsContent.append(opts.barAlert.cloneNode(true)); }
|
||||
|
||||
var contactButtons = friendsObject.buttons;
|
||||
contactButtons.unshift(makeCancelButton());
|
||||
|
||||
cb(void 0, {
|
||||
content: contactsContent,
|
||||
buttons: contactButtons
|
||||
});
|
||||
};
|
||||
|
||||
var getLinkTab = function (Env, data, opts, _cb) {
|
||||
var cb = Util.once(Util.mkAsync(_cb));
|
||||
var common = Env.common;
|
||||
var origin = opts.origin;
|
||||
var pathname = opts.pathname;
|
||||
var hashes = opts.hashes;
|
||||
|
||||
// Create modal
|
||||
var linkContent = opts.sharedFolder ? [
|
||||
h('label', Messages.sharedFolders_share),
|
||||
h('br'),
|
||||
] : [
|
||||
UI.createCheckbox('cp-share-embed', Messages.share_linkEmbed, false, { mark: {tabindex:1} }),
|
||||
];
|
||||
linkContent.push(h('div.cp-spacer'));
|
||||
linkContent.push(UI.dialog.selectableArea('', { id: 'cp-share-link-preview', tabindex: 1, rows:3}));
|
||||
|
||||
// Show alert if the pad is password protected
|
||||
if (opts.hasPassword) {
|
||||
linkContent.push(h('div.alert.alert-primary', [
|
||||
h('i.fa.fa-lock'),
|
||||
Messages.share_linkPasswordAlert, h('br'),
|
||||
makeFaqLink(opts)
|
||||
]));
|
||||
}
|
||||
|
||||
// warning about sharing links
|
||||
var localStore = window.cryptpadStore;
|
||||
var dismissButton = h('span.fa.fa-times');
|
||||
var shareLinkWarning = h('div.alert.alert-warning.dismissable',
|
||||
{ style: 'display: none;' },
|
||||
[
|
||||
h('span.cp-inline-alert-text', Messages.share_linkWarning),
|
||||
dismissButton
|
||||
]);
|
||||
linkContent.push(shareLinkWarning);
|
||||
|
||||
localStore.get('hide-alert-shareLinkWarning', function (val) {
|
||||
if (val === '1') { return; }
|
||||
$(shareLinkWarning).show();
|
||||
|
||||
$(dismissButton).on('click', function () {
|
||||
localStore.put('hide-alert-shareLinkWarning', '1');
|
||||
$(shareLinkWarning).remove();
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
// Burn after reading
|
||||
if (opts.barAlert) { linkContent.push(opts.barAlert.cloneNode(true)); }
|
||||
|
||||
var link = h('div.cp-share-modal', linkContent);
|
||||
var $link = $(link);
|
||||
$link.find('#cp-share-link-preview').val(opts.getLinkValue());
|
||||
$link.find('input[type="checkbox"]').on('change', function () {
|
||||
$link.find('#cp-share-link-preview').val(opts.getLinkValue({
|
||||
embed: Util.isChecked($link.find('#cp-share-embed'))
|
||||
}));
|
||||
});
|
||||
|
||||
Messages.share_bar = "Generate link"; // XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX
|
||||
var linkButtons = [
|
||||
makeCancelButton(),
|
||||
!opts.sharedFolder && {
|
||||
className: 'secondary cp-nobar',
|
||||
name: Messages.share_linkOpen,
|
||||
onClick: function () {
|
||||
opts.saveValue();
|
||||
var v = opts.getLinkValue({
|
||||
embed: Util.isChecked($link.find('#cp-share-embed'))
|
||||
});
|
||||
window.open(v);
|
||||
return true;
|
||||
},
|
||||
keys: [[13, 'ctrl']]
|
||||
}, {
|
||||
className: 'primary cp-nobar',
|
||||
name: Messages.share_linkCopy,
|
||||
onClick: function () {
|
||||
opts.saveValue();
|
||||
var v = opts.getLinkValue({
|
||||
embed: Util.isChecked($link.find('#cp-share-embed'))
|
||||
});
|
||||
var success = Clipboard.copy(v);
|
||||
if (success) { UI.log(Messages.shareSuccess); }
|
||||
},
|
||||
keys: [13]
|
||||
}, {
|
||||
className: 'primary cp-bar',
|
||||
name: Messages.share_bar,
|
||||
onClick: function () {
|
||||
var barHref = origin + pathname + '#' + (hashes.viewHash || hashes.editHash);
|
||||
makeBurnAfterReadingUrl(common, barHref, opts.channel, function (url) {
|
||||
opts.burnAfterReadingUrl = url;
|
||||
opts.$rights.find('input[type="radio"]').trigger('change');
|
||||
});
|
||||
return true;
|
||||
},
|
||||
keys: []
|
||||
}
|
||||
];
|
||||
|
||||
$link.find('.cp-bar').hide();
|
||||
|
||||
cb(void 0, {
|
||||
content: link,
|
||||
buttons: linkButtons
|
||||
});
|
||||
};
|
||||
|
||||
var getEmbedTab = function (Env, data, opts, _cb) {
|
||||
var cb = Util.once(Util.mkAsync(_cb));
|
||||
|
||||
var embedContent = [
|
||||
h('p', Messages.viewEmbedTag),
|
||||
UI.dialog.selectableArea(opts.getEmbedValue(), { id: 'cp-embed-link-preview', tabindex: 1, rows: 3})
|
||||
];
|
||||
|
||||
// Show alert if the pad is password protected
|
||||
if (opts.hasPassword) {
|
||||
embedContent.push(h('div.alert.alert-primary', [
|
||||
h('i.fa.fa-lock'), ' ',
|
||||
Messages.share_embedPasswordAlert, h('br'),
|
||||
makeFaqLink(opts)
|
||||
]));
|
||||
}
|
||||
|
||||
var embedButtons = [
|
||||
makeCancelButton(),
|
||||
{
|
||||
className: 'primary',
|
||||
name: Messages.share_linkCopy,
|
||||
onClick: function () {
|
||||
var v = opts.getEmbedValue();
|
||||
var success = Clipboard.copy(v);
|
||||
if (success) { UI.log(Messages.shareSuccess); }
|
||||
},
|
||||
keys: [13]
|
||||
}];
|
||||
|
||||
var embed = h('div.cp-share-modal', embedContent);
|
||||
var $embed = $(embed);
|
||||
|
||||
$embed.find('#cp-embed-link-preview').val(opts.getEmbedValue());
|
||||
|
||||
cb(void 0, {
|
||||
content: embed,
|
||||
buttons: embedButtons
|
||||
});
|
||||
};
|
||||
|
||||
var getRightsHeader = function (common, opts) {
|
||||
var hashes = opts.hashes;
|
||||
var hash = hashes.editHash || hashes.viewHash;
|
||||
var origin = opts.origin;
|
||||
var pathname = opts.pathname;
|
||||
var parsed = Hash.parsePadUrl(pathname);
|
||||
var canPresent = ['code', 'slide'].indexOf(parsed.type) !== -1;
|
||||
var canBAR = parsed.type !== 'drive';
|
||||
|
||||
var burnAfterReading = (hashes.viewHash && canBAR) ?
|
||||
UI.createRadio('accessRights', 'cp-share-bar', Messages.burnAfterReading_linkBurnAfterReading, false, {
|
||||
mark: {tabindex:1},
|
||||
label: {style: "display: none;"}
|
||||
}) : undefined;
|
||||
var rights = h('div.msg.cp-inline-radio-group', [
|
||||
h('label', Messages.share_linkAccess),
|
||||
h('div.radio-group',[
|
||||
UI.createRadio('accessRights', 'cp-share-editable-false',
|
||||
Messages.share_linkView, true, { mark: {tabindex:1} }),
|
||||
canPresent ? UI.createRadio('accessRights', 'cp-share-present',
|
||||
Messages.share_linkPresent, false, { mark: {tabindex:1} }) : undefined,
|
||||
UI.createRadio('accessRights', 'cp-share-editable-true',
|
||||
Messages.share_linkEdit, false, { mark: {tabindex:1} })]),
|
||||
burnAfterReading
|
||||
]);
|
||||
|
||||
// Burn after reading
|
||||
// Check if we are an owner of this pad. If we are, we can show the burn after reading option.
|
||||
// When BAR is selected, display a red message indicating the consequence and add
|
||||
// the options to generate the BAR url
|
||||
opts.barAlert = h('div.alert.alert-danger.cp-alertify-bar-selected', {
|
||||
style: 'display: none;'
|
||||
}, Messages.burnAfterReading_warningLink);
|
||||
var channel = opts.channel = Hash.getSecrets('pad', hash, opts.password).channel;
|
||||
common.getPadMetadata({
|
||||
channel: channel
|
||||
}, function (obj) {
|
||||
if (!obj || obj.error) { return; }
|
||||
var priv = common.getMetadataMgr().getPrivateData();
|
||||
// Not an owner: don't display the burn after reading option
|
||||
if (!Array.isArray(obj.owners) || obj.owners.indexOf(priv.edPublic) === -1) {
|
||||
$(burnAfterReading).remove();
|
||||
return;
|
||||
}
|
||||
// When the burn after reading option is selected, transform the modal buttons
|
||||
$(burnAfterReading).css({
|
||||
display: 'flex'
|
||||
});
|
||||
});
|
||||
|
||||
var $rights = $(rights);
|
||||
|
||||
opts.saveValue = function () {
|
||||
var edit = Util.isChecked($rights.find('#cp-share-editable-true'));
|
||||
var present = Util.isChecked($rights.find('#cp-share-present'));
|
||||
common.setAttribute(['general', 'share'], {
|
||||
edit: edit,
|
||||
present: present
|
||||
});
|
||||
};
|
||||
opts.getLinkValue = function (initValue, cb) {
|
||||
var val = initValue || {};
|
||||
var edit = val.edit !== undefined ? val.edit : Util.isChecked($rights.find('#cp-share-editable-true'));
|
||||
var embed = val.embed;
|
||||
var present = val.present !== undefined ? val.present : Util.isChecked($rights.find('#cp-share-present'));
|
||||
var burnAfterReading = Util.isChecked($rights.find('#cp-share-bar'));
|
||||
if (burnAfterReading && !opts.burnAfterReadingUrl) {
|
||||
if (cb) { // Called from the contacts tab, "share" button
|
||||
var barHref = origin + pathname + '#' + (hashes.viewHash || hashes.editHash);
|
||||
return makeBurnAfterReadingUrl(common, barHref, channel, function (url) {
|
||||
cb(url);
|
||||
});
|
||||
}
|
||||
return Messages.burnAfterReading_generateLink;
|
||||
}
|
||||
var hash = (!hashes.viewHash || (edit && hashes.editHash)) ? hashes.editHash
|
||||
: hashes.viewHash;
|
||||
var href = burnAfterReading ? opts.burnAfterReadingUrl
|
||||
: (origin + pathname + '#' + hash);
|
||||
var parsed = Hash.parsePadUrl(href);
|
||||
return origin + parsed.getUrl({embed: embed, present: present});
|
||||
};
|
||||
opts.getEmbedValue = function () {
|
||||
var url = opts.getLinkValue({
|
||||
embed: true
|
||||
});
|
||||
return '<iframe src="' + url + '"></iframe>';
|
||||
};
|
||||
|
||||
// disable edit share options if you don't have edit rights
|
||||
if (!hashes.editHash) {
|
||||
$rights.find('#cp-share-editable-false').attr('checked', true);
|
||||
$rights.find('#cp-share-editable-true').removeAttr('checked').attr('disabled', true);
|
||||
} else if (!hashes.viewHash) {
|
||||
$rights.find('#cp-share-editable-false').removeAttr('checked').attr('disabled', true);
|
||||
$rights.find('#cp-share-present').removeAttr('checked').attr('disabled', true);
|
||||
$rights.find('#cp-share-editable-true').attr('checked', true);
|
||||
}
|
||||
|
||||
var getLink = function () {
|
||||
return $rights.parent().find('#cp-share-link-preview');
|
||||
};
|
||||
var getEmbed = function () {
|
||||
return $rights.parent().find('#cp-embed-link-preview');
|
||||
};
|
||||
|
||||
// update values for link and embed preview when radio btns change
|
||||
$rights.find('input[type="radio"]').on('change', function () {
|
||||
getLink().val(opts.getLinkValue({
|
||||
embed: Util.isChecked($('.alertify').find('#cp-share-embed'))
|
||||
}));
|
||||
// Hide or show the burn after reading alert
|
||||
if (Util.isChecked($rights.find('#cp-share-bar')) && !opts.burnAfterReadingUrl) {
|
||||
$('.cp-alertify-bar-selected').show();
|
||||
// Show burn after reading button
|
||||
$('.alertify').find('.cp-bar').show();
|
||||
$('.alertify').find('.cp-nobar').hide();
|
||||
return;
|
||||
}
|
||||
getEmbed().val(opts.getEmbedValue());
|
||||
// Hide burn after reading button
|
||||
$('.alertify').find('.cp-nobar').show();
|
||||
$('.alertify').find('.cp-bar').hide();
|
||||
$('.cp-alertify-bar-selected').hide();
|
||||
});
|
||||
|
||||
// Set default values
|
||||
common.getAttribute(['general', 'share'], function (err, val) {
|
||||
val = val || {};
|
||||
if (val.present && canPresent) {
|
||||
$rights.find('#cp-share-editable-false').prop('checked', false);
|
||||
$rights.find('#cp-share-editable-true').prop('checked', false);
|
||||
$rights.find('#cp-share-present').prop('checked', true);
|
||||
} else if ((val.edit === false && hashes.viewHash) || !hashes.editHash) {
|
||||
$rights.find('#cp-share-editable-false').prop('checked', true);
|
||||
$rights.find('#cp-share-editable-true').prop('checked', false);
|
||||
$rights.find('#cp-share-present').prop('checked', false);
|
||||
} else {
|
||||
$rights.find('#cp-share-editable-true').prop('checked', true);
|
||||
$rights.find('#cp-share-editable-false').prop('checked', false);
|
||||
$rights.find('#cp-share-present').prop('checked', false);
|
||||
}
|
||||
delete val.embed;
|
||||
if (!canPresent) {
|
||||
delete val.present;
|
||||
}
|
||||
getLink().val(opts.getLinkValue(val));
|
||||
});
|
||||
common.getMetadataMgr().onChange(function () {
|
||||
// "hashes" is only available is the secure "share" app
|
||||
var _hashes = common.getMetadataMgr().getPrivateData().hashes;
|
||||
if (!_hashes) { return; }
|
||||
hashes = _hashes;
|
||||
getLink().val(opts.getLinkValue());
|
||||
});
|
||||
|
||||
return $rights;
|
||||
};
|
||||
|
||||
// In the share modal, tabs need to share data between themselves.
|
||||
// To do so we're using "opts" to store data and functions
|
||||
Share.getShareModal = function (common, opts, cb) {
|
||||
cb = cb || function () {};
|
||||
opts = opts || {};
|
||||
opts.access = true; // Allow the use of the modal even if the pad is not stored
|
||||
|
||||
var hashes = opts.hashes;
|
||||
if (!hashes || (!hashes.editHash && !hashes.viewHash)) { return; }
|
||||
|
||||
var teams = getEditableTeams(common, opts);
|
||||
opts.teams = teams;
|
||||
var hasFriends = opts.hasFriends = Object.keys(opts.friends || {}).length ||
|
||||
Object.keys(teams).length;
|
||||
|
||||
// check if the pad is password protected
|
||||
var pathname = opts.pathname;
|
||||
var hash = hashes.editHash || hashes.viewHash;
|
||||
var href = pathname + '#' + hash;
|
||||
var parsedHref = Hash.parsePadUrl(href);
|
||||
opts.hasPassword = parsedHref.hashData.password;
|
||||
|
||||
|
||||
var $rights = opts.$rights = getRightsHeader(common, opts);
|
||||
var resetTab = function () {
|
||||
$rights.show();
|
||||
$rights.find('label.cp-radio').show();
|
||||
};
|
||||
var onShowEmbed = function () {
|
||||
$rights.find('#cp-share-bar').closest('label').hide();
|
||||
$rights.find('input[type="radio"]:enabled').first().prop('checked', 'checked');
|
||||
$rights.find('input[type="radio"]').trigger('change');
|
||||
};
|
||||
var onShowContacts = function () {
|
||||
if (!hasFriends) {
|
||||
$rights.hide();
|
||||
}
|
||||
};
|
||||
|
||||
var tabs = [{
|
||||
getTab: getContactsTab,
|
||||
title: Messages.share_contactCategory,
|
||||
icon: "fa fa-addessèbook",
|
||||
active: hasFriends,
|
||||
onShow: onShowContacts,
|
||||
onHide: resetTab
|
||||
}, {
|
||||
getTab: getLinkTab,
|
||||
title: Messages.share_linkCategory,
|
||||
icon: "fa fa-link",
|
||||
active: !hasFriends,
|
||||
}, {
|
||||
getTab: getEmbedTab,
|
||||
title: Messages.share_embedCategory,
|
||||
icon: "fa fa-code",
|
||||
onShow: onShowEmbed,
|
||||
onHide: resetTab
|
||||
}];
|
||||
Modal.getModal(common, opts, tabs, function (err, modal) {
|
||||
$(modal).find('.cp-bar').hide();
|
||||
// Prepend the "rights" radio selection
|
||||
$(modal).find('.alertify-tabs-titles').after($rights);
|
||||
// callback
|
||||
cb(err, modal);
|
||||
});
|
||||
};
|
||||
|
||||
var getFileContactsTab = function (Env, data, opts, _cb) {
|
||||
var cb = Util.once(Util.mkAsync(_cb));
|
||||
var common = Env.common;
|
||||
var friendsObject = opts.hasFriends ? createShareWithFriends(opts, null, opts.getLinkValue) : UIElements.noContactsMessage(common);
|
||||
var friendsList = friendsObject.content;
|
||||
|
||||
var contactsContent = h('div.cp-share-modal');
|
||||
var $contactsContent = $(contactsContent);
|
||||
$contactsContent.append(friendsList);
|
||||
|
||||
// Show alert if the pad is password protected
|
||||
if (opts.hasPassword) {
|
||||
$contactsContent.append(h('div.alert.alert-primary', [
|
||||
h('i.fa.fa-lock'),
|
||||
Messages.share_linkPasswordAlert, h('br'),
|
||||
makeFaqLink(opts)
|
||||
]));
|
||||
}
|
||||
|
||||
var contactButtons = friendsObject.buttons;
|
||||
contactButtons.unshift(makeCancelButton());
|
||||
|
||||
cb(void 0, {
|
||||
content: contactsContent,
|
||||
buttons: contactButtons
|
||||
});
|
||||
};
|
||||
|
||||
var getFileLinkTab = function (Env, data, opts, _cb) {
|
||||
var cb = Util.once(Util.mkAsync(_cb));
|
||||
var linkContent = [
|
||||
UI.dialog.selectableArea(opts.getLinkValue(), {
|
||||
id: 'cp-share-link-preview', tabindex: 1, rows:2
|
||||
})
|
||||
];
|
||||
|
||||
// Show alert if the pad is password protected
|
||||
if (opts.hasPassword) {
|
||||
linkContent.push(h('div.alert.alert-primary', [
|
||||
h('i.fa.fa-lock'),
|
||||
Messages.share_linkPasswordAlert, h('br'),
|
||||
makeFaqLink(opts)
|
||||
]));
|
||||
}
|
||||
|
||||
// warning about sharing links
|
||||
var localStore = window.cryptpadStore;
|
||||
var dismissButton = h('span.fa.fa-times');
|
||||
var shareLinkWarning = h('div.alert.alert-warning.dismissable',
|
||||
{ style: 'display: none;' },
|
||||
[
|
||||
h('span.cp-inline-alert-text', Messages.share_linkWarning),
|
||||
dismissButton
|
||||
]);
|
||||
linkContent.push(shareLinkWarning);
|
||||
|
||||
localStore.get('hide-alert-shareLinkWarning', function (val) {
|
||||
if (val === '1') { return; }
|
||||
$(shareLinkWarning).show();
|
||||
|
||||
$(dismissButton).on('click', function () {
|
||||
localStore.put('hide-alert-shareLinkWarning', '1');
|
||||
$(shareLinkWarning).remove();
|
||||
});
|
||||
});
|
||||
|
||||
var link = h('div.cp-share-modal', linkContent);
|
||||
var linkButtons = [
|
||||
makeCancelButton(),
|
||||
{
|
||||
className: 'primary',
|
||||
name: Messages.share_linkCopy,
|
||||
onClick: function () {
|
||||
var v = opts.getLinkValue();
|
||||
var success = Clipboard.copy(v);
|
||||
if (success) { UI.log(Messages.shareSuccess);
|
||||
}
|
||||
},
|
||||
keys: [13]
|
||||
}
|
||||
];
|
||||
|
||||
cb(void 0, {
|
||||
content: link,
|
||||
buttons: linkButtons
|
||||
});
|
||||
};
|
||||
|
||||
var getFileEmbedTab = function (Env, data, opts, _cb) {
|
||||
var cb = Util.once(Util.mkAsync(_cb));
|
||||
var common = Env.common;
|
||||
var fileData = opts.fileData;
|
||||
|
||||
var embed = h('div.cp-share-modal', [
|
||||
h('p', Messages.fileEmbedScript),
|
||||
UI.dialog.selectable(common.getMediatagScript()),
|
||||
h('p', Messages.fileEmbedTag),
|
||||
UI.dialog.selectable(common.getMediatagFromHref(fileData)),
|
||||
]);
|
||||
|
||||
// Show alert if the pad is password protected
|
||||
if (opts.hasPassword) {
|
||||
$(embed).append(h('div.alert.alert-primary', [
|
||||
h('i.fa.fa-lock'),
|
||||
Messages.share_linkPasswordAlert, h('br'),
|
||||
makeFaqLink(opts)
|
||||
]));
|
||||
}
|
||||
|
||||
var embedButtons = [{
|
||||
className: 'cancel',
|
||||
name: Messages.cancel,
|
||||
onClick: function () {},
|
||||
keys: [27]
|
||||
}, {
|
||||
className: 'primary',
|
||||
name: Messages.share_mediatagCopy,
|
||||
onClick: function () {
|
||||
var v = common.getMediatagFromHref(opts.fileData);
|
||||
var success = Clipboard.copy(v);
|
||||
if (success) { UI.log(Messages.shareSuccess); }
|
||||
},
|
||||
keys: [13]
|
||||
}];
|
||||
|
||||
cb(void 0, {
|
||||
content: embed,
|
||||
buttons: embedButtons
|
||||
});
|
||||
};
|
||||
|
||||
Share.getFileShareModal = function (common, opts, cb) {
|
||||
cb = cb || function () {};
|
||||
opts = opts || {};
|
||||
opts.access = true; // Allow the use of the modal even if the pad is not stored
|
||||
|
||||
var hashes = opts.hashes;
|
||||
if (!hashes || !hashes.fileHash) { return; }
|
||||
|
||||
var teams = getEditableTeams(common, opts);
|
||||
opts.teams = teams;
|
||||
var hasFriends = opts.hasFriends = Object.keys(opts.friends || {}).length ||
|
||||
Object.keys(teams).length;
|
||||
|
||||
// check if the pad is password protected
|
||||
var origin = opts.origin;
|
||||
var pathname = opts.pathname;
|
||||
var url = opts.url = origin + pathname + '#' + hashes.fileHash;
|
||||
var parsedHref = Hash.parsePadUrl(url);
|
||||
opts.hasPassword = parsedHref.hashData.password;
|
||||
opts.getLinkValue = function () { return url; };
|
||||
|
||||
var tabs = [{
|
||||
getTab: getFileContactsTab,
|
||||
title: Messages.share_contactCategory,
|
||||
icon: "fa fa-addessèbook",
|
||||
active: hasFriends,
|
||||
}, {
|
||||
getTab: getFileLinkTab,
|
||||
title: Messages.share_linkCategory,
|
||||
icon: "fa fa-link",
|
||||
active: !hasFriends,
|
||||
}, {
|
||||
getTab: getFileEmbedTab,
|
||||
title: Messages.share_embedCategory,
|
||||
icon: "fa fa-code",
|
||||
}];
|
||||
Modal.getModal(common, opts, tabs, cb);
|
||||
};
|
||||
|
||||
return Share;
|
||||
});
|
|
@ -48,12 +48,19 @@ define([
|
|||
titleUpdated = cb;
|
||||
};
|
||||
|
||||
var ret = {
|
||||
updateTitle: exp.updateTitle,
|
||||
suggestName: suggestTitle,
|
||||
defaultName: exp.defaultTitle,
|
||||
getTitle: exp.getTitle
|
||||
};
|
||||
|
||||
metadataMgr.onChange(function () {
|
||||
var md = metadataMgr.getMetadata();
|
||||
if ($title) {
|
||||
$title.find('input').prop('placeholder', md.defaultTitle);
|
||||
}
|
||||
exp.defaultTitle = md.defaultTitle;
|
||||
ret.defaultName = exp.defaultTitle = md.defaultTitle;
|
||||
});
|
||||
metadataMgr.onTitleChange(function (title, defaultTitle) {
|
||||
if ($title) {
|
||||
|
@ -79,12 +86,7 @@ define([
|
|||
});
|
||||
|
||||
exp.getTitleConfig = function () {
|
||||
return {
|
||||
updateTitle: exp.updateTitle,
|
||||
suggestName: suggestTitle,
|
||||
defaultName: exp.defaultTitle,
|
||||
getTitle: exp.getTitle
|
||||
};
|
||||
return ret;
|
||||
};
|
||||
|
||||
exp.onTitleChange = evTitleChange.reg;
|
||||
|
|
|
@ -45,32 +45,33 @@ define([
|
|||
// Share modal
|
||||
create['share'] = function (data) {
|
||||
var priv = metadataMgr.getPrivateData();
|
||||
var f = (data && data.file) ? UIElements.createFileShareModal
|
||||
: UIElements.createShareModal;
|
||||
|
||||
var friends = common.getFriends();
|
||||
|
||||
var _modal;
|
||||
var modal = f({
|
||||
origin: priv.origin,
|
||||
pathname: priv.pathname,
|
||||
password: priv.password,
|
||||
isTemplate: priv.isTemplate,
|
||||
hashes: priv.hashes,
|
||||
common: common,
|
||||
title: data.title,
|
||||
friends: friends,
|
||||
onClose: function () {
|
||||
if (_modal && _modal.close) { _modal.close(); }
|
||||
hideIframe();
|
||||
},
|
||||
fileData: {
|
||||
hash: priv.hashes.fileHash,
|
||||
password: priv.password
|
||||
}
|
||||
require(['/common/inner/share.js'], function (Share) {
|
||||
var f = (data && data.file) ? Share.getFileShareModal
|
||||
: Share.getShareModal;
|
||||
f(common, {
|
||||
origin: priv.origin,
|
||||
pathname: priv.pathname,
|
||||
password: priv.password,
|
||||
isTemplate: priv.isTemplate,
|
||||
hashes: priv.hashes,
|
||||
common: common,
|
||||
title: data.title,
|
||||
versionHash: data.versionHash,
|
||||
friends: friends,
|
||||
onClose: function () {
|
||||
hideIframe();
|
||||
},
|
||||
fileData: {
|
||||
hash: priv.hashes.fileHash,
|
||||
password: priv.password
|
||||
}
|
||||
}, function (e, modal) {
|
||||
if (e) { console.error(e); }
|
||||
displayed = modal;
|
||||
});
|
||||
});
|
||||
_modal = UI.openCustomModal(modal);
|
||||
displayed = modal;
|
||||
};
|
||||
|
||||
// Properties modal
|
||||
|
|
Loading…
Reference in New Issue