Improve friend request process and UI

pull/1/head
yflory 6 years ago
parent 38f8535dd5
commit 9cb1a059f2

@ -898,6 +898,27 @@
} }
.cp-toolbar-notifications { .cp-toolbar-notifications {
margin-left: 10px; margin-left: 10px;
.cp-notifications-empty {
color: black;
padding: 5px;
}
button {
position: relative;
&.fa-bell-o {
cursor: default;
}
.cp-dropdown-button-title {
position: absolute;
bottom: 0;
right: 0;
font-size: 14px;
border: 1px solid;
border-radius: 50%;
width: 20px;
height: 20px;
line-height: 16px;
}
}
} }
.cp-toolbar-link { .cp-toolbar-link {
display: inline-flex; display: inline-flex;

@ -59,7 +59,6 @@ define([
curvePublic: data.curvePublic curvePublic: data.curvePublic
}, function (obj) { }, function (obj) {
cb(obj); cb(obj);
if (obj && obj.error) { return void cb(obj); }
}); });
}; };
Msg.addToFriendList = function (cfg, data, cb) { Msg.addToFriendList = function (cfg, data, cb) {

@ -68,7 +68,7 @@ define([
}); });
}; };
Msg.messenger = function (store) { Msg.messenger = function (store, updateMetadata) {
var messenger = { var messenger = {
handlers: { handlers: {
event: [] event: []
@ -97,6 +97,7 @@ define([
stack.push(f); stack.push(f);
}; };
var allowFriendsChannels = false;
var channels = messenger.channels = {}; var channels = messenger.channels = {};
var joining = {}; var joining = {};
@ -301,7 +302,10 @@ define([
if (!proxy.friends) { return; } if (!proxy.friends) { return; }
var friends = proxy.friends; var friends = proxy.friends;
delete friends[curvePublic]; delete friends[curvePublic];
Realtime.whenRealtimeSyncs(realtime, cb); Realtime.whenRealtimeSyncs(realtime, function () {
updateMetadata();
cb();
});
}; };
var pushMsg = function (channel, cryptMsg) { var pushMsg = function (channel, cryptMsg) {
@ -771,45 +775,9 @@ define([
openChannel(data); openChannel(data);
}; };
// Detect friends changes made in another worker
proxy.on('change', ['friends'], function (o, n, p) {
var curvePublic;
if (o === undefined) {
// new friend added
curvePublic = p.slice(-1)[0];
// Load channel
var friend = friends[curvePublic];
if (typeof(friend) !== 'object') { return; }
var channel = friend.channel;
if (!channel) { return; }
loadFriend(friend, function () {
emit('FRIEND', {
curvePublic: curvePublic,
});
});
return;
}
if (typeof(n) === 'undefined') {
// Handled by .on('remove')
return;
}
}).on('remove', ['friends'], function (o, p) {
var curvePublic = p[1];
if (!curvePublic) { return; }
if (p[2] !== 'channel') { return; }
var channel = channels[o];
channel.wc.leave(Types.unfriend);
delete channels[channel.id];
emit('UNFRIEND', {
curvePublic: curvePublic,
fromMe: true
});
});
// Friend added in our contacts in the current worker // Friend added in our contacts in the current worker
messenger.onFriendAdded = function (friendData) { messenger.onFriendAdded = function (friendData) {
if (!allowFriendsChannels) { return; }
var friend = friends[friendData.curvePublic]; var friend = friends[friendData.curvePublic];
if (typeof(friend) !== 'object') { return; } if (typeof(friend) !== 'object') { return; }
var channel = friend.channel; var channel = friend.channel;
@ -820,10 +788,23 @@ define([
}); });
}); });
}; };
messenger.onFriendRemoved = function (curvePublic, chanId) {
var channel = channels[chanId];
if (!channel) { return; }
if (channel.wc) {
channel.wc.leave(Types.unfriend);
}
delete channels[channel.id];
emit('UNFRIEND', {
curvePublic: curvePublic,
fromMe: true
});
};
var ready = false; var ready = false;
var initialized = false; var initialized = false;
var init = function () { var init = function () {
allowFriendsChannels = true;
if (initialized) { return; } if (initialized) { return; }
initialized = true; initialized = true;
var friends = getFriendList(proxy); var friends = getFriendList(proxy);

@ -2610,7 +2610,8 @@ define([
UIElements.displayFriendRequestModal = function (common, data) { UIElements.displayFriendRequestModal = function (common, data) {
var msg = data.content.msg; var msg = data.content.msg;
var text = Messages._getKey('contacts_request', [msg.content.displayName]); var text = Messages._getKey('contacts_request', [msg.content.displayName]);
UI.confirm(text, function (yes) {
var todo = function (yes) {
common.getSframeChannel().query("Q_ANSWER_FRIEND_REQUEST", { common.getSframeChannel().query("Q_ANSWER_FRIEND_REQUEST", {
data: data, data: data,
value: yes value: yes
@ -2621,10 +2622,32 @@ define([
} }
UI.log(Messages.contacts_added); UI.log(Messages.contacts_added);
}); });
};
var content = h('div.cp-share-modal', [
setHTML(h('p'), text)
]);
var buttons = [{
name: Messages.cancel, // XXX "later"?
onClick: function () {},
keys: [27]
}, {
className: 'primary',
name: "Accept (Enter)", // XXX
onClick: function () {
todo(true);
},
keys: [13]
}, { }, {
ok: 'Accept', // XXX className: 'primary',
cancel: 'Ignore the request' // XXX name: "Ignore the request", // XXX
}, true); onClick: function () {
todo(false);
},
keys: [[13, 'ctrl']]
}];
var modal = UI.dialog.customModal(content, {buttons: buttons});
UI.openCustomModal(modal);
}; };
return UIElements; return UIElements;

@ -0,0 +1,50 @@
define([
'jquery',
'/common/hyperscript.js',
'/common/common-ui-elements.js'
], function ($, h, UIElements) {
var handlers = {};
handlers['FRIEND_REQUEST'] = function (common, data, el) {
var content = data.content;
var msg = content.msg;
// Check authenticity
if (msg.author !== msg.content.curvePublic) { return; }
common.addFriendRequest(data);
// Display the notification
$(el).find('.cp-notification-dismiss').attr('title', 'IGNORE').css('display', 'flex'); // XXX
$(el).find('.cp-notification-content').addClass("cp-clickable");
$(el).find('.cp-notification-content p')
.html('New friend request: <b>'+msg.content.displayName+'</b>') // XXX
.click(function () {
UIElements.displayFriendRequestModal(common, data);
});
};
handlers['ACCEPT_FRIEND_REQUEST'] = function (common, data, el) {
var content = data.content;
var msg = content.msg;
$(el).find('.cp-notification-content p')
.html('Friend request accepted: <b>'+msg.content.displayName+'</b>');
$(el).find('.cp-notification-dismiss').css('display', 'flex');
};
return {
add: function (common, data, el) {
var type = data.content.msg.type;
if (handlers[type]) {
handlers[type](common, data, el);
} else {
$(el).find('.cp-notification-dismiss').css('display', 'flex');
}
},
remove: function (common, data) {
common.removeFriendRequest(data.hash);
},
};
});

@ -639,7 +639,7 @@ define([
/*store.mailbox.post('notifications', 'NAME_CHANGED', { /*store.mailbox.post('notifications', 'NAME_CHANGED', {
old: store.proxy[Constants.displayNameKey], old: store.proxy[Constants.displayNameKey],
new: value new: value
});*/ });
Object.keys(store.proxy.friends).forEach(function (curve) { Object.keys(store.proxy.friends).forEach(function (curve) {
var f = store.proxy.friends[curve]; var f = store.proxy.friends[curve];
if (!f.notifications) { return; } if (!f.notifications) { return; }
@ -653,7 +653,7 @@ define([
if (obj && obj.error) { return void console.error(obj.error); } if (obj && obj.error) { return void console.error(obj.error); }
console.log('notif sent to '+f); console.log('notif sent to '+f);
}); });
}); });*/
} }
store.proxy[Constants.displayNameKey] = value; store.proxy[Constants.displayNameKey] = value;
broadcast([clientId], "UPDATE_METADATA"); broadcast([clientId], "UPDATE_METADATA");
@ -911,7 +911,6 @@ define([
// Messaging (manage friends from the userlist) // Messaging (manage friends from the userlist)
Store.answerFriendRequest = function (clientId, obj, cb) { Store.answerFriendRequest = function (clientId, obj, cb) {
console.log(obj);
var value = obj.value; var value = obj.value;
var data = obj.data; var data = obj.data;
if (data.type !== 'notifications') { return void cb ({error: 'EINVAL'}); } if (data.type !== 'notifications') { return void cb ({error: 'EINVAL'}); }
@ -926,6 +925,7 @@ define([
}, cb); }, cb);
}; };
// If we accept the request, add the friend to the list
if (value) { if (value) {
Messaging.acceptFriendRequest(store, msg.content, function (obj) { Messaging.acceptFriendRequest(store, msg.content, function (obj) {
if (obj && obj.error) { return void cb(obj); } if (obj && obj.error) { return void cb(obj); }
@ -934,6 +934,9 @@ define([
realtime: store.realtime, realtime: store.realtime,
pinPads: function (data, cb) { Store.pinPads(null, data, cb); }, pinPads: function (data, cb) { Store.pinPads(null, data, cb); },
}, msg.content, function (err) { }, msg.content, function (err) {
if (store.messenger) {
store.messenger.onFriendAdded(msg.content);
}
broadcast([], "UPDATE_METADATA"); broadcast([], "UPDATE_METADATA");
if (err) { return void cb({error: err}); } if (err) { return void cb({error: err}); }
dismiss(cb); dismiss(cb);
@ -941,6 +944,7 @@ define([
}); });
return; return;
} }
// Otherwise, just remove the notification
dismiss(); dismiss();
}; };
Store.sendFriendRequest = function (clientId, data, cb) { Store.sendFriendRequest = function (clientId, data, cb) {
@ -1445,7 +1449,9 @@ define([
}; };
var loadMessenger = function () { var loadMessenger = function () {
if (AppConfig.availablePadTypes.indexOf('contacts') === -1) { return; } if (AppConfig.availablePadTypes.indexOf('contacts') === -1) { return; }
var messenger = store.messenger = Messenger.messenger(store); var messenger = store.messenger = Messenger.messenger(store, function () {
broadcast([], "UPDATE_METADATA");
});
messenger.on('event', function (ev, data) { messenger.on('event', function (ev, data) {
sendMessengerEvent('CHAT_EVENT', { sendMessengerEvent('CHAT_EVENT', {
ev: ev, ev: ev,
@ -1496,6 +1502,18 @@ define([
}); });
}; };
var cleanFriendRequests = function () {
try {
if (!store.proxy.friends_pending) { return; }
var twoDaysAgo = +new Date() - (2 * 24 * 3600 * 1000); // XXX
Object.keys(store.proxy.friends_pending).forEach(function (curve) {
if (store.proxy.friends_pending[curve] < twoDaysAgo) {
delete store.proxy.friends_pending[curve];
}
});
} catch (e) {}
};
////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////
/////////////////////// Init ///////////////////////////////////// /////////////////////// Init /////////////////////////////////////
////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////
@ -1591,6 +1609,7 @@ define([
loadCursor(); loadCursor();
loadOnlyOffice(); loadOnlyOffice();
loadMailbox(waitFor); loadMailbox(waitFor);
cleanFriendRequests();
}).nThen(function () { }).nThen(function () {
var requestLogin = function () { var requestLogin = function () {
broadcast([], "REQUEST_LOGIN"); broadcast([], "REQUEST_LOGIN");
@ -1644,14 +1663,32 @@ define([
// Trigger userlist update when the avatar has changed // Trigger userlist update when the avatar has changed
broadcast([], "UPDATE_METADATA"); broadcast([], "UPDATE_METADATA");
}); });
proxy.on('change', ['friends'], function () { proxy.on('change', ['friends'], function (o, n, p) {
// Trigger userlist update when the friendlist has changed // Trigger userlist update when the friendlist has changed
broadcast([], "UPDATE_METADATA"); broadcast([], "UPDATE_METADATA");
if (!store.messenger) { return; }
if (o !== undefined) { return; }
var curvePublic = p.slice(-1)[0];
var friend = proxy.friends && proxy.friends[curvePublic];
store.messenger.onFriendAdded(friend);
});
proxy.on('remove', ['friends'], function (o, p) {
broadcast([], "UPDATE_METADATA");
if (!store.messenger) { return; }
var curvePublic = p[1];
if (!curvePublic) { return; }
if (p[2] !== 'channel') { return; }
store.messenger.onFriendRemoved(curvePublic, o);
}); });
proxy.on('change', ['friends_pending'], function () { proxy.on('change', ['friends_pending'], function () {
// Trigger userlist update when the friendlist has changed // Trigger userlist update when the friendlist has changed
broadcast([], "UPDATE_METADATA"); broadcast([], "UPDATE_METADATA");
}); });
proxy.on('remove', ['friends_pending'], function () {
broadcast([], "UPDATE_METADATA");
});
proxy.on('change', ['settings'], function () { proxy.on('change', ['settings'], function () {
broadcast([], "UPDATE_METADATA"); broadcast([], "UPDATE_METADATA");
}); });

@ -0,0 +1,52 @@
define([
'/common/common-messaging.js',
], function (Messaging) {
var handlers = {};
handlers['FRIEND_REQUEST'] = function (ctx, data, cb) {
if (data.msg.author === data.msg.content.curvePublic &&
Messaging.getFriend(ctx.store.proxy, data.msg.author)) {
Messaging.acceptFriendRequest(ctx.store, data.msg.content, function (obj) {
if (obj && obj.error) { return void cb(); }
cb(true);
});
return;
}
cb();
};
handlers['ACCEPT_FRIEND_REQUEST'] = function (ctx, box, data, cb) {
// Our friend request was accepted.
// Make sure we really sent it
if (!ctx.store.proxy.friends_pending[data.msg.author]) { return void cb(); }
// And add the friend
Messaging.addToFriendList({
proxy: ctx.store.proxy,
realtime: ctx.store.realtime,
pinPads: ctx.pinPads
}, data.msg.content, function (err) {
if (err) { console.error(err); }
delete ctx.store.proxy.friends_pending[data.msg.author];
if (ctx.store.messenger) {
ctx.store.messenger.onFriendAdded(data.msg.content);
}
ctx.updateMetadata();
});
cb();
};
return function (ctx, box, data, cb) {
var type = data.msg.type;
if (handlers[type]) {
try {
handlers[type](ctx, box, data, cb);
} catch (e) {
cb();
}
} else {
cb();
}
};
});

@ -347,11 +347,11 @@ proxy.mailboxes = {
if (BLOCKING_TYPES.indexOf(key) === -1) { if (BLOCKING_TYPES.indexOf(key) === -1) {
openChannel(ctx, key, m, function () { openChannel(ctx, key, m, function () {
updateLastKnownHash(ctx, key); updateLastKnownHash(ctx, key);
console.log(key + ' mailbox is ready'); //console.log(key + ' mailbox is ready');
}); });
} else { } else {
openChannel(ctx, key, m, waitFor(function () { openChannel(ctx, key, m, waitFor(function () {
console.log(key + ' mailbox is ready'); //console.log(key + ' mailbox is ready');
})); }));
} }
}); });

@ -3,9 +3,10 @@ define([
'/common/common-util.js', '/common/common-util.js',
'/common/common-interface.js', '/common/common-interface.js',
'/common/common-ui-elements.js', '/common/common-ui-elements.js',
'/common/notifications.js',
'/common/hyperscript.js', '/common/hyperscript.js',
'/customize/messages.js' '/customize/messages.js'
], function ($, Util, UI, UIElements, h, Messages) { ], function ($, Util, UI, UIElements, Notifications, h, Messages) {
var Mailbox = {}; var Mailbox = {};
Messages = Messages; // XXX Messages = Messages; // XXX
@ -87,6 +88,7 @@ define([
var todo = function (f) { var todo = function (f) {
try { try {
var el = createElement(data); var el = createElement(data);
Notifications.add(Common, data, el);
f(data, el); f(data, el);
} catch (e) { } catch (e) {
console.error(e); console.error(e);
@ -103,6 +105,7 @@ define([
onViewedHandlers.forEach(function (f) { onViewedHandlers.forEach(function (f) {
try { try {
f(data); f(data);
Notifications.remove(Common, data);
} catch (e) { } catch (e) {
console.error(e); console.error(e);
} }
@ -165,7 +168,7 @@ define([
}); });
execCommand('SUBSCRIBE', null, function () { execCommand('SUBSCRIBE', null, function () {
console.log('subscribed'); //console.log('subscribed');
}); });
return mailbox; return mailbox;

@ -392,10 +392,17 @@ define([
var friendRequests = {}; var friendRequests = {};
funcs.addFriendRequest = function (data) { funcs.addFriendRequest = function (data) {
var curve = Util.find(data, ['content', 'msg', 'author']); var curve = Util.find(data, ['content', 'msg', 'author']);
console.log(data);
console.log(curve);
friendRequests[curve] = data; friendRequests[curve] = data;
}; };
funcs.removeFriendRequest = function (hash) {
Object.keys(friendRequests).some(function (curve) {
var h = Util.find(friendRequests[curve], ['content', 'hash']);
if (h === hash) {
delete friendRequests[curve];
return true;
}
});
};
funcs.getFriendRequests = function () { funcs.getFriendRequests = function () {
return JSON.parse(JSON.stringify(friendRequests)); return JSON.parse(JSON.stringify(friendRequests));
}; };

@ -8,11 +8,10 @@ define([
'/common/common-util.js', '/common/common-util.js',
'/common/common-feedback.js', '/common/common-feedback.js',
'/common/hyperscript.js', '/common/hyperscript.js',
'/common/notifications.js',
'/common/messenger-ui.js', '/common/messenger-ui.js',
'/customize/messages.js', '/customize/messages.js',
], function ($, Config, ApiConfig, UIElements, UI, Hash, Util, Feedback, h, ], function ($, Config, ApiConfig, UIElements, UI, Hash, Util, Feedback, h,
Notifications, MessengerUI, Messages) { MessengerUI, Messages) {
var Common; var Common;
var Bar = { var Bar = {
@ -235,9 +234,8 @@ Notifications, MessengerUI, Messages) {
// Editors // Editors
var pendingFriends = Common.getPendingFriends(); // Friend requests sent var pendingFriends = Common.getPendingFriends(); // Friend requests sent
var friendRequests = Common.getFriendRequests(); // Friend requests received var friendRequests = Common.getFriendRequests(); // Friend requests received
console.log(friendRequests);
var friendTo = +new Date() - (2 * 24 * 3600 * 1000); var friendTo = +new Date() - (2 * 24 * 3600 * 1000);
friendTo = +new Date(); // XXX //friendTo = +new Date(); // XXX
editUsersNames.forEach(function (data) { editUsersNames.forEach(function (data) {
var name = data.name || Messages.anonymous; var name = data.name || Messages.anonymous;
var $span = $('<span>', {'class': 'cp-avatar'}); var $span = $('<span>', {'class': 'cp-avatar'});
@ -305,7 +303,6 @@ Notifications, MessengerUI, Messages) {
} }
} else if (Common.isLoggedIn() && data.curvePublic && !friends[data.curvePublic] } else if (Common.isLoggedIn() && data.curvePublic && !friends[data.curvePublic]
&& !priv.readOnly) { && !priv.readOnly) {
console.log(pendingFriends);
if (pendingFriends[data.curvePublic] && pendingFriends[data.curvePublic] > friendTo) { if (pendingFriends[data.curvePublic] && pendingFriends[data.curvePublic] > friendTo) {
$('<span>', {'class': 'cp-toolbar-userlist-friend'}).text(Messages.userlist_pending) $('<span>', {'class': 'cp-toolbar-userlist-friend'}).text(Messages.userlist_pending)
.appendTo($rightCol); .appendTo($rightCol);
@ -950,10 +947,11 @@ Notifications, MessengerUI, Messages) {
return $userAdmin; return $userAdmin;
}; };
var createNotifications = function (toolbar) { var createNotifications = function (toolbar, config) {
console.log(Common.mailbox);
var $notif = toolbar.$top.find('.'+NOTIFICATIONS_CLS).show(); var $notif = toolbar.$top.find('.'+NOTIFICATIONS_CLS).show();
var div = h('div.cp-notifications-container'); var div = h('div.cp-notifications-container', [
h('div.cp-notifications-empty', "Nothing new here") // XXX
]);
var pads_options = [div]; var pads_options = [div];
var dropdownConfig = { var dropdownConfig = {
text: '', // Button initial text text: '', // Button initial text
@ -963,15 +961,35 @@ Notifications, MessengerUI, Messages) {
common: Common common: Common
}; };
var $newPadBlock = UIElements.createDropdown(dropdownConfig); var $newPadBlock = UIElements.createDropdown(dropdownConfig);
$newPadBlock.find('button').attr('title', Messages.mailbox_title); // XXX var $button = $newPadBlock.find('button');
$newPadBlock.find('button').addClass('fa fa-bell-o'); $button.attr('title', Messages.mailbox_title); // XXX
$button.addClass('fa fa-bell-o');
var $n = $button.find('.cp-dropdown-button-title').hide();
var $empty = $(div).find('.cp-notifications-empty');
var refresh = function () {
updateUserList(toolbar, config);
var n = $(div).find('.cp-notification').length;
$button.removeClass('fa-bell-o').removeClass('fa-bell');
if (n === 0) {
$empty.show();
$n.hide();
return void $button.addClass('fa-bell-o');
}
$empty.hide();
$n.text(n).show();
$button.addClass('fa-bell');
};
Common.mailbox.subscribe({ Common.mailbox.subscribe({
onMessage: function (data, el) { onMessage: function (data, el) {
if (el) { if (el) {
Notifications(Common, data, el);
div.appendChild(el); div.appendChild(el);
} }
refresh();
},
onViewed: function (data) {
refresh();
} }
}); });

Loading…
Cancel
Save