bugfixes and style improvements
parent
0b830174d3
commit
05bbdc0d60
173
client/app.js
173
client/app.js
|
@ -1,23 +1,33 @@
|
||||||
import { render, html } from '/uhtml.js';
|
import { render, html } from "/uhtml.js";
|
||||||
|
|
||||||
window.currentThreadId = 1;
|
window.currentThreadId = 1;
|
||||||
|
|
||||||
function chooseThread(thread) {
|
function chooseThread(thread) {
|
||||||
if (window.currentThreadId)
|
if (window.currentThreadId)
|
||||||
document.getElementById(`thread${window.currentThreadId}`).classList.remove('selected');
|
document
|
||||||
document.getElementById(`thread${thread.id}`).classList.add('selected');
|
.getElementById(`thread${window.currentThreadId}`)
|
||||||
|
.classList.remove("active");
|
||||||
|
document.getElementById(`thread${thread.id}`).classList.add("active");
|
||||||
window.currentThreadId = thread.id;
|
window.currentThreadId = thread.id;
|
||||||
window.earliestMessage = null;
|
window.earliestMessage = null;
|
||||||
document.getElementById("messages").innerHTML = "";
|
document.getElementById("messages").innerHTML = "";
|
||||||
document.getElementById("threadname").textContent = thread.name;
|
document.getElementById("threadname").textContent = thread.name;
|
||||||
|
if (!thread.permissions.post) {
|
||||||
|
document.getElementById("msginput").classList.add("hidden");
|
||||||
|
} else {
|
||||||
|
document.getElementById("msginput").classList.remove("hidden");
|
||||||
|
}
|
||||||
loadMessages();
|
loadMessages();
|
||||||
}
|
}
|
||||||
|
|
||||||
function loadMessages() {
|
function loadMessages() {
|
||||||
window.emit("get_history", {
|
window.emit(
|
||||||
|
"get_history",
|
||||||
|
{
|
||||||
before: window.earliestMessage,
|
before: window.earliestMessage,
|
||||||
thread: window.currentThreadId,
|
thread: window.currentThreadId,
|
||||||
}, msg => {
|
},
|
||||||
|
(msg) => {
|
||||||
if (msg.messages.length > 0) {
|
if (msg.messages.length > 0) {
|
||||||
window.earliestMessage = msg.messages[msg.messages.length - 1].id;
|
window.earliestMessage = msg.messages[msg.messages.length - 1].id;
|
||||||
for (let message of msg.messages)
|
for (let message of msg.messages)
|
||||||
|
@ -29,30 +39,26 @@ function loadMessages() {
|
||||||
}
|
}
|
||||||
if (!msg.more)
|
if (!msg.more)
|
||||||
document.getElementById("loadmore").classList.add("hidden");
|
document.getElementById("loadmore").classList.add("hidden");
|
||||||
else
|
else document.getElementById("loadmore").classList.remove("hidden");
|
||||||
document.getElementById("loadmore").classList.remove("hidden");
|
}
|
||||||
});
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function addThread(thread) {
|
function addThread(thread, top) {
|
||||||
let node = html.node`
|
let node = html.node`
|
||||||
<div class='thread' onclick=${() => {
|
<button class='thread tab' onclick=${() => chooseThread(thread)}>${
|
||||||
chooseThread(thread);
|
thread.name
|
||||||
if (!thread.permissions.post) {
|
}</button>`;
|
||||||
document.getElementById("msginput").classList.add("hidden");
|
|
||||||
} else {
|
|
||||||
document.getElementById("msginput").classList.remove("hidden");
|
|
||||||
}
|
|
||||||
}}>${thread.name}</div>`;
|
|
||||||
node.id = `thread${thread.id}`;
|
node.id = `thread${thread.id}`;
|
||||||
document.getElementById("threadlist").appendChild(node);
|
document.getElementById("threadlist")[top ? "prepend" : "appendChild"](node);
|
||||||
}
|
}
|
||||||
|
|
||||||
function addMember() {
|
function addMember() {
|
||||||
const name = document.getElementById("membername").value;
|
const name = document.getElementById("membername").value;
|
||||||
window.threadmembers.push(name);
|
window.threadmembers.push(name);
|
||||||
document.getElementById("memberlist").appendChild(
|
document
|
||||||
html.node`<p class='member'>${name}</p>`);
|
.getElementById("memberlist")
|
||||||
|
.appendChild(html.node`<p class='member'>${name}</p>`);
|
||||||
document.getElementById("membername").value = "";
|
document.getElementById("membername").value = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -60,31 +66,34 @@ async function createThread(e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
let name = document.getElementById("newthreadname");
|
let name = document.getElementById("newthreadname");
|
||||||
if (!name.value) {
|
if (!name.value) {
|
||||||
name.insertAdjacentHTML('afterend', `<p>name cannot be empty</p>`);
|
name.insertAdjacentHTML("afterend", `<p>name cannot be empty</p>`);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let members = window.threadmembers.map(name => ({ name }));
|
let members = window.threadmembers.map((name) => ({ name }));
|
||||||
const perms = document.querySelector(
|
const perms = document.querySelector(
|
||||||
'input[name="permissions"]:checked').value;
|
'input[name="permissions"]:checked'
|
||||||
|
).value;
|
||||||
if (perms === "private_view")
|
if (perms === "private_view")
|
||||||
members = (await new Promise(resolve =>
|
members = (
|
||||||
|
await new Promise((resolve) =>
|
||||||
window.emit("get_keys", { names: window.threadmembers }, resolve)
|
window.emit("get_keys", { names: window.threadmembers }, resolve)
|
||||||
)).keys;
|
)
|
||||||
|
).keys;
|
||||||
let permissions;
|
let permissions;
|
||||||
if (perms === "public") {
|
if (perms === "public") {
|
||||||
permissions = {
|
permissions = {
|
||||||
view_limited: false,
|
view_limited: false,
|
||||||
post_limited: false
|
post_limited: false,
|
||||||
};
|
};
|
||||||
} else if (perms === "private_post") {
|
} else if (perms === "private_post") {
|
||||||
permissions = {
|
permissions = {
|
||||||
view_limited: false,
|
view_limited: false,
|
||||||
post_limited: true
|
post_limited: true,
|
||||||
};
|
};
|
||||||
} else if (perms === "private_view") {
|
} else if (perms === "private_view") {
|
||||||
permissions = {
|
permissions = {
|
||||||
view_limited: true,
|
view_limited: true,
|
||||||
post_limited: true
|
post_limited: true,
|
||||||
};
|
};
|
||||||
// generate key
|
// generate key
|
||||||
/* wip
|
/* wip
|
||||||
|
@ -101,45 +110,50 @@ async function createThread(e) {
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
window.emit("create_thread", {
|
window.emit(
|
||||||
|
"create_thread",
|
||||||
|
{
|
||||||
name: name.value,
|
name: name.value,
|
||||||
permissions,
|
permissions,
|
||||||
members
|
members,
|
||||||
}, msg => {
|
},
|
||||||
|
(msg) => {
|
||||||
chooseThread({
|
chooseThread({
|
||||||
name: name.value,
|
name: name.value,
|
||||||
id: msg.id
|
id: msg.id,
|
||||||
});
|
});
|
||||||
document.getElementById('createthread').remove();
|
// since the form exists, this will perform cleanup
|
||||||
|
newThread();
|
||||||
document.getElementById("loadmore").classList.add("hidden");
|
document.getElementById("loadmore").classList.add("hidden");
|
||||||
document.getElementById("msginput").classList.remove("hidden");
|
document.getElementById("msginput").classList.remove("hidden");
|
||||||
});
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function sendMessage(e) {
|
function sendMessage(e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
const msg = document.getElementById("msg").value;
|
const msg = document.getElementById("msg").value;
|
||||||
if (!msg)
|
if (!msg) return;
|
||||||
return;
|
|
||||||
window.emit("send_message", {
|
window.emit("send_message", {
|
||||||
message: msg,
|
message: msg,
|
||||||
thread: window.currentThreadId
|
thread: window.currentThreadId,
|
||||||
});
|
});
|
||||||
document.getElementById("msg").value = "";
|
document.getElementById("msg").value = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
function newThread(e) {
|
function newThread() {
|
||||||
let form = document.getElementById('createthread');
|
let form = document.getElementById("createthread");
|
||||||
if (form) {
|
if (form) {
|
||||||
form.remove();
|
form.remove();
|
||||||
e.target.textContent = 'create';
|
document.getElementById("newthread").textContent = "create";
|
||||||
}
|
} else {
|
||||||
else {
|
window.threadmembers = [window.name];
|
||||||
window.threadmembers = [ window.name ];
|
document.getElementById("threads").insertAdjacentElement(
|
||||||
document.getElementById('threads').insertAdjacentElement('afterend', html.node`
|
"afterend",
|
||||||
|
html.node`
|
||||||
<form id="createthread" class='column' onsubmit=${createThread}>
|
<form id="createthread" class='column' onsubmit=${createThread}>
|
||||||
<h3>create thread</h3>
|
<h3>create thread</h3>
|
||||||
<label for="newthreadname">thread name</label>
|
<label for="newthreadname" class="heading">thread name</label>
|
||||||
<input type="text" id="newthreadname" />
|
<input type="text" id="newthreadname" />
|
||||||
<p id='permissions'>thread permissions</p>
|
<p id='permissions'>thread permissions</p>
|
||||||
<input type="radio" id="public" name="permissions" value="public" checked />
|
<input type="radio" id="public" name="permissions" value="public" checked />
|
||||||
|
@ -153,7 +167,7 @@ function newThread(e) {
|
||||||
/>
|
/>
|
||||||
<label for="private_view">only members can view and post</label
|
<label for="private_view">only members can view and post</label
|
||||||
><br /><br />
|
><br /><br />
|
||||||
<span>members</span><br />
|
<label class="heading" for="membername">members</label>
|
||||||
<input type="text" id="membername" placeholder="username" onkeydown=${(e) => {
|
<input type="text" id="membername" placeholder="username" onkeydown=${(e) => {
|
||||||
if (e.key == "Enter") {
|
if (e.key == "Enter") {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
@ -165,65 +179,68 @@ function newThread(e) {
|
||||||
<p class='member'>${window.name}</p>
|
<p class='member'>${window.name}</p>
|
||||||
</div>
|
</div>
|
||||||
<br />
|
<br />
|
||||||
<input id="submitthread" type="submit" value="create" />
|
<button id="submitthread" type="submit">create</button>
|
||||||
</form>
|
</form>
|
||||||
`);
|
`
|
||||||
e.target.textContent = 'cancel';
|
);
|
||||||
|
document.getElementById("newthread").textContent = "cancel";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function switchTab(event){
|
function switchTab(event) {
|
||||||
for (let tab of document.querySelectorAll('.tab'))
|
for (let tab of document.querySelectorAll(".tab"))
|
||||||
tab.classList.remove('active');
|
tab.classList.remove("active");
|
||||||
for (let tab of document.querySelectorAll('.tabcontent'))
|
for (let tab of document.querySelectorAll(".tabcontent"))
|
||||||
tab.classList.add('hidden');
|
tab.classList.add("hidden");
|
||||||
event.target.classList.add('active');
|
event.target.classList.add("active");
|
||||||
document.getElementById(event.target.id.substring(0, event.target.id.length - 3))
|
document
|
||||||
.classList.remove('hidden');
|
.getElementById(event.target.id.substring(0, event.target.id.length - 3))
|
||||||
|
.classList.remove("hidden");
|
||||||
}
|
}
|
||||||
|
|
||||||
render(document.body, html`
|
render(
|
||||||
|
document.body,
|
||||||
|
html`
|
||||||
<div id="threads" class="column">
|
<div id="threads" class="column">
|
||||||
<h3>vybe</h3>
|
<h3>vybe</h3>
|
||||||
<h4>threads</h4>
|
<h4>threads</h4>
|
||||||
<div id="threadlist">loading...</div>
|
<div id="threadlist">loading...</div>
|
||||||
<button id='newthread' onclick=${newThread}>create</button>
|
<button id="newthread" onclick=${newThread}>create</button>
|
||||||
</div>
|
</div>
|
||||||
<div id="thread" class="column">
|
<div id="thread" class="column">
|
||||||
<div id='title'>
|
<div id="title">thread: <strong id="threadname">meow</strong></div>
|
||||||
thread: <strong id="threadname">meow</strong>
|
<button id="messagetab" class="tab active" onclick=${switchTab}>
|
||||||
</div>
|
messages
|
||||||
<button id='messagetab' class='tab active' onclick=${switchTab}>messages</button>
|
</button>
|
||||||
<button id='spacetab' class='tab' onclick=${switchTab}>space</button>
|
<button id="spacetab" class="tab" onclick=${switchTab}>space</button>
|
||||||
<button id="loadmore" class="hidden" onclick=${loadMessages}>load more messages</button>
|
<button id="loadmore" class="hidden" onclick=${loadMessages}>
|
||||||
<div id='message' class='tabcontent'>
|
load more messages
|
||||||
<div id='messages'>
|
</button>
|
||||||
</div>
|
<div id="message" class="tabcontent">
|
||||||
|
<div id="messages"></div>
|
||||||
<form id="msginput" onsubmit=${sendMessage}>
|
<form id="msginput" onsubmit=${sendMessage}>
|
||||||
<input type="text" placeholder="write a message..." id="msg" />
|
<input type="text" placeholder="write a message..." id="msg" />
|
||||||
<button type="submit" class="hidden" id="sendmsg"></button>
|
<button type="submit" class="hidden" id="sendmsg"></button>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
<div id='space' class='tabcontent'></div>
|
<div id="space" class="tabcontent"></div>
|
||||||
</div>
|
</div>
|
||||||
`);
|
`
|
||||||
|
);
|
||||||
|
|
||||||
window.socket.on("new_message", (msg) => {
|
window.socket.on("new_message", (msg) => {
|
||||||
if (msg.thread !== window.currentThreadId)
|
if (msg.thread !== window.currentThreadId) return;
|
||||||
return;
|
|
||||||
document.getElementById("messages").appendChild(html.node`
|
document.getElementById("messages").appendChild(html.node`
|
||||||
<div class='message'>
|
<div class='message'>
|
||||||
<strong>${msg.name}: </strong>
|
<strong>${msg.name}: </strong>
|
||||||
${msg.message}
|
${msg.message}
|
||||||
</div>`);
|
</div>`);
|
||||||
if (!window.earliestMessage)
|
if (!window.earliestMessage) window.earliestMessage = msg.id;
|
||||||
window.earliestMessage = msg.id;
|
|
||||||
});
|
});
|
||||||
window.socket.on("new_thread", addThread);
|
window.socket.on("new_thread", (thread) => addThread(thread, true));
|
||||||
|
|
||||||
window.emit("list_threads", {}, msg => {
|
window.emit("list_threads", {}, (msg) => {
|
||||||
document.getElementById("threadlist").innerHTML = "";
|
document.getElementById("threadlist").innerHTML = "";
|
||||||
for (let thread of msg.threads)
|
for (let thread of msg.threads) addThread(thread);
|
||||||
addThread(thread);
|
|
||||||
chooseThread(msg.threads[0]);
|
chooseThread(msg.threads[0]);
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { render, html } from '/uhtml.js';
|
import { render, html } from "/uhtml.js";
|
||||||
|
|
||||||
function rand() {
|
function rand() {
|
||||||
let str = "";
|
let str = "";
|
||||||
|
@ -16,19 +16,26 @@ async function auth() {
|
||||||
message: new openpgp.CleartextMessage("vybe_auth " + window.session, ""),
|
message: new openpgp.CleartextMessage("vybe_auth " + window.session, ""),
|
||||||
signingKeys: window.keys.priv,
|
signingKeys: window.keys.priv,
|
||||||
});
|
});
|
||||||
window.socket.emit("authenticate", { name: window.name, message: sig },
|
window.socket.emit(
|
||||||
msg => {
|
"authenticate",
|
||||||
|
{ name: window.name, message: sig },
|
||||||
|
(msg) => {
|
||||||
if (!msg.success) {
|
if (!msg.success) {
|
||||||
console.log('authenticate failed');
|
console.log("authenticate failed", msg);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (document.getElementById("register")) {
|
||||||
document.getElementById("register").remove();
|
document.getElementById("register").remove();
|
||||||
import('/app.js');
|
import("/app.js");
|
||||||
});
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
render(document.body, html`
|
render(
|
||||||
<div id="register" class='hidden'>
|
document.body,
|
||||||
|
html`
|
||||||
|
<div id="register" class="hidden">
|
||||||
<h1>welcome to vybe</h1>
|
<h1>welcome to vybe</h1>
|
||||||
<h3>a communication network (beta)</h3>
|
<h3>a communication network (beta)</h3>
|
||||||
<p>
|
<p>
|
||||||
|
@ -36,20 +43,26 @@ render(document.body, html`
|
||||||
for security, rather than passwords. your keys are stored in your
|
for security, rather than passwords. your keys are stored in your
|
||||||
browser storage only, so do this on a browser you can access again.
|
browser storage only, so do this on a browser you can access again.
|
||||||
</p>
|
</p>
|
||||||
<form onsubmit=${async e => {
|
<form
|
||||||
|
onsubmit=${async (e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
const name = document.getElementById("name").value;
|
const name = document.getElementById("name").value;
|
||||||
if (!name)
|
if (!name) return;
|
||||||
return;
|
|
||||||
const keys = await openpgp.generateKey({
|
const keys = await openpgp.generateKey({
|
||||||
userIDs: [{ name }],
|
userIDs: [{ name }],
|
||||||
});
|
});
|
||||||
const priv = await openpgp.readKey({ armoredKey: keys.privateKey });
|
const priv = await openpgp.readKey({ armoredKey: keys.privateKey });
|
||||||
const pub = await openpgp.readKey({ armoredKey: keys.publicKey });
|
const pub = await openpgp.readKey({ armoredKey: keys.publicKey });
|
||||||
window.emit("create_user", { name, pubkey: keys.publicKey }, msg => {
|
window.emit(
|
||||||
|
"create_user",
|
||||||
|
{ name, pubkey: keys.publicKey },
|
||||||
|
(msg) => {
|
||||||
if (!msg.success) {
|
if (!msg.success) {
|
||||||
document.querySelector('#registerform').insertAdjacentHTML('afterend', `
|
document.querySelector("#registerform").insertAdjacentHTML(
|
||||||
<p>${msg.message}</p>`);
|
"afterend",
|
||||||
|
`
|
||||||
|
<p>${msg.message}</p>`
|
||||||
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
window.keys = { priv, pub };
|
window.keys = { priv, pub };
|
||||||
|
@ -57,23 +70,37 @@ render(document.body, html`
|
||||||
localStorage.setItem("name", name);
|
localStorage.setItem("name", name);
|
||||||
window.name = name;
|
window.name = name;
|
||||||
auth();
|
auth();
|
||||||
});
|
}
|
||||||
}} id="registerform">
|
);
|
||||||
|
}}
|
||||||
|
id="registerform"
|
||||||
|
>
|
||||||
<label for="name">username: </label>
|
<label for="name">username: </label>
|
||||||
<input id="name" type="text" />
|
<input id="name" type="text" />
|
||||||
<input id="submit" type="submit" value='generate keys & register'>
|
<input id="submit" type="submit" value="generate keys & register" />
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
`);
|
`
|
||||||
|
);
|
||||||
|
|
||||||
|
const gensession = async () => {
|
||||||
|
window.session = rand();
|
||||||
|
|
||||||
|
window.emit = (type, data, callback) =>
|
||||||
|
window.socket.emit(
|
||||||
|
type,
|
||||||
|
{
|
||||||
|
...data,
|
||||||
|
__session: window.session,
|
||||||
|
},
|
||||||
|
callback
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
window.onload = async () => {
|
window.onload = async () => {
|
||||||
window.socket = io();
|
window.socket = io();
|
||||||
|
|
||||||
window.session = rand();
|
await gensession();
|
||||||
window.emit = (type, data, callback) => window.socket.emit(type, {
|
|
||||||
...data,
|
|
||||||
__session: window.session,
|
|
||||||
}, callback);
|
|
||||||
|
|
||||||
let keys = localStorage.getItem("keys");
|
let keys = localStorage.getItem("keys");
|
||||||
if (keys) {
|
if (keys) {
|
||||||
|
@ -81,10 +108,13 @@ window.onload = async () => {
|
||||||
keys = JSON.parse(keys);
|
keys = JSON.parse(keys);
|
||||||
window.keys = {
|
window.keys = {
|
||||||
priv: await openpgp.readKey({ armoredKey: keys.privateKey }),
|
priv: await openpgp.readKey({ armoredKey: keys.privateKey }),
|
||||||
pub: await openpgp.readKey({ armoredKey: keys.publicKey })
|
pub: await openpgp.readKey({ armoredKey: keys.publicKey }),
|
||||||
};
|
};
|
||||||
await auth();
|
await auth();
|
||||||
}
|
} else document.getElementById("register").classList.remove("hidden");
|
||||||
else
|
|
||||||
document.getElementById('register').classList.remove('hidden');
|
window.socket.io.on("reconnect", async (attempt) => {
|
||||||
|
await gensession();
|
||||||
|
if (localStorage.getItem("keys")) await auth();
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
|
@ -18,20 +18,47 @@
|
||||||
body,
|
body,
|
||||||
button,
|
button,
|
||||||
input {
|
input {
|
||||||
background: #020202;
|
|
||||||
color: #eaeaea;
|
color: #eaeaea;
|
||||||
|
border: none;
|
||||||
|
outline: none;
|
||||||
}
|
}
|
||||||
body {
|
body {
|
||||||
|
background: #020202;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: stretch;
|
align-items: stretch;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
min-width: min-content;
|
min-width: min-content;
|
||||||
}
|
}
|
||||||
h3, h4 {
|
button,
|
||||||
margin: 10px 0;
|
input,
|
||||||
|
.tab {
|
||||||
|
padding: 5px 7px;
|
||||||
}
|
}
|
||||||
button {
|
button {
|
||||||
border-color: #767676;
|
background: #4f4f4f;
|
||||||
|
}
|
||||||
|
input {
|
||||||
|
background: #2f2f2f;
|
||||||
|
border-bottom: 2px solid transparent;
|
||||||
|
padding-bottom: 3px;
|
||||||
|
}
|
||||||
|
input:focus {
|
||||||
|
border-bottom: 2px solid #4f4f4f;
|
||||||
|
}
|
||||||
|
input::placeholder {
|
||||||
|
color: #aaa;
|
||||||
|
}
|
||||||
|
button:hover,
|
||||||
|
.tab:hover {
|
||||||
|
background-color: #3b3b3b;
|
||||||
|
}
|
||||||
|
label.heading {
|
||||||
|
margin-bottom: 5px;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
h3,
|
||||||
|
h4 {
|
||||||
|
margin: 10px 0;
|
||||||
}
|
}
|
||||||
.hidden {
|
.hidden {
|
||||||
display: none;
|
display: none;
|
||||||
|
@ -44,11 +71,10 @@
|
||||||
#threads {
|
#threads {
|
||||||
max-width: 250px;
|
max-width: 250px;
|
||||||
}
|
}
|
||||||
.thread.selected {
|
.thread {
|
||||||
background-color: #4f4f4f;
|
display: block;
|
||||||
}
|
width: 100%;
|
||||||
.thread:hover {
|
text-align: left;
|
||||||
background-color: #3b3b3b;
|
|
||||||
}
|
}
|
||||||
#newthread {
|
#newthread {
|
||||||
margin-top: 5px;
|
margin-top: 5px;
|
||||||
|
@ -63,9 +89,9 @@
|
||||||
margin: 4px 2px;
|
margin: 4px 2px;
|
||||||
}
|
}
|
||||||
.tab {
|
.tab {
|
||||||
|
background: transparent;
|
||||||
border: 0;
|
border: 0;
|
||||||
margin-top: 2px;
|
margin-top: 2px;
|
||||||
padding: 5px 7px;
|
|
||||||
color: #ccc;
|
color: #ccc;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
}
|
}
|
||||||
|
@ -73,9 +99,6 @@
|
||||||
background-color: #4f4f4f;
|
background-color: #4f4f4f;
|
||||||
color: #fff;
|
color: #fff;
|
||||||
}
|
}
|
||||||
.tab:hover {
|
|
||||||
background-color:#3b3b3b;
|
|
||||||
}
|
|
||||||
#messages {
|
#messages {
|
||||||
margin: 4px 2px;
|
margin: 4px 2px;
|
||||||
}
|
}
|
||||||
|
@ -97,6 +120,5 @@
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body></body>
|
||||||
</body>
|
|
||||||
</html>
|
</html>
|
||||||
|
|
27
index.js
27
index.js
|
@ -3,15 +3,17 @@ const http = require("http");
|
||||||
const { Server } = require("socket.io");
|
const { Server } = require("socket.io");
|
||||||
const compression = require("compression");
|
const compression = require("compression");
|
||||||
|
|
||||||
const events = Object.fromEntries([
|
const events = Object.fromEntries(
|
||||||
'create_user',
|
[
|
||||||
'get_history',
|
"create_user",
|
||||||
'send_message',
|
"get_history",
|
||||||
'authenticate',
|
"send_message",
|
||||||
'create_thread',
|
"authenticate",
|
||||||
'list_threads',
|
"create_thread",
|
||||||
'get_keys',
|
"list_threads",
|
||||||
].map(event => [event, require('./src/' + event)]));
|
"get_keys",
|
||||||
|
].map((event) => [event, require("./src/" + event)])
|
||||||
|
);
|
||||||
|
|
||||||
const app = express();
|
const app = express();
|
||||||
app.use(compression());
|
app.use(compression());
|
||||||
|
@ -32,11 +34,10 @@ io.on("connection", (socket) => {
|
||||||
events[event](msg, callback, socket, io)
|
events[event](msg, callback, socket, io)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
socket.on('disconnect', reason => {
|
socket.on("disconnect", (reason) => {
|
||||||
let sockets = io.cache[socket.username];
|
let sockets = io.cache[socket.username];
|
||||||
if (sockets)
|
if (sockets) sockets.splice(sockets.indexOf(socket.id), 1);
|
||||||
sockets.splice(sockets.indexOf(socket.id), 1);
|
});
|
||||||
})
|
|
||||||
});
|
});
|
||||||
|
|
||||||
server.listen(PORT, () => {
|
server.listen(PORT, () => {
|
||||||
|
|
|
@ -3,7 +3,7 @@ const authwrap = require("./authwrap");
|
||||||
|
|
||||||
const create_thread = async (msg, respond, socket, io) => {
|
const create_thread = async (msg, respond, socket, io) => {
|
||||||
// validate inputs
|
// validate inputs
|
||||||
if (typeof msg.name !== 'string') {
|
if (typeof msg.name !== "string") {
|
||||||
return respond({
|
return respond({
|
||||||
success: false,
|
success: false,
|
||||||
message: "thread name required",
|
message: "thread name required",
|
||||||
|
@ -77,24 +77,23 @@ const create_thread = async (msg, respond, socket, io) => {
|
||||||
permissions: {
|
permissions: {
|
||||||
is_member: false,
|
is_member: false,
|
||||||
view: true,
|
view: true,
|
||||||
post: !msg.permissions || !msg.permissions.post_limited
|
post: !msg.permissions || !msg.permissions.post_limited,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
for (let member of msg.members) {
|
for (let member of msg.members) {
|
||||||
for (let socket of io.cache[member.user]) {
|
for (let socket of io.cache[member.name]) {
|
||||||
io.to(socket).emit("new_thread", {
|
io.to(socket).emit("new_thread", {
|
||||||
name: msg.name,
|
name: msg.name,
|
||||||
id: insert.rows[0].id,
|
id: insert.rows[0].id,
|
||||||
permissions: {
|
permissions: {
|
||||||
is_member: true,
|
is_member: true,
|
||||||
view: true,
|
view: true,
|
||||||
post: true
|
post: true,
|
||||||
},
|
},
|
||||||
key: member.key
|
key: member.key,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue