instance pane

main
jerl 2024-06-12 21:52:23 -07:00
parent 02294b0327
commit b8b7a7edd6
4 changed files with 100 additions and 42 deletions

View File

@ -94,7 +94,26 @@ function expandInstance(event) {
this.children[0].classList.toggle('collapsed');
}
function instanceClicked(event) {}
function instanceClicked(event) {
let instance = this.parentElement.parentElement.instance;
let div = document.getElementById('instance');
if (div.classList.contains('hidden')) {
let disconnect = document.getElementById('disconnect');
if (window.instancelist[0] === instance)
disconnect.classList.add('hidden');
else
disconnect.classList.remove('hidden');
document.getElementById('instancename').textContent = instance.url;
let userlist = document.getElementById('userlist');
userlist.innerHTML = '';
instance.emit('list_users', {}, msg =>
userlist.innerHTML = msg.users.map(user =>
`<p>${user.displayname}</p>`).join('\n')
);
div.instance = instance;
}
div.classList.toggle('hidden');
}
function saveInstances() {
localStorage.setItem('instances', JSON.stringify(
@ -110,10 +129,9 @@ async function addInstance() {
let instancediv = this.parentElement.parentElement;
if (!this.textContent)
return instancediv.remove();
let url = (/^[\w-]+:.+/.test(this.textContent) ? '' : 'https://') + this.textContent;
if (window.instancelist.find(i => i.url === url))
if (window.instancelist.find(i => i.url === this.textContent))
return instancediv.remove();
let instance = await connectInstance(url);
let instance = await connectInstance(this.textContent);
instancediv.instance = instance;
await authenticateInstance(instancediv, true);
this.contentEditable = false;
@ -130,13 +148,29 @@ async function addInstance() {
// main app html
document.body.append(html.node`
<div id='profile' class='column hidden'>
<p><strong>profile</strong></p>
<label class='heading'>display name</label>
<input id='newname' onkeyup=${function(event) {
if (window.displayname === this.value)
document.getElementById('savename').classList.add('hidden');
else if (event.key === 'Enter')
changeName();
else
document.getElementById('savename').classList.remove('hidden');
}}>
<button class='hidden' id='savename' onclick=${changeName}>save</button>
<label class='heading'>authentication requests</label>
<div id='authrequests'></div>
</div>
<hr class='separator' color='#505050'>
<div id='home' class='column'>
<div id='instancelist'>
<h3>vybe</h3>
<p id='instances'>instances:<button onclick=${() => {
let div = html.node`
<div>
<div class='instance'>
<div class='instancetitle'>
<span></span>
<span onblur=${addInstance} onkeydown=${function(event) {
if (event.key === 'Enter') {
@ -156,23 +190,22 @@ document.body.append(html.node`
}>${window.name}</div>
</div>
<hr class='separator' color='#505050'>
<!-- create thread column goes here -->
<hr class='separator' color='#505050'>
<div id='profile' class='column hidden'>
<p><strong>profile</strong></p>
<label class='heading'>display name</label>
<input id='newname' onkeyup=${function(event) {
if (window.displayname === this.value)
document.getElementById('savename').classList.add('hidden');
else if (event.key === 'Enter')
changeName();
else
document.getElementById('savename').classList.remove('hidden');
}}>
<button class='hidden' id='savename' onclick=${changeName}>save</button>
<label class='heading'>authentication requests</label>
<div id='authrequests'></div>
<div id='instance' class='column hidden'>
<div class='content'>
<p>instance: <strong id='instancename'></strong></p>
<h4>users</h4>
<div id='userlist'>
</div>
</div>
<button id='disconnect' onclick=${function(event) {
document.getElementById('instance' + this.parentElement.instance.id).remove();
window.instancelist.splice(window.instancelist.indexOf(this.parentElement.instance), 1);
saveInstances();
document.getElementById('instance').classList.add('hidden');
}}>disconnect</button>
</div>
<hr class='separator' color='#505050'>
<!-- create thread column goes here -->
<hr class='separator' color='#505050'>
`);
@ -180,7 +213,7 @@ for (let i = 0; i < instancelist.length; ++i) {
let instance = instancelist[i];
let div = html.node`
<div>
<div class='instance'>
<div class='instancetitle'>
<span class='expander' onclick=${expandInstance}>
<span class='arrow'></span>
</span>

View File

@ -71,11 +71,12 @@
max-width: 800px;
}
:not(#register) > p {
margin: 5px 1px;
margin-block: 5px;
word-wrap: break-word;
}
.thread:hover,
.tab:hover,
.instance > span:hover,
.instancetitle > span:hover,
#user:hover {
background-color: #333;
}
@ -86,7 +87,7 @@
color: #fff;
}
label.heading {
margin: 10px 1px 4px;
margin: 10px 0 4px;
display: block;
}
h3 {
@ -106,18 +107,22 @@
margin: 8px 2px;
}
.separator:has(+ .separator),
*.hidden + .separator,
.separator:has(+ *.hidden),
.separator:last-child {
display: none;
}
.instance {
.content {
flex: 1;
}
.instancetitle {
margin: 2px;
> span {
display: table-cell;
background-color: #222;
padding-block: 6px;
}
> .title {
padding-block: 6px;
width: 100%;
}
}
@ -142,9 +147,12 @@
flex-direction: column;
justify-content: space-between;
}
#instancelist > :not(div) {
#instancelist {
overflow-y: auto;
> :not(div) {
margin: 3px;
}
}
#instances {
display: flex;
justify-content: space-between;
@ -166,6 +174,15 @@
#profile {
max-width: 250px;
}
#instance {
display: flex;
flex-direction: column;
justify-content: space-between;
max-width: 250px;
}
#disconnect {
width: fit-content;
}
.thread {
padding: 2px 3px;
white-space: pre;
@ -187,7 +204,7 @@
}
#content {
margin: 2px;
flex: 1;
min-width: 300px;
display: flex;
flex-direction: column;
}
@ -237,11 +254,8 @@
margin-bottom: 10px;
}
#members {
flex: 1;
min-width: 140px;
max-width: 250px;
> * {
margin: 4px;
}
}
#editthread {
max-width: fit-content;

View File

@ -129,7 +129,7 @@ function newThread() {
name.value = '';
}
document.querySelector('#home + .separator').insertAdjacentElement('afterend', html.node`
document.querySelector('#instance + .separator').insertAdjacentElement('afterend', html.node`
<form id='createthread' class='column' onsubmit=${event => {
event.preventDefault();
let name = document.getElementById('newthreadname').value;
@ -164,7 +164,7 @@ function newThread() {
}
);
}}>
<h3>create thread</h3>
<h4>create thread</h4>
<label for='newthreadname' class='heading'>thread name</label>
<p id='newnameempty' class='hidden'>name cannot be empty</p>
<input type='text' id='newthreadname' />
@ -237,6 +237,7 @@ function editThread() {
editThread();
});
}}>
<h4>edit thread</h4>
<label for='editthreadname' class='heading'>thread name</label>
<input type='text' id='editthreadname' />
<p id='nameempty' class='hidden'>name cannot be empty</p>
@ -260,7 +261,7 @@ function editThread() {
form['private_post'].checked = true;
else
form['private_view'].checked = true;
document.querySelector('#thread').append(form);
document.body.append(form);
document.getElementById('edit').textContent = 'cancel';
}
@ -289,7 +290,7 @@ async function loadThreads(instancediv, select) {
if (!document.getElementById('thread'))
document.body.append(html.node`
<div id='thread' class='column hidden'>
<div id='content'>
<div id='content' class='content'>
<div id='titlebar'>
<span id='title'>thread: <strong id='threadname'>meow</strong></span>
<button id='edit' class='hidden' onclick=${editThread}>edit</button>
@ -309,14 +310,14 @@ async function loadThreads(instancediv, select) {
<div id='stream' class='tabcontent hidden'></div>
</div>
<hr class='separator' color='#505050'>
<div id='members' class='hidden'>
<div id='members' class='column hidden'>
<p id='visibility'></p>
<p><strong>members</strong></p>
<h4>members</h4>
<div id='memberlist'>
</div>
</div>
<hr class='separator' color='#505050'>
</div>`);
</div>
<hr class='separator' color='#505050'>`);
if (!instancediv.children['threads']) {
instancediv.append(html.node`

View File

@ -249,6 +249,15 @@ async function get_user(msg, respond) {
});
}
async function list_users(msg, respond) {
return respond({
success: true,
users: (await db.query(`
select id, name, coalesce(displayname, name) as displayname
from user`)).rows
});
}
async function get_keys(msg, respond) {
// validate inputs
if (!Array.isArray(msg.ids)) {
@ -276,5 +285,6 @@ module.exports = {
authorize_key: authwrap(authorize_key),
update_user: authwrap(update_user),
get_user,
list_users: authwrap(list_users),
get_keys
};