Commit 997806ec authored by Juliusz Chroboczek's avatar Juliusz Chroboczek

Add contextual menu in user list.

parent 7cbc5166
...@@ -1120,7 +1120,6 @@ legend { ...@@ -1120,7 +1120,6 @@ legend {
transition: all 0.3s; transition: all 0.3s;
background: #ffffff; background: #ffffff;
border-right: 1px solid #dcdcdc; border-right: 1px solid #dcdcdc;
z-index: 1039;
} }
#left-sidebar .galene-header { #left-sidebar .galene-header {
...@@ -1168,7 +1167,6 @@ header .collapse { ...@@ -1168,7 +1167,6 @@ header .collapse {
margin: 0; margin: 0;
height: calc(100% - 84px); height: calc(100% - 84px);
width: 100%; width: 100%;
z-index: 1;
position: relative; position: relative;
display: block; display: block;
background-color: #fff; background-color: #fff;
...@@ -1345,3 +1343,17 @@ header .collapse { ...@@ -1345,3 +1343,17 @@ header .collapse {
} }
} }
:root{
--contextualMenuBg: #eee;
--contextualMenuShadow: 1px 1px 1px #444; */
--contextualMenuRadius: 0px; */
--contextualMenuText: black;
--contextualSubMenuBg: #eee;
--contextualHover: #ddd;
--contextualOverflowIcon: #999;
--contextualSeperator: #999;
}
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
<link rel="stylesheet" type="text/css" href="/external/fontawesome/css/solid.min.css"/> <link rel="stylesheet" type="text/css" href="/external/fontawesome/css/solid.min.css"/>
<link rel="stylesheet" type="text/css" href="/external/fontawesome/css/regular.min.css"/> <link rel="stylesheet" type="text/css" href="/external/fontawesome/css/regular.min.css"/>
<link rel="stylesheet" type="text/css" href="/external/toastify/toastify.css"/> <link rel="stylesheet" type="text/css" href="/external/toastify/toastify.css"/>
<link rel="stylesheet" type="text/css" href="/external/contextual/contextual.css"/>
</head> </head>
<body> <body>
...@@ -274,6 +275,7 @@ ...@@ -274,6 +275,7 @@
<script src="/protocol.js" defer></script> <script src="/protocol.js" defer></script>
<script src="/external/toastify/toastify.js" defer></script> <script src="/external/toastify/toastify.js" defer></script>
<script src="/external/contextual/contextual.js"></script>
<script src="/galene.js" defer></script> <script src="/galene.js" defer></script>
</body> </body>
</html> </html>
...@@ -1959,6 +1959,60 @@ function stringCompare(a, b) { ...@@ -1959,6 +1959,60 @@ function stringCompare(a, b) {
return 0 return 0
} }
/**
* @param {HTMLElement} elt
*/
function userMenu(elt) {
if(!elt.id.startsWith('user-'))
throw new Error('Unexpected id for user menu');
let id = elt.id.slice('user-'.length);
let user = serverConnection.users[id];
if(!user)
throw new Error("Couldn't find user")
let items = [];
if(id === serverConnection.id) {
let mydata = serverConnection.users[serverConnection.id].data;
if(mydata['raisehand'])
items.push({label: 'Lower hand', onClick: () => {
serverConnection.userAction(
'setdata', serverConnection.id, {'raisehand': null},
);
}});
else
items.push({label: 'Raise hand', onClick: () => {
serverConnection.userAction(
'setdata', serverConnection.id, {'raisehand': true},
);
}});
items.push({label: 'Restart media', onClick: renegotiateStreams});
} else {
items.push({label: 'Send file', onClick: () => {
sendFile(id);
}});
if(serverConnection.permissions.op) {
items.push({type: 'seperator'}); // sic
if(user.permissions.present)
items.push({label: 'Forbid presenting', onClick: () => {
serverConnection.userAction('unpresent', id);
}});
else
items.push({label: 'Allow presenting', onClick: () => {
serverConnection.userAction('present', id);
}});
items.push({label: 'Mute', onClick: () => {
serverConnection.userAction('mute', id);
}});
items.push({label: 'Kick out', onClick: () => {
serverConnection.userAction('kick', id);
}});
}
}
/** @ts-ignore */
new Contextual({
items: items,
});
}
/** /**
* @param {string} id * @param {string} id
* @param {user} userinfo * @param {user} userinfo
...@@ -1974,6 +2028,13 @@ function addUser(id, userinfo) { ...@@ -1974,6 +2028,13 @@ function addUser(id, userinfo) {
else else
user.classList.remove('user-status-raisehand'); user.classList.remove('user-status-raisehand');
user.addEventListener('click', function(e) {
let elt = e.target;
if(!elt || !(elt instanceof HTMLElement))
throw new Error("Couldn't find user div");
userMenu(elt);
});
let us = div.children; let us = div.children;
if(id === serverConnection.id) { if(id === serverConnection.id) {
...@@ -2342,12 +2403,12 @@ function failFile(f, message) { ...@@ -2342,12 +2403,12 @@ function failFile(f, message) {
} }
/** /**
* @param {string} username
* @param {string} id * @param {string} id
* @param {File} file * @param {File} file
*/ */
function offerFile(username, id, file) { function offerFile(id, file) {
let fileid = newRandomId(); let fileid = newRandomId();
let username = serverConnection.users[id].username;
let f = new TransferredFile( let f = new TransferredFile(
fileid, id, true, username, file.name, file.type, file.size, fileid, id, true, username, file.name, file.type, file.size,
); );
...@@ -3089,13 +3150,17 @@ commands.subgroups = { ...@@ -3089,13 +3150,17 @@ commands.subgroups = {
} }
}; };
commands.renegotiate = { function renegotiateStreams() {
description: 'renegotiate media streams',
f: (c, r) => {
for(let id in serverConnection.up) for(let id in serverConnection.up)
serverConnection.up[id].restartIce(); serverConnection.up[id].restartIce();
for(let id in serverConnection.down) for(let id in serverConnection.down)
serverConnection.down[id].restartIce(); serverConnection.down[id].restartIce();
}
commands.renegotiate = {
description: 'renegotiate media streams',
f: (c, r) => {
renegotiateStreams();
} }
}; };
...@@ -3283,16 +3348,10 @@ commands.unraise = { ...@@ -3283,16 +3348,10 @@ commands.unraise = {
} }
} }
commands.sendfile = { /**
parameters: 'user', * @param {string} id
description: 'send a file (this will disclose your IP address)', */
f: (c, r) => { function sendFile(id) {
let p = parseCommand(r);
if(!p[0])
throw new Error(`/${c} requires parameters`);
let id = findUserId(p[0]);
if(!id)
throw new Error(`Unknown user ${p[0]}`);
let input = document.createElement('input'); let input = document.createElement('input');
input.type = 'file'; input.type = 'file';
input.onchange = function(e) { input.onchange = function(e) {
...@@ -3301,15 +3360,28 @@ commands.sendfile = { ...@@ -3301,15 +3360,28 @@ commands.sendfile = {
let files = input.files; let files = input.files;
for(let i = 0; i < files.length; i++) { for(let i = 0; i < files.length; i++) {
try { try {
offerFile(p[i], id, files[i]); offerFile(id, files[i]);
} catch(e) { } catch(e) {
console.error(e); console.error(e);
displayError(e); displayError(e);
} }
}; }
}; };
input.click(); input.click();
} }
commands.sendfile = {
parameters: 'user',
description: 'send a file (this will disclose your IP address)',
f: (c, r) => {
let p = parseCommand(r);
if(!p[0])
throw new Error(`/${c} requires parameters`);
let id = findUserId(p[0]);
if(!id)
throw new Error(`Unknown user ${p[0]}`);
sendFile(id);
},
}; };
/** /**
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment