diff --git a/customize.dist/src/less2/include/alertify.less b/customize.dist/src/less2/include/alertify.less
index 3274f1c63..c73c27c78 100644
--- a/customize.dist/src/less2/include/alertify.less
+++ b/customize.dist/src/less2/include/alertify.less
@@ -427,7 +427,7 @@
display: flex;
flex-flow: row;
- .cp-share-column {
+ & > .cp-share-column {
width: 50%;
padding: 0 10px;
}
diff --git a/rpc.js b/rpc.js
index 7f0e7732b..058215200 100644
--- a/rpc.js
+++ b/rpc.js
@@ -367,7 +367,8 @@ var setMetadata = function (Env, data, unsafeKey, cb) {
metadata.owners.indexOf(unsafeKey) === -1) {
// If you are a pending owner, make sure you can only add yourelf as an owner
- if (command !== 'ADD_OWNERS' || !Array.isArray(data.value)
+ if ((command !== 'ADD_OWNERS' && command !== 'RM_PENDING_OWNERS')
+ || !Array.isArray(data.value)
|| data.value.length !== 1
|| data.value[0] !== unsafeKey) {
g();
diff --git a/www/common/common-ui-elements.js b/www/common/common-ui-elements.js
index d3afa3012..b37d71355 100644
--- a/www/common/common-ui-elements.js
+++ b/www/common/common-ui-elements.js
@@ -107,11 +107,12 @@ define([
common.getPadAttribute('tags', waitFor(function (err, val) {
data.tags = val;
}));
- common.getSframeChannel().query('Q_GET_PAD_METADATA', null, waitFor(function (err, val) {
- if (err) { return; }
- data.owners = val.owners;
- data.expire = val.expire;
- data.pending_owners = val.pending_owners;
+ common.getPadMetadata(null, waitFor(function (obj) {
+ console.log(obj);
+ if (obj && obj.error) { return; }
+ data.owners = obj.owners;
+ data.expire = obj.expire;
+ data.pending_owners = obj.pending_owners;
}));
/*
common.getPadAttribute('owners', waitFor(function (err, val) {
@@ -132,14 +133,20 @@ define([
var edPublic = priv.edPublic;
var channel = data.channel;
var owners = data.owners;
+ var pending_owners = data.pending_owners;
- var $div1, $div2;
var redrawAll = function () {};
+ var div1 = h('div.cp-share-friends.cp-share-column');
+ var div2 = h('div.cp-share-friends.cp-share-column');
+ var $div1 = $(div1);
+ var $div2 = $(div2);
+
// Remove owner column
- var drawRemove = function () {
+ var drawRemove = function (pending) {
var _owners = {};
- owners.forEach(function (ed) {
+ var o = pending ? pending_owners : owners;
+ o.forEach(function (ed) {
var f;
Object.keys(friends).some(function (c) {
if (friends[c].edPublic === ed) {
@@ -153,17 +160,19 @@ define([
edPublic: ed,
};
});
- var removeCol = UIElements.getFriendsList('Remove an existing owner instantly', {
+ var msg = pending ? 'Remove a pending owner:'
+ : 'Remove an existing owner:'; // XXX
+ var removeCol = UIElements.getFriendsList(msg, {
common: common,
friends: _owners,
noFilter: true
}, function () {
console.log(arguments);
});
- $div1 = $(removeCol.div);
+ var $div = $(removeCol.div);
var others1 = removeCol.others;
- $div1.append(h('div.cp-share-grid', others1));
- $div1.find('.cp-share-friend').click(function () {
+ $div.append(h('div.cp-share-grid', others1));
+ $div.find('.cp-share-friend').click(function () {
var sel = $(this).hasClass('cp-selected');
if (!sel) {
$(this).addClass('cp-selected');
@@ -175,10 +184,11 @@ define([
});
// When clicking on the remove button, we check the selected users.
// If you try to remove yourself, we'll display an additional warning message
- var removeButton = h('button.no-margin', 'Remove owners'); // XXX
+ var btnMsg = pending ? 'Remove pending owners' : 'Remove owners'; // XXX
+ var removeButton = h('button.no-margin', btnMsg);
$(removeButton).click(function () {
// Check selection
- var $sel = $div1.find('.cp-share-friend.cp-selected');
+ var $sel = $div.find('.cp-share-friend.cp-selected');
var sel = $sel.toArray();
var me = false;
var toRemove = sel.map(function (el) {
@@ -191,12 +201,11 @@ define([
var send = function () {
sframeChan.query('Q_SET_PAD_METADATA', {
channel: channel,
- command: 'RM_OWNERS',
+ command: pending ? 'RM_PENDING_OWNERS' : 'RM_OWNERS',
value: toRemove
}, function (err, res) {
err = err || (res && res.error);
if (err) { return void UI.warn('ERROR' + err); } // XXX
- owners = res.owners;
redrawAll();
UI.log('DONE'); // XXX
});
@@ -209,8 +218,8 @@ define([
send();
});
});
- $div1.append(h('p', removeButton));
- return $div1;
+ $div.append(h('p', removeButton));
+ return $div;
};
// Add owners column
@@ -261,20 +270,22 @@ define([
}
}));
}).nThen(function (waitFor) {
+ console.log('koko');
// Send the command
sframeChan.query('Q_SET_PAD_METADATA', {
channel: channel,
command: 'ADD_PENDING_OWNERS',
value: toAdd
}, waitFor(function (err, res) {
+ console.error(arguments);
err = err || (res && res.error);
if (err) {
waitFor.abort();
return void UI.warn('ERROR' + err);
} // XXX
- owners = res.owners;
}));
}).nThen(function (waitFor) {
+ console.log('okok');
// TODO send notifications
sel.forEach(function (el) {
var friend = friends[$(el).attr('data-curve')];
@@ -307,18 +318,26 @@ define([
};
redrawAll = function () {
- var $d1 = $div1;
- var $d2 = $div2;
- drawRemove().insertBefore($d1);
- $d1.remove();
- drawAdd().insertBefore($d2);
- $d2.remove();
+ $div1.empty();
+ $div2.empty();
+ common.getPadMetadata(null, function (obj) {
+ if (obj && obj.error) { return; }
+ owners = obj.owners;
+ pending_owners = obj.pending_owners;
+ $div1.append(drawRemove(false)).append(drawRemove(true));
+ $div2.append(drawAdd());
+ });
};
+ $div1.append(drawRemove(false)).append(drawRemove(true));
+ $div2.append(drawAdd());
+
// Create modal
var link = h('div.cp-share-columns', [
- drawRemove()[0],
- drawAdd()[0]
+ div1,
+ div2
+ /*drawRemove()[0],
+ drawAdd()[0]*/
]);
var linkButtons = [{
className: 'cancel',
@@ -3260,8 +3279,10 @@ define([
UIElements.displayAddOwnerModal = function (common, data) {
var priv = common.getMetadataMgr().getPrivateData();
+ var user = common.getMetadataMgr().getUserData();
var sframeChan = common.getSframeChannel();
var msg = data.content.msg;
+
var name = Util.fixHTML(msg.content.user.displayName) || Messages.anonymous;
var title = Util.fixHTML(msg.content.title);
@@ -3274,8 +3295,8 @@ define([
$(link).click(function (e) {
e.preventDefault();
e.stopPropagation();
- if (data.content.password) {
- common.sessionStorage.put('newPadPassword', data.content.password, function () {
+ if (msg.content.password) {
+ common.sessionStorage.put('newPadPassword', msg.content.password, function () {
common.openURL(msg.content.href);
});
return;
@@ -3288,23 +3309,76 @@ define([
link
]);
+ var answer = function (yes) {
+ common.mailbox.sendTo("ADD_OWNER_ANSWER", {
+ channel: msg.content.channel,
+ href: msg.content.href,
+ password: msg.content.password,
+ title: msg.content.title,
+ answer: yes,
+ user: {
+ displayName: user.name,
+ avatar: user.avatar,
+ profile: user.profile,
+ notifications: user.notifications,
+ curvePublic: user.curvePublic,
+ edPublic: priv.edPublic
+ }
+ }, {
+ channel: msg.content.user.notifications,
+ curvePublic: msg.content.user.curvePublic
+ });
+ common.mailbox.dismiss(data, function (err) {
+ console.log(err);
+ });
+ };
+
var todo = function (yes) {
if (yes) {
+ // ACCEPT
sframeChan.query('Q_SET_PAD_METADATA', {
- channel: data.content.channel,
+ channel: msg.content.channel,
command: 'ADD_OWNERS',
value: [priv.edPublic]
}, function (err, res) {
err = err || (res && res.error);
if (err) {
- return void UI.warn('ERROR' + err);
+ return void UI.warn('ERROR ' + err);
} // XXX
UI.log('DONE'); // XXX
- // TODO send notification to the sender?
+
+ // Send notification to the sender
+ answer(true);
+
+ // Remove yourself from the pending owners
+ sframeChan.query('Q_SET_PAD_METADATA', {
+ channel: msg.content.channel,
+ command: 'RM_PENDING_OWNERS',
+ value: [priv.edPublic]
+ }, function (err, res) {
+ err = err || (res && res.error);
+ if (err) {
+ console.error(err);
+ }
+ });
});
return;
}
- // XXX implement decline?
+
+ // DECLINE
+ // Remove yourself from the pending owners
+ sframeChan.query('Q_SET_PAD_METADATA', {
+ channel: msg.content.channel,
+ command: 'RM_PENDING_OWNERS',
+ value: [priv.edPublic]
+ }, function (err, res) {
+ err = err || (res && res.error);
+ if (err) {
+ console.error(err);
+ }
+ // Send notification to the sender
+ answer(false);
+ });
};
var buttons = [{
diff --git a/www/common/notifications.js b/www/common/notifications.js
index 010d1f46e..b06e8e3fc 100644
--- a/www/common/notifications.js
+++ b/www/common/notifications.js
@@ -216,12 +216,15 @@ define([
var msg = content.msg;
// Display the notification
+ var name = Util.fixHTML(msg.content.user.displayName) || Messages.anonymous;
+ var title = Util.fixHTML(msg.content.title);
+ Messages.owner_request = '{0} wants you to be an owner of {1}'; // XXX
content.getFormatText = function () {
- return Messages._getKey('friendRequest_notification', [name]);
+ return Messages._getKey('owner_request', [name, title]);
};
// Check authenticity
- if (msg.author !== msg.content.curvePublic) { return; }
+ if (msg.author !== msg.content.user.curvePublic) { return; }
// if not archived, add handlers
if (!content.archived) {
@@ -231,6 +234,24 @@ define([
}
};
+ handlers['ADD_OWNER_ANSWER'] = function (common, data) {
+ var content = data.content;
+ var msg = content.msg;
+
+ // Display the notification
+ var name = Util.fixHTML(msg.content.user.displayName) || Messages.anonymous;
+ var title = Util.fixHTML(msg.content.title);
+ Messages.owner_request_accepted = '{0} has accepted your offer to be an owner of {1}'; // XXX
+ Messages.owner_request_declined = '{0} has declined your offer to be an owner of {1}'; // XXX
+ var key = 'owner_request_' + (msg.content.answer ? 'accepted' : 'declined');
+ content.getFormatText = function () {
+ return Messages._getKey(key, [name, title]);
+ };
+ if (!content.archived) {
+ content.dismissHandler = defaultDismiss(common, data);
+ }
+ };
+
// NOTE: don't forget to fixHTML everything returned by "getFormatText"
return {
diff --git a/www/common/outer/async-store.js b/www/common/outer/async-store.js
index 9c5c23bf8..a293de8e4 100644
--- a/www/common/outer/async-store.js
+++ b/www/common/outer/async-store.js
@@ -1397,6 +1397,7 @@ define([
cb(channel.data || {});
};
Store.setPadMetadata = function (clientId, data, cb) {
+ console.log(data);
if (!data.channel) { return void cb({ error: 'ENOTFOUND'}); }
if (!data.command) { return void cb({ error: 'EINVAL' }); }
store.rpc.setMetadata(data, function (err, res) {
diff --git a/www/common/outer/mailbox-handlers.js b/www/common/outer/mailbox-handlers.js
index cca192d04..ed1d954b1 100644
--- a/www/common/outer/mailbox-handlers.js
+++ b/www/common/outer/mailbox-handlers.js
@@ -264,6 +264,7 @@ define([
handlers['ADD_OWNER'] = function (ctx, box, data, cb) {
var msg = data.msg;
var content = msg.content;
+console.log(msg);
if (msg.author !== content.user.curvePublic) { return void cb(true); }
if (!content.href || !content.title || !content.channel) {
diff --git a/www/common/sframe-common.js b/www/common/sframe-common.js
index 58e1ffcb0..6b4fc96aa 100644
--- a/www/common/sframe-common.js
+++ b/www/common/sframe-common.js
@@ -467,6 +467,13 @@ define([
}, { timeout: 60000 });
};
+ funcs.getPadMetadata = function (data, cb) {
+ ctx.sframeChan.query('Q_GET_PAD_METADATA', data, function (err, val) {
+ if (err || (val && val.error)) { return void cb({error: err || val.error}); }
+ cb(val);
+ });
+ };
+
funcs.gotoURL = function (url) { ctx.sframeChan.event('EV_GOTO_URL', url); };
funcs.openURL = function (url) { ctx.sframeChan.event('EV_OPEN_URL', url); };
funcs.openUnsafeURL = function (url) {