diff --git a/client/app.js b/client/app.js index 09d8d9d..4d884d2 100644 --- a/client/app.js +++ b/client/app.js @@ -69,8 +69,11 @@ window.getUser = async (id, name) => { ); }; -window.makeUser = (user, url, removable) => { - removable &&= window.currentThread.permissions.admin && !user.permissions?.admin; +window.makeUser = (user, url, context) => { + let removable = context === 'user' ? false : + window.currentThread?.permissions.admin && !user.permissions?.admin && + (context === 'member' ? true : Array.from(document.getElementById('memberlist').children) + .find(p => p.children[0].user?.id == user.id)); let span = html.node` userlist.replaceChildren(...msg.users.map(user => { let p = document.createElement('p'); - p.append(window.makeUser(user, instance.url)); + p.append(window.makeUser(user, instance.url, 'user')); return p; })) ); @@ -192,32 +195,34 @@ document.body.append(html.node`

- +

+

vybe

+

instances:

-

vybe

-

instances:

-
+
+
+
document.getElementById('profile').classList.toggle('hidden') }>${window.name}
diff --git a/client/index.html b/client/index.html index 6ea13a0..f689102 100644 --- a/client/index.html +++ b/client/index.html @@ -174,7 +174,8 @@ .user { white-space: pre-wrap; &:hover { - background-color: #444; + background-color: #333; + border-bottom: 1px #bbb solid; } } #profile { diff --git a/client/message.js b/client/message.js index 5db63b8..4091023 100644 --- a/client/message.js +++ b/client/message.js @@ -72,8 +72,7 @@ function loadMessages(callback) { } } let div = html.node`
: ${message.content}
`; - div.prepend(user ? window.makeUser(user, - user.id.split?.('@')[1] || instance.url, true) + div.prepend(user ? window.makeUser(user, user.id.split?.('@')[1] || instance.url) : html.node`${message.user.id}`); messages.prepend(div); } @@ -93,7 +92,7 @@ function loadMessages(callback) { let scroll = messages.scrollTop + 10 >= messages.scrollHeight - messages.clientHeight; let div = html.node`
: ${message.content}
`; div.prepend(window.makeUser(message.user, - message.user.id.split?.('@')[1] || instance.url, true)); + message.user.id.split?.('@')[1] || instance.url)); messages.append(div); if (scroll) messages.scroll(0, messages.scrollHeight - messages.clientHeight); diff --git a/client/stream.js b/client/stream.js index 428f56c..fb73c0d 100644 --- a/client/stream.js +++ b/client/stream.js @@ -78,7 +78,7 @@ function loadStreams() { let div = document.getElementById('stream'); div.innerHTML = ''; - if (window.currentThread.permissions.post) { + if (window.currentThread?.permissions.post) { // why doesn't html` work here? html.node` does render(div, html.node` - ${stream.user}${stream.name ? ` - ${stream.name}` : ''} + ${stream.name ? ` - ${stream.name}` : ''}

`; + p.insertBefore(window.makeUser(stream.user, + stream.user.id.split?.('@')[1] || window.currentInstance.url), + p.children[1]); p.id = 'stream' + stream.id; document.getElementById('streams').append(p); } @@ -167,8 +173,9 @@ function loadStreams() { }); } - for (let stream of window.currentThread.streams) - addStream(stream); + if (window.currentThread) + for (let stream of window.currentThread.streams) + addStream(stream); } export default loadStreams; diff --git a/client/thread.js b/client/thread.js index d23a64c..fce8db8 100644 --- a/client/thread.js +++ b/client/thread.js @@ -39,26 +39,17 @@ function chooseThread() { } else document.getElementById('thread').classList.remove('hidden'); - if (thread.permissions.admin) + if (thread.permissions.admin) { edit.classList.remove('hidden'); - else + document.getElementById('membersadd').classList.remove('hidden'); + } else { edit.classList.add('hidden'); + document.getElementById('membersadd').classList.add('hidden'); + } document.getElementById('threadname').textContent = thread.name; this.classList.add('active'); window.currentThread = thread; window.currentInstance = thread.instance; - let tab = url.searchParams.get('tab'); - if (!['message', 'space', 'stream'].includes(tab)) - tab = null; - if (tab || this.tab) { - if (tab) - this.tab = tab + 'tab'; - switchTab(document.getElementById(this.tab)); - if (this.tab === 'messagetab') - loadMessages(); - else if (this.tab === 'spacetab') - loadSpace(); - } let div = this; window.currentInstance.emit('get_thread', { thread: thread.id }, async msg => { if (!msg.success) { @@ -71,13 +62,13 @@ function chooseThread() { ...await Promise.all(msg.thread.members.map(async member => { let p = document.createElement('p'); if (member.name) - p.append(window.makeUser(member, window.currentInstance.url, true)); + p.append(window.makeUser(member, window.currentInstance.url, 'member')); else try { let user = await window.getUser(member.id); user.id = member.id; user.permissions = member.permissions; - p.append(window.makeUser(user, user.id.split?.('@')[1], true)); + p.append(window.makeUser(user, user.id.split?.('@')[1], 'member')); } catch (e) { console.log(`error getting user ${member.id}: ${e}`); @@ -87,9 +78,20 @@ function chooseThread() { })) ); loadStreams(); - if (!div.tab) + let tab = url.searchParams.get('tab'); + if (!['message', 'space', 'stream'].includes(tab)) + tab = null; + if (tab || this.tab) { + if (tab) + this.tab = tab + 'tab'; + switchTab(document.getElementById(this.tab)); + if (this.tab === 'messagetab') + loadMessages(); + else if (this.tab === 'spacetab') + loadSpace(); + } + else // load first tab that has any content await new Promise(resolve => { - // load first tab that has any content loadMessages(messages => { if (messages.length) { switchTab(document.getElementById(div.tab = 'messagetab')); @@ -108,8 +110,13 @@ function chooseThread() { }); }); }); - url.searchParams.set('thread', thread.id); - url.searchParams.set('tab', div.tab.substring(0, div.tab.length - 3)); + if (window.currentInstance === window.instancelist[0]) { + url.searchParams.set('thread', thread.id); + url.searchParams.set('tab', div.tab.substring(0, div.tab.length - 3)); + } else { + url.searchParams.delete('thread'); + url.searchParams.delete('tab'); + } window.history.pushState(null, '', url.toString()); }); } @@ -327,10 +334,8 @@ async function addMember() { name.value = ''; document.getElementById('addmember').classList.add('hidden'); } - if (!name.value) { - close(); - return; - } + if (!name.value) + return close(); let at = name.value.split('@'); let url = at[1] || window.currentInstance.url; let user = await window.getUser('@' + url, at[0]); @@ -339,15 +344,11 @@ async function addMember() { return; } error.innerText = ''; - if (window.currentInstance.url !== url) { + if (window.currentInstance.url !== url) user.id += '@' + url; - user.name += '@' + url; - } for (let p of document.getElementById('memberlist').children) - if (p.children[0].user.id == user.id) { - close(); - return; - } + if (p.children[0].user.id == user.id) + return close(); window.currentInstance.emit('add_member', { id: String(user.id), thread: window.currentThread.id @@ -359,7 +360,7 @@ async function addMember() { } close(); let p = document.createElement('p'); - p.append(window.makeUser(user, url, true)); + p.append(window.makeUser(user, url, 'member')); document.getElementById('memberlist').append(p); }); } @@ -404,7 +405,7 @@ async function loadThreads(instancediv, select) {

members - diff --git a/src/events/stream.js b/src/events/stream.js index d6f54bf..fffcc8b 100644 --- a/src/events/stream.js +++ b/src/events/stream.js @@ -26,8 +26,7 @@ async function stream(msg, respond, socket) { socket.emit('stream', stream); } else { for (let member of ( - await db.query( - 'select user from member where member.thread = ?', msg.thread) + await db.query('select user from member where member.thread = ?', msg.thread) ).rows) { member = vybe.users[member.user]; if (member) @@ -49,19 +48,30 @@ async function stream(msg, respond, socket) { message: "stream doesn't belong to user" }); if (msg.stop) { - stream.stop(); + await stream.stop(); return respond({ success: true }); } stream = stream.stream; stream.name = msg.name; + stream.user.displayname = msg.auth_user.displayname; } else { stream = { id: newstreamid++, thread: msg.thread, - user: msg.auth_user.displayname, + user: { + id: msg.auth_user.id, + name: msg.auth_user.name, + displayname: msg.auth_user.displayname, + permissions: Object.fromEntries((await db.query( + `select permission, value from permission + where type = 'user' and thread = ? and user = ?`, + [msg.thread, msg.auth_user.id])).rows.map(p => + [p.permission, ['admin', 'post', 'view'].includes(p.permission) + ? p.value === 'true' : p.value])) + }, name: msg.name }; thread.streams.push(stream); @@ -70,11 +80,11 @@ async function stream(msg, respond, socket) { userid: msg.auth_user.id, listeners: {}, socket: socket.id, - stop: () => { + stop: async () => { stream.stopped = true; thread.streams.splice(thread.streams.findIndex(s => s.id === stream.id), 1); delete vybe.streams[stream.id]; - send(); + await send(); } }; }