openmedialibrary/static/js/peersPanel.js

629 lines
21 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

'use strict';
oml.ui.peersPanel = function() {
var ui = oml.user.ui,
preferences = oml.user.preferences,
buttons = [
{id: 'send', title: Ox._('Send')},
{id: 'cancel', title: Ox._('Cancel')},
{id: 'accept', title: Ox._('Accept')},
{id: 'reject', title: Ox._('Reject')},
{id: 'remove', title: Ox._('Remove...')}
],
folders = [
{
id: 'peers',
title: Ox._('Your Peers'),
itemTitle: Ox._('No peers'),
text: Ox._('You don\'t have any peers yet.')
},
{
id: 'received',
title: Ox._('Received Requests'),
itemTitle: Ox._('No pending requests'),
text: Ox._('You haven\'t received any peering requests.')
},
{
id: 'sent',
title: Ox._('Sent Requests'),
itemTitle: Ox._('No pending requests'),
text: Ox._('You haven\'t sent any peering requests.')
},
{
id: 'others',
title: Ox._('Other Users'),
itemTitle: Ox._('No other users'),
text: Ox._('There are no other users in your extended network.')
}
],
peerIds = [],
users,
// FIXME: UGLY
$users = Ox.Element().css({
background: {
oxlight: 'rgb(240, 240, 240)',
oxmedium: 'rgb(144, 144, 145)',
oxdark: 'rgb(16, 16, 16)'
}[Ox.Theme()],
overflowX: 'hidden'
}),
$lists = [
renderSectionList({id: 'invitations'}).appendTo($users)
],
$folders = folders.map(function(folder) {
return Ox.CollapsePanel({
collapsed: false,
title: folder.title
})
.css({width: '256px'})
.appendTo($users);
}),
$user = Ox.Element(),
that = Ox.SplitPanel({
elements: [
{element: $users, size: 256},
{element: $user}
],
orientation: 'horizontal'
})
.bindEvent({
oml_page: function(data) {
if (data.value == 'peers') {
oml.bindEvent({peering: peering});
} else if (data.previousValue == 'peers') {
oml.unbindEvent({peering: peering});
}
}
});
var peering = Ox.throttle(function() {
updateUsers();
}, 1000);
if (oml.user.ui.page == 'peers') {
oml.bindEvent({peering: peering});
}
function renderSectionList(folder) {
var $list = Ox.TableList({
columns: [
{
format: function() {
return $('<img>')
.attr({
src: Ox.UI.getImageURL('symbolUser')
})
.css({
width: '10px',
height: '10px',
margin: '2px -2px 2px 0',
opacity: folder.id == 'invitations' ? 1 : 0.5
})
},
id: 'id',
visible: true,
width: 16
},
{
format: function(value) {
return folder.id == 'invitations'
? value
: '<span class="OxLight">' + value + '</span>'
},
id: 'title',
visible: true,
width: 240 - Ox.SCROLLBAR_SIZE
}
],
items: [
{
id: folder.id,
title: folder.id == 'invitations' ? Ox._('Invitations')
: Ox.getObjectById(folders, folder.id).itemTitle
},
],
sort: [{key: 'id', operator: '+'}],
unique: 'id'
})
.css({height: '16px'})
.bindEvent({
select: function(data) {
if (data.ids.length) {
selectItem($list);
renderUser({section: data.ids[0]});
} else {
renderUser();
}
}
});
$list.$body.css({
height: '16px',
overflowX: 'hidden'
}); // FIXME!
return $list;
}
function renderUser(user) {
var $user = Ox.Element(),
$form = Ox.Element()
.addClass('OxSelectable OxTextPage')
.css({margin: '16px'})
.appendTo($user),
$warning = Ox.Element()
.css({margin: '32px 16px'}) // FIXME: WTF!
.appendTo($user),
$id, $buttons = [], $message, $nickname,
folder;
if (user && user.section) {
folder = Ox.getObjectById(folders, user.section);
}
if (folder) {
$('<div>')
.html(folder.text)
.appendTo($form);
} else if (user) {
if (user.section == 'invitations') {
$('<div>')
.html(
'To invite someone, just send her your public key – that\'s all she\'ll need to add you as a peer. '
+ 'Along with that, you may want to send a download link for Open Media Library, in case she doesn\'t have it yet.'
)
.appendTo($form);
Ox.Input({
readonly: true,
label: Ox._('Your Public Key'),
labelWidth: 128,
style: 'squared',
value: oml.user.id,
width: 480
})
.css({
marginTop: '8px'
})
.appendTo($form);
Ox.Input({
readonly: true,
label: Ox._('Download Link'),
labelWidth: 128,
style: 'squared',
value: 'https://openmedialibrary.com/#download',
width: 480
})
.css({
marginTop: '8px'
})
.appendTo($form);
$('<div>')
.html(
'If someone invites you, or if you know another user\'s public key, you can add her here.'
)
.css({
margin: '32px 0 8px 0'
})
.appendTo($form);
}
$nickname = Ox.Input({
label: Ox._('Nickname'),
labelWidth: 128,
style: 'squared',
value: user.nickname,
width: 480
})
.bindEvent({
change: function(data) {
if (user.section != 'invitations') {
oml.api.editUser({
id: user.id,
nickname: data.value
}, function(result) {
oml.renameUser(result.data)
// FIXME: ugly
Ox.forEach($lists, function($list) {
var selected = $list.options('selected');
if (selected.length) {
$list.value(user.id, 'name', result.data.name);
return false;
}
});
});
}
}
})
.appendTo($form);
if (user.section == 'invitations') {
$id = Ox.Input({
label: Ox._('Public Key'),
labelWidth: 128,
style: 'squared',
width: 480
})
.bindEvent({
change: function(data) {
var isOwn = data.value == oml.user.id,
isPeer = Ox.contains(peerIds, data.value),
isValid = oml.validatePublicKey(data.value),
peer = Ox.getObjectById(users, data.value),
readonly = isOwn || isPeer || !isValid;
$buttons[0].options({
readonly: readonly
});
if (data.value && readonly) {
$warning.html(
isOwn ? 'That\'s your own public key.'
: isPeer ? 'That\'s '
+ Ox.encodeHTMLEntities(peer.nickname || peer.username)
+ ' - you\'re already peered.'
: 'That\'s not a valid key.'
)
} else {
$warning.empty();
if (data.value) {
user.id = data.value;
}
}
}
})
.css({
marginTop: '8px'
})
.appendTo($form);
} else {
Ox.Input({
readonly: true,
label: Ox._('Username'),
labelWidth: 128,
style: 'squared',
value: user.username,
width: 480
})
.css({
marginTop: '8px'
})
.appendTo($form);
Ox.Input({
readonly: true,
label: Ox._('Public Key'),
labelWidth: 128,
style: 'squared',
value: user.id,
width: 480
})
.css({
marginTop: '8px'
})
.appendTo($form);
Ox.Input({
readonly: true,
label: Ox._('Contact'),
labelWidth: 128,
style: 'squared',
value: user.contact || '',
width: 480
})
.css({
marginTop: '8px'
})
.appendTo($form);
if (user.pending) {
Ox.Input({
readonly: true,
label: Ox._('Message'),
labelWidth: 128,
style: 'squared',
value: user.message || '',
width: 480
})
.css({
marginTop: '8px'
})
.appendTo($form);
}
}
Ox.Label({
textAlign: 'center',
style: 'squared',
title: user.peered ? Ox._('Remove Peer')
: user.pending == 'received' ? Ox._('Accept Peering Request')
: user.pending == 'sent' ? Ox._('Cancel Peering Request')
: Ox._('Send Peering Request'),
width: 480
})
.css({
marginTop: '32px'
})
.appendTo($form);
$message = Ox.Input({
label: Ox._('Message'),
labelWidth: 128,
placeholder: Ox._('none'),
style: 'squared',
width: 480
})
.css({
margin: '8px 0'
})
.appendTo($form);
$buttons = (
user.peered ? ['remove']
: user.pending == 'received' ? ['accept', 'reject']
: user.pending == 'sent' ? ['cancel']
: ['send']
).map(function(id, index) {
return Ox.Button({
style: 'squared',
title: Ox.getObjectById(buttons, id).title
})
.css({
float: 'right',
marginRight: index ? '8px' : 0
})
.bindEvent({
click: function() {
var data = {
id: user.id,
message: $message.value()
};
if (id == 'send') {
data.nickname = $nickname.value();
oml.api.requestPeering(data, function(result) {
Ox.Request.clearCache();
updateUsers(function() {
selectUser(user.id);
});
});
} else if (id == 'cancel') {
oml.api.cancelPeering(data, function(result) {
Ox.Request.clearCache();
updateUsers(function() {
selectUser(user.id);
});
});
} else if (id == 'accept') {
oml.api.acceptPeering(data, function(result) {
Ox.Request.clearCache();
updateUsers(function() {
selectUser(user.id);
});
});
} else if (id == 'reject') {
oml.api.rejectPeering(data, function(result) {
Ox.Request.clearCache();
updateUsers(function() {
selectUser(user.id);
});
});
} else if (id == 'remove') {
oml.ui.confirmDialog({
buttons: [
Ox.Button({
title: Ox._('No, Keep Peer')
}),
Ox.Button({
title: Ox._('Yes, Remove Peer')
})
],
title: Ox._('Remove Peering'),
content: Ox._('Are you sure you want to remove this peer?')
}, function() {
oml.api.removePeering(data, function(result) {
Ox.Request.clearCache();
updateUsers(function() {
selectUser(user.id);
});
});
});
}
}
})
.appendTo($form);
});
}
that.replaceElement(1, $user);
}
function renderUserList(folder) {
var $list = Ox.TableList({
columns: [
{
format: function(value, data) {
return oml.ui.statusIcon(data)
.css({
margin: '2px 3px 3px 0'
});
},
id: 'online',
visible: true,
width: 16
},
{
format: function(value) {
return Ox.encodeHTMLEntities(value);
},
id: 'name',
visible: true,
width: 240
}
],
items: folder.items,
keys: ['local'],
max: 1,
sort: [{key: 'index', operator: '+'}],
sortable: folder.id == 'peers',
unique: 'id'
})
.css({
height: folder.items.length * 16 + 'px'
})
.bindEvent({
move: function(data) {
oml.api.sortUsers({
ids: data.ids
}, function(result) {
oml.$ui.folders.updateElement();
});
},
select: function(data) {
if (data.ids.length) {
selectItem($list);
renderUser(Ox.getObjectById(users, data.ids[0]));
} else {
renderUser();
}
}
});
return $list;
}
function selectUser(id) {
$lists.forEach(function($list) {
var item = $list.options('items').filter(function(item) {
return item.id == id;
})[0];
if (item) {
selectItem($list, id);
}
});
}
function selectItem($list, id) {
$lists.forEach(function($element) {
if ($element == $list) {
$element.gainFocus();
} else {
$element.options({selected: []});
}
});
if (id) {
$list.options({selected: [id]});
renderUser(Ox.getObjectById(users, id) || {section: id});
}
}
function updateUsers(callback) {
Ox.Request.clearCache('getUsers');
oml.api.getUsers(function(result) {
users = result.data.users;
peerIds = users.filter(function(user) {
return user.peered;
}).map(function(user) {
return user.id;
});
folders.forEach(function(folder) {
folder.items = [];
});
users.forEach(function(user, index) {
var id = user.peered ? 'peers' : (user.pending || 'others');
Ox.getObjectById(folders, id).items.push(
Ox.extend({
index: index,
nickname: '',
username: ''
}, user)
);
});
$lists.splice(1).forEach(function(folder) {
folder.remove();
});
folders.forEach(function(folder, index) {
$lists.push(
(
folder.items.length
? renderUserList(folder)
: renderSectionList(folder)
)
.appendTo($folders[index].$content)
);
});
$lists.forEach(function($list, index) {
$list.bindEvent({
selectnext: function() {
var $list;
if (index < $lists.length - 1) {
$list = $lists[index + 1];
selectItem($list, $list.options('items')[0].id);
}
},
selectprevious: function() {
var $list;
if (index) {
$list = $lists[index - 1];
selectItem($list, Ox.last($list.options('items')).id)
}
}
})
});
callback && callback();
});
}
that.updateElement = function() {
updateUsers(function() {
selectItem($lists[0], 'invitations');
renderUser({section: 'invitations'});
});
return that;
};
return that.updateElement();
};