Implement UI to share a pad with a friend
This commit is contained in:
parent
8e7858e6ae
commit
39d2496330
@ -144,6 +144,10 @@
|
|||||||
padding: @alertify_padding-base;
|
padding: @alertify_padding-base;
|
||||||
background: #fff;
|
background: #fff;
|
||||||
box-shadow: @alertify_box-shadow;
|
box-shadow: @alertify_box-shadow;
|
||||||
|
&.wide {
|
||||||
|
width: 1000px;
|
||||||
|
max-width: 70%;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.msg {
|
.msg {
|
||||||
|
|||||||
@ -156,12 +156,14 @@ define([
|
|||||||
]);
|
]);
|
||||||
};
|
};
|
||||||
|
|
||||||
dialog.frame = function (content) {
|
dialog.frame = function (content, opt) {
|
||||||
|
opt = opt || {};
|
||||||
|
var cls = opt.wide ? '.wide' : '';
|
||||||
return $(h('div.alertify', {
|
return $(h('div.alertify', {
|
||||||
tabindex: 1,
|
tabindex: 1,
|
||||||
}, [
|
}, [
|
||||||
h('div.dialog', [
|
h('div.dialog', [
|
||||||
h('div', content),
|
h('div'+cls, content),
|
||||||
])
|
])
|
||||||
])).click(function (e) {
|
])).click(function (e) {
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
@ -376,10 +378,10 @@ define([
|
|||||||
if (opt.forefront) { $(frame).addClass('forefront'); }
|
if (opt.forefront) { $(frame).addClass('forefront'); }
|
||||||
return frame;
|
return frame;
|
||||||
};
|
};
|
||||||
UI.openCustomModal = function (content) {
|
UI.openCustomModal = function (content, opt) {
|
||||||
var frame = dialog.frame([
|
var frame = dialog.frame([
|
||||||
content
|
content
|
||||||
]);
|
], opt);
|
||||||
$(frame).find('button[data-keys]').each(function (i, el) {
|
$(frame).find('button[data-keys]').each(function (i, el) {
|
||||||
var keys = JSON.parse($(el).attr('data-keys'));
|
var keys = JSON.parse($(el).attr('data-keys'));
|
||||||
customListenForKeys(keys, function () {
|
customListenForKeys(keys, function () {
|
||||||
|
|||||||
@ -316,6 +316,167 @@ define([
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
var getFriendsList = function (common) {
|
||||||
|
var priv = common.getMetadataMgr().getPrivateData();
|
||||||
|
var friends = priv.friends;
|
||||||
|
var order = [];
|
||||||
|
if (!friends) { return; }
|
||||||
|
|
||||||
|
// XXX
|
||||||
|
for (var i = 0; i < 30; i++) {
|
||||||
|
friends[i] = {
|
||||||
|
curvePublic: Hash.createChannelId(),
|
||||||
|
displayName: i+ ' blu'
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
var others = Object.keys(friends).map(function (curve, i) {
|
||||||
|
var data = friends[curve];
|
||||||
|
var avatar = h('span.cp-share-friend-avatar.cp-avatar');
|
||||||
|
UIElements.displayAvatar(common, $(avatar), data.avatar, data.displayName);
|
||||||
|
return h('div.cp-share-friend', {
|
||||||
|
'data-curve': data.curvePublic,
|
||||||
|
'data-name': data.displayName,
|
||||||
|
'data-order': i,
|
||||||
|
style: 'order:'+i+';'
|
||||||
|
},[
|
||||||
|
avatar,
|
||||||
|
h('span.cp-share-friend-name', data.displayName)
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
var smallCurves = Object.keys(friends).map(function (c) {
|
||||||
|
return friends[c].curvePublic.slice(0,8);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Fill with fake friends to have a uniform spacing (from the flexbox)
|
||||||
|
var addFake = function (els) {
|
||||||
|
$(bloc).find('.cp-fake-friend').remove();
|
||||||
|
var n = (6 - els.length%6)%6;
|
||||||
|
for (var j = 0; j < n; j++) {
|
||||||
|
els.push(h('div.cp-share-friend.cp-fake-friend', {
|
||||||
|
style: 'order:9999999;'
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
addFake(others);
|
||||||
|
var noOthers = others.length === 0 ? '.cp-recent-only' : '';
|
||||||
|
|
||||||
|
var buttonSelect = h('button.cp-share-with-friends', Messages.shareSelectAll || 'Select'); // XXX
|
||||||
|
var buttonDeselect = h('button.cp-share-with-friends', Messages.shareDeselectAll || 'Deselect'); // XXX
|
||||||
|
var inputFilter = h('input', {
|
||||||
|
placeholder: 'Search friend...'
|
||||||
|
});
|
||||||
|
|
||||||
|
var bloc = h('div.cp-share-friends.cp-share-column' + noOthers, [
|
||||||
|
h('label', Messages.share_linkFriends || "Friends"), // XXX
|
||||||
|
h('div.cp-share-grid-filter', [
|
||||||
|
inputFilter,
|
||||||
|
buttonSelect,
|
||||||
|
buttonDeselect
|
||||||
|
]),
|
||||||
|
]);
|
||||||
|
var $bloc = $(bloc);
|
||||||
|
|
||||||
|
var redraw = function () {
|
||||||
|
var name = $(inputFilter).val().trim().replace(/"/g, '');
|
||||||
|
$bloc.find('.cp-share-friend').show();
|
||||||
|
if (!name) { return; }
|
||||||
|
$bloc.find('.cp-share-friend:not(.cp-selected):not([data-name*="'+name+'"])').hide();
|
||||||
|
};
|
||||||
|
|
||||||
|
$(inputFilter).on('keydown keyup change', redraw);
|
||||||
|
$(buttonSelect).click(function () {
|
||||||
|
$bloc.find('.cp-share-friend:not(.cp-selected):visible').addClass('cp-selected');
|
||||||
|
});
|
||||||
|
$(buttonDeselect).click(function () {
|
||||||
|
$bloc.find('.cp-share-friend.cp-selected').removeClass('cp-selected').each(function (i, el) {
|
||||||
|
var order = $(el).attr('data-order');
|
||||||
|
if (!order) { return; }
|
||||||
|
$(el).attr('style', 'order:'+order);
|
||||||
|
});
|
||||||
|
redraw();
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log(smallCurves);
|
||||||
|
var refreshButtons = function () {
|
||||||
|
var $nav = $bloc.parents('.alertify-tabs-content').find('nav');
|
||||||
|
if (!$nav.find('.cp-share-with-friends').length) {
|
||||||
|
var button = h('button.primary.cp-share-with-friends', {
|
||||||
|
'data-keys': '[13]'
|
||||||
|
}, Messages.shareLinkWithFriends || 'Share with friends'); // XXX
|
||||||
|
$(button).click(function () {
|
||||||
|
// Get the selected curves
|
||||||
|
var $friends = $bloc.find('.cp-share-friend.cp-selected');
|
||||||
|
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);
|
||||||
|
console.log(order);
|
||||||
|
order = Util.deduplicateString(order);
|
||||||
|
console.log(order);
|
||||||
|
// Make sure we don't have "old" friends and save
|
||||||
|
order = order.filter(function (curve) {
|
||||||
|
return smallCurves.indexOf(curve) !== -1;
|
||||||
|
});
|
||||||
|
console.log(order);
|
||||||
|
common.setAttribute(['general', 'share-friends'], order);
|
||||||
|
|
||||||
|
// XXX send to mailboxes
|
||||||
|
// Notes: we need to filter the friend to only have th eones with mailboxes!
|
||||||
|
});
|
||||||
|
$nav.append(button);
|
||||||
|
}
|
||||||
|
|
||||||
|
var friendMode = $bloc.find('.cp-share-friend.cp-selected').length;
|
||||||
|
if (friendMode) {
|
||||||
|
$nav.find('button.primary[data-keys]').hide();
|
||||||
|
$nav.find('button.cp-share-with-friends').show();
|
||||||
|
} else {
|
||||||
|
$nav.find('button.primary[data-keys]').show();
|
||||||
|
$nav.find('button.cp-share-with-friends').hide();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
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) {
|
||||||
|
if ($(el).is('.cp-fake-friend')) { return; }
|
||||||
|
$(el).attr('data-order', i).css('order', i);
|
||||||
|
});
|
||||||
|
// Display them
|
||||||
|
$bloc.append(h('div.cp-share-grid', others));
|
||||||
|
$bloc.find('.cp-share-friend').click(function (e) {
|
||||||
|
var sel = $(this).hasClass('cp-selected');
|
||||||
|
if (!sel) {
|
||||||
|
$(this).addClass('cp-selected');
|
||||||
|
} else {
|
||||||
|
var order = $(this).attr('data-order');
|
||||||
|
order = order ? 'order:'+order : '';
|
||||||
|
$(this).removeClass('cp-selected').attr('style', order);
|
||||||
|
}
|
||||||
|
refreshButtons();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
return bloc;
|
||||||
|
};
|
||||||
|
|
||||||
UIElements.createShareModal = function (config) {
|
UIElements.createShareModal = function (config) {
|
||||||
var origin = config.origin;
|
var origin = config.origin;
|
||||||
var pathname = config.pathname;
|
var pathname = config.pathname;
|
||||||
@ -325,32 +486,37 @@ define([
|
|||||||
if (!hashes) { return; }
|
if (!hashes) { return; }
|
||||||
|
|
||||||
// Share link tab
|
// Share link tab
|
||||||
var link = h('div.cp-share-modal', [
|
var friendsList = getFriendsList(common);
|
||||||
h('label', Messages.share_linkAccess),
|
var link = h('div.cp-share-modal.cp-share-columns', [
|
||||||
h('br'),
|
h('div.cp-share-column', [
|
||||||
UI.createRadio('cp-share-editable', 'cp-share-editable-true',
|
h('p', 'Select the access rights you want to use and copy the share URL or send it directly to your CryptPad friends'), // XXX
|
||||||
Messages.share_linkEdit, true, { mark: {tabindex:1} }),
|
h('label', Messages.share_linkAccess),
|
||||||
UI.createRadio('cp-share-editable', 'cp-share-editable-false',
|
h('br'),
|
||||||
Messages.share_linkView, false, { mark: {tabindex:1} }),
|
UI.createRadio('cp-share-editable', 'cp-share-editable-true',
|
||||||
/*h('input#cp-share-editable-true.cp-share-editable-value', {
|
Messages.share_linkEdit, true, { mark: {tabindex:1} }),
|
||||||
type: 'radio',
|
UI.createRadio('cp-share-editable', 'cp-share-editable-false',
|
||||||
name: 'cp-share-editable',
|
Messages.share_linkView, false, { mark: {tabindex:1} }),
|
||||||
value: 1,
|
/*h('input#cp-share-editable-true.cp-share-editable-value', {
|
||||||
}),
|
type: 'radio',
|
||||||
h('label', { 'for': 'cp-share-editable-true' }, Messages.share_linkEdit),
|
name: 'cp-share-editable',
|
||||||
h('input#cp-share-editable-false.cp-share-editable-value', {
|
value: 1,
|
||||||
type: 'radio',
|
}),
|
||||||
name: 'cp-share-editable',
|
h('label', { 'for': 'cp-share-editable-true' }, Messages.share_linkEdit),
|
||||||
value: 0
|
h('input#cp-share-editable-false.cp-share-editable-value', {
|
||||||
}),
|
type: 'radio',
|
||||||
h('label', { 'for': 'cp-share-editable-false' }, Messages.share_linkView),*/
|
name: 'cp-share-editable',
|
||||||
h('br'),
|
value: 0
|
||||||
h('label', Messages.share_linkOptions),
|
}),
|
||||||
h('br'),
|
h('label', { 'for': 'cp-share-editable-false' }, Messages.share_linkView),*/
|
||||||
UI.createCheckbox('cp-share-embed', Messages.share_linkEmbed, false, { mark: {tabindex:1} }),
|
h('br'),
|
||||||
UI.createCheckbox('cp-share-present', Messages.share_linkPresent, false, { mark: {tabindex:1} }),
|
h('label', Messages.share_linkOptions),
|
||||||
h('br'),
|
h('br'),
|
||||||
UI.dialog.selectable('', { id: 'cp-share-link-preview', tabindex: 1 })
|
UI.createCheckbox('cp-share-embed', Messages.share_linkEmbed, false, { mark: {tabindex:1} }),
|
||||||
|
UI.createCheckbox('cp-share-present', Messages.share_linkPresent, false, { mark: {tabindex:1} }),
|
||||||
|
h('br'),
|
||||||
|
UI.dialog.selectable('', { id: 'cp-share-link-preview', tabindex: 1 }),
|
||||||
|
]),
|
||||||
|
friendsList
|
||||||
]);
|
]);
|
||||||
if (!hashes.editHash) {
|
if (!hashes.editHash) {
|
||||||
$(link).find('#cp-share-editable-false').attr('checked', true);
|
$(link).find('#cp-share-editable-false').attr('checked', true);
|
||||||
@ -407,7 +573,7 @@ define([
|
|||||||
}];
|
}];
|
||||||
var frameLink = UI.dialog.customModal(link, {
|
var frameLink = UI.dialog.customModal(link, {
|
||||||
buttons: linkButtons,
|
buttons: linkButtons,
|
||||||
onClose: config.onClose
|
onClose: config.onClose,
|
||||||
});
|
});
|
||||||
|
|
||||||
// Embed tab
|
// Embed tab
|
||||||
@ -438,7 +604,10 @@ define([
|
|||||||
},
|
},
|
||||||
keys: [13]
|
keys: [13]
|
||||||
}];
|
}];
|
||||||
var frameEmbed = UI.dialog.customModal(embed, { buttons: embedButtons});
|
var frameEmbed = UI.dialog.customModal(embed, {
|
||||||
|
buttons: embedButtons,
|
||||||
|
onClose: config.onClose,
|
||||||
|
});
|
||||||
|
|
||||||
// Create modal
|
// Create modal
|
||||||
var tabs = [{
|
var tabs = [{
|
||||||
|
|||||||
@ -739,8 +739,9 @@ define([
|
|||||||
ShareModal.$iframe = $('<iframe>', {id: 'sbox-share-iframe'}).appendTo($('body'));
|
ShareModal.$iframe = $('<iframe>', {id: 'sbox-share-iframe'}).appendTo($('body'));
|
||||||
ShareModal.modal = Share.create(config);
|
ShareModal.modal = Share.create(config);
|
||||||
} else if (!cfg.hidden) {
|
} else if (!cfg.hidden) {
|
||||||
ShareModal.$iframe.show();
|
ShareModal.modal.refresh(cfg, function () {
|
||||||
ShareModal.modal.refresh(cfg);
|
ShareModal.$iframe.show();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
if (cfg.hidden) {
|
if (cfg.hidden) {
|
||||||
ShareModal.$iframe.hide();
|
ShareModal.$iframe.hide();
|
||||||
|
|||||||
@ -2,6 +2,7 @@
|
|||||||
@import (reference) '../../customize/src/less2/include/modal.less';
|
@import (reference) '../../customize/src/less2/include/modal.less';
|
||||||
@import (reference) '../../customize/src/less2/include/alertify.less';
|
@import (reference) '../../customize/src/less2/include/alertify.less';
|
||||||
@import (reference) '../../customize/src/less2/include/tippy.less';
|
@import (reference) '../../customize/src/less2/include/tippy.less';
|
||||||
|
@import (reference) '../../customize/src/less2/include/avatar.less';
|
||||||
@import (reference) '../../customize/src/less2/include/checkmark.less';
|
@import (reference) '../../customize/src/less2/include/checkmark.less';
|
||||||
@import (reference) '../../customize/src/less2/include/password-input.less';
|
@import (reference) '../../customize/src/less2/include/password-input.less';
|
||||||
|
|
||||||
@ -11,4 +12,74 @@
|
|||||||
.checkmark_main(20px);
|
.checkmark_main(20px);
|
||||||
.password_main();
|
.password_main();
|
||||||
.modal_main();
|
.modal_main();
|
||||||
|
|
||||||
|
.cp-share-columns {
|
||||||
|
display: flex;
|
||||||
|
flex-flow: row;
|
||||||
|
|
||||||
|
.cp-share-column {
|
||||||
|
width: 50%;
|
||||||
|
padding: 0 10px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.cp-share-grid, .cp-share-list {
|
||||||
|
.avatar_main(50px);
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
.cp-share-list {
|
||||||
|
margin-bottom: 15px;
|
||||||
|
}
|
||||||
|
.cp-share-grid {
|
||||||
|
height: 228px;
|
||||||
|
max-height: 228px;
|
||||||
|
overflow-x: auto;
|
||||||
|
}
|
||||||
|
.cp-recent-only {
|
||||||
|
.cp-share-grid, .cp-share-grid-filter {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.cp-share-grid-filter {
|
||||||
|
display: flex;
|
||||||
|
input {
|
||||||
|
flex: 1;
|
||||||
|
margin-bottom: 0 !important;
|
||||||
|
&::placeholder { /* Chrome, Firefox, Opera, Safari 10.1+ */
|
||||||
|
color: @colortheme_alertify-primary-text;
|
||||||
|
opacity: 1; /* Firefox */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
margin-bottom: 15px;
|
||||||
|
}
|
||||||
|
.cp-share-friend {
|
||||||
|
width: 70px;
|
||||||
|
height: 70px;
|
||||||
|
display: flex;
|
||||||
|
flex-flow: column;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
padding: 5px;
|
||||||
|
margin-bottom: 6px;
|
||||||
|
cursor: default;
|
||||||
|
transition: order 0.5s, background-color 0.5s;
|
||||||
|
|
||||||
|
&.cp-selected {
|
||||||
|
background-color: @colortheme_alertify-primary;
|
||||||
|
color: @colortheme_alertify-primary-text;
|
||||||
|
order: -1 !important;
|
||||||
|
}
|
||||||
|
.cp-share-friend-name {
|
||||||
|
overflow: hidden;
|
||||||
|
white-space: nowrap;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
width: 100%;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
border: 1px solid @colortheme_alertify-primary;
|
||||||
|
&.cp-fake-friend {
|
||||||
|
visibility: hidden;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -53,7 +53,9 @@ define([
|
|||||||
password: priv.password
|
password: priv.password
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
UI.openCustomModal(UI.dialog.tabs(modal));
|
UI.openCustomModal(UI.dialog.tabs(modal), {
|
||||||
|
wide: true
|
||||||
|
});
|
||||||
};
|
};
|
||||||
sframeChan.on('EV_SHARE_REFRESH', function (data) {
|
sframeChan.on('EV_SHARE_REFRESH', function (data) {
|
||||||
createShareDialog(data);
|
createShareDialog(data);
|
||||||
|
|||||||
@ -7,6 +7,8 @@ define([
|
|||||||
], function (nThen, ApiConfig, $, RequireConfig) {
|
], function (nThen, ApiConfig, $, RequireConfig) {
|
||||||
var requireConfig = RequireConfig();
|
var requireConfig = RequireConfig();
|
||||||
|
|
||||||
|
var ready = false;
|
||||||
|
|
||||||
var create = function (config) {
|
var create = function (config) {
|
||||||
// Loaded in load #2
|
// Loaded in load #2
|
||||||
var sframeChan;
|
var sframeChan;
|
||||||
@ -89,7 +91,7 @@ define([
|
|||||||
feedbackAllowed: Utils.Feedback.state,
|
feedbackAllowed: Utils.Feedback.state,
|
||||||
hashes: config.data.hashes,
|
hashes: config.data.hashes,
|
||||||
password: config.data.password,
|
password: config.data.password,
|
||||||
file: config.data.file
|
file: config.data.file,
|
||||||
};
|
};
|
||||||
for (var k in additionalPriv) { metaObj.priv[k] = additionalPriv[k]; }
|
for (var k in additionalPriv) { metaObj.priv[k] = additionalPriv[k]; }
|
||||||
|
|
||||||
@ -116,11 +118,25 @@ define([
|
|||||||
sframeChan.on('EV_SHARE_ACTION', function (data) {
|
sframeChan.on('EV_SHARE_ACTION', function (data) {
|
||||||
config.onShareAction(data);
|
config.onShareAction(data);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
sframeChan.onReady(function () {
|
||||||
|
if (ready === true) { return; }
|
||||||
|
if (typeof ready === "function") {
|
||||||
|
ready();
|
||||||
|
}
|
||||||
|
ready = true;
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
var refresh = function (data) {
|
var refresh = function (data, cb) {
|
||||||
if (!sframeChan) { return; }
|
if (!ready) {
|
||||||
|
ready = function () {
|
||||||
|
refresh(data, cb);
|
||||||
|
};
|
||||||
|
return;
|
||||||
|
}
|
||||||
sframeChan.event('EV_SHARE_REFRESH', data);
|
sframeChan.event('EV_SHARE_REFRESH', data);
|
||||||
|
cb();
|
||||||
};
|
};
|
||||||
return {
|
return {
|
||||||
refresh: refresh
|
refresh: refresh
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user