column view n live threads
parent
55fdc45073
commit
b2b15231df
111
client/chat.js
111
client/chat.js
|
@ -19,43 +19,6 @@ async function auth() {
|
||||||
window.socket.emit("authenticate", { name: window.name, message: sig });
|
window.socket.emit("authenticate", { name: window.name, message: sig });
|
||||||
}
|
}
|
||||||
|
|
||||||
async function register(e) {
|
|
||||||
e.preventDefault();
|
|
||||||
const name = document.getElementById("name").value;
|
|
||||||
if (!name) return;
|
|
||||||
const keys = await openpgp.generateKey({
|
|
||||||
userIDs: [{ name }],
|
|
||||||
});
|
|
||||||
const priv = await openpgp.readKey({ armoredKey: keys.privateKey });
|
|
||||||
const pub = await openpgp.readKey({ armoredKey: keys.publicKey });
|
|
||||||
window.keys = { priv, pub };
|
|
||||||
localStorage.setItem("keys", JSON.stringify(keys));
|
|
||||||
localStorage.setItem("name", name);
|
|
||||||
window.name = name;
|
|
||||||
window.socket.emit("create_user", { name, pubkey: keys.publicKey });
|
|
||||||
}
|
|
||||||
|
|
||||||
async function message(e) {
|
|
||||||
e.preventDefault();
|
|
||||||
const msg = document.getElementById("msg").value;
|
|
||||||
if (!msg) return;
|
|
||||||
window.socket.emit("send_message", {
|
|
||||||
message: msg,
|
|
||||||
thread: window.currentThreadId,
|
|
||||||
});
|
|
||||||
document.getElementById("msg").value = "";
|
|
||||||
const el = document.createElement("div");
|
|
||||||
el.classList.add("message");
|
|
||||||
el.innerHTML = `<strong>${window.name}: </strong>${msg}`;
|
|
||||||
document.getElementById("messages").appendChild(el);
|
|
||||||
}
|
|
||||||
|
|
||||||
function startThreadPicker() {
|
|
||||||
document.getElementById("chat").classList.add("hidden");
|
|
||||||
document.getElementById("threads").classList.remove("hidden");
|
|
||||||
window.socket.emit("list_threads");
|
|
||||||
}
|
|
||||||
|
|
||||||
function chooseThread(thread) {
|
function chooseThread(thread) {
|
||||||
window.currentThreadId = thread.id;
|
window.currentThreadId = thread.id;
|
||||||
window.earliestMessage = null;
|
window.earliestMessage = null;
|
||||||
|
@ -63,14 +26,6 @@ function chooseThread(thread) {
|
||||||
document.getElementById("chat").classList.remove("hidden");
|
document.getElementById("chat").classList.remove("hidden");
|
||||||
document.getElementById("messages").innerHTML = "";
|
document.getElementById("messages").innerHTML = "";
|
||||||
document.getElementById("threadname").innerHTML = thread.name;
|
document.getElementById("threadname").innerHTML = thread.name;
|
||||||
document.getElementById("threads").classList.add("hidden");
|
|
||||||
}
|
|
||||||
|
|
||||||
function createThread(e) {
|
|
||||||
e.preventDefault();
|
|
||||||
window.socket.emit("create_thread", {
|
|
||||||
name: document.getElementById("newthreadname").value,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async function loadKeys(keys) {
|
async function loadKeys(keys) {
|
||||||
|
@ -80,13 +35,6 @@ async function loadKeys(keys) {
|
||||||
await auth();
|
await auth();
|
||||||
}
|
}
|
||||||
|
|
||||||
async function loadMessages() {
|
|
||||||
window.socket.emit(
|
|
||||||
"get_history",
|
|
||||||
{ before: window.earliestMessage, thread: window.currentThreadId }
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
window.onload = () => {
|
window.onload = () => {
|
||||||
window.currentThreadId = 1;
|
window.currentThreadId = 1;
|
||||||
window.socket = io();
|
window.socket = io();
|
||||||
|
@ -121,7 +69,9 @@ window.onload = () => {
|
||||||
window.socket.on("authenticate", (msg) => {
|
window.socket.on("authenticate", (msg) => {
|
||||||
if (msg.success) {
|
if (msg.success) {
|
||||||
document.getElementById("register").classList.add("hidden");
|
document.getElementById("register").classList.add("hidden");
|
||||||
|
document.getElementById("threads").classList.remove("hidden");
|
||||||
document.getElementById("chat").classList.remove("hidden");
|
document.getElementById("chat").classList.remove("hidden");
|
||||||
|
window.socket.emit("list_threads");
|
||||||
}
|
}
|
||||||
let emitter = window.socket.emit;
|
let emitter = window.socket.emit;
|
||||||
window.socket.emit = (type, data) => {
|
window.socket.emit = (type, data) => {
|
||||||
|
@ -133,9 +83,7 @@ window.onload = () => {
|
||||||
else return emitter.call(window.socket, type);
|
else return emitter.call(window.socket, type);
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
window.socket.on("list_threads", (msg) => {
|
function addThread(thread) {
|
||||||
document.getElementById("threadlist").innerHTML = "";
|
|
||||||
for (let thread of msg.threads) {
|
|
||||||
const el = document.createElement("div");
|
const el = document.createElement("div");
|
||||||
el.classList.add("thread");
|
el.classList.add("thread");
|
||||||
el.innerHTML = thread.name;
|
el.innerHTML = thread.name;
|
||||||
|
@ -145,7 +93,12 @@ window.onload = () => {
|
||||||
el.appendChild(btn);
|
el.appendChild(btn);
|
||||||
document.getElementById("threadlist").appendChild(el);
|
document.getElementById("threadlist").appendChild(el);
|
||||||
}
|
}
|
||||||
|
window.socket.on("list_threads", (msg) => {
|
||||||
|
document.getElementById("threadlist").innerHTML = "";
|
||||||
|
for (let thread of msg.threads)
|
||||||
|
addThread(thread);
|
||||||
});
|
});
|
||||||
|
window.socket.on('new_thread', addThread);
|
||||||
window.socket.on("create_thread", (msg) => {
|
window.socket.on("create_thread", (msg) => {
|
||||||
chooseThread({
|
chooseThread({
|
||||||
name: document.getElementById("newthreadname").value,
|
name: document.getElementById("newthreadname").value,
|
||||||
|
@ -153,6 +106,49 @@ window.onload = () => {
|
||||||
});
|
});
|
||||||
document.getElementById("newthreadname").value = "";
|
document.getElementById("newthreadname").value = "";
|
||||||
});
|
});
|
||||||
|
|
||||||
|
document.getElementById("registerform").onsubmit = async e => {
|
||||||
|
e.preventDefault();
|
||||||
|
const name = document.getElementById("name").value;
|
||||||
|
if (!name) return;
|
||||||
|
const keys = await openpgp.generateKey({
|
||||||
|
userIDs: [{ name }],
|
||||||
|
});
|
||||||
|
const priv = await openpgp.readKey({ armoredKey: keys.privateKey });
|
||||||
|
const pub = await openpgp.readKey({ armoredKey: keys.publicKey });
|
||||||
|
window.keys = { priv, pub };
|
||||||
|
localStorage.setItem("keys", JSON.stringify(keys));
|
||||||
|
localStorage.setItem("name", name);
|
||||||
|
window.name = name;
|
||||||
|
window.socket.emit("create_user", { name, pubkey: keys.publicKey });
|
||||||
|
};
|
||||||
|
document.getElementById("msginput").onsubmit = e => {
|
||||||
|
e.preventDefault();
|
||||||
|
const msg = document.getElementById("msg").value;
|
||||||
|
if (!msg) return;
|
||||||
|
window.socket.emit("send_message", {
|
||||||
|
message: msg,
|
||||||
|
thread: window.currentThreadId,
|
||||||
|
});
|
||||||
|
document.getElementById("msg").value = "";
|
||||||
|
const el = document.createElement("div");
|
||||||
|
el.classList.add("message");
|
||||||
|
el.innerHTML = `<strong>${window.name}: </strong>${msg}`;
|
||||||
|
document.getElementById("messages").appendChild(el);
|
||||||
|
};
|
||||||
|
document.getElementById("loadmore").onclick = e => {
|
||||||
|
window.socket.emit(
|
||||||
|
"get_history",
|
||||||
|
{ before: window.earliestMessage, thread: window.currentThreadId }
|
||||||
|
);
|
||||||
|
};
|
||||||
|
document.getElementById("createthread").onsubmit = e => {
|
||||||
|
e.preventDefault();
|
||||||
|
window.socket.emit("create_thread", {
|
||||||
|
name: document.getElementById("newthreadname").value,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
const keys = localStorage.getItem("keys");
|
const keys = localStorage.getItem("keys");
|
||||||
if (keys) {
|
if (keys) {
|
||||||
window.name = localStorage.getItem("name");
|
window.name = localStorage.getItem("name");
|
||||||
|
@ -160,9 +156,4 @@ window.onload = () => {
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
document.getElementById("register").classList.remove("hidden");
|
document.getElementById("register").classList.remove("hidden");
|
||||||
document.getElementById("registerform").onsubmit = register;
|
|
||||||
document.getElementById("msginput").onsubmit = message;
|
|
||||||
document.getElementById("loadmore").onclick = loadMessages;
|
|
||||||
document.getElementById("change").onclick = startThreadPicker;
|
|
||||||
document.getElementById("createthread").onsubmit = createThread;
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -15,6 +15,15 @@
|
||||||
background: #020202;
|
background: #020202;
|
||||||
color: #eaeaea;
|
color: #eaeaea;
|
||||||
}
|
}
|
||||||
|
body {
|
||||||
|
display: flex;
|
||||||
|
align-items: stretch;
|
||||||
|
margin: 0;
|
||||||
|
min-width: min-content;
|
||||||
|
}
|
||||||
|
.column {
|
||||||
|
flex-grow: 1;
|
||||||
|
}
|
||||||
button {
|
button {
|
||||||
border-color: #767676;
|
border-color: #767676;
|
||||||
}
|
}
|
||||||
|
@ -50,8 +59,19 @@
|
||||||
<button id="submit" type="submit">generate keys & register</button>
|
<button id="submit" type="submit">generate keys & register</button>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
<div id="chat" class="hidden">
|
<div id="threads" class="column hidden">
|
||||||
<h1>vybe</h1>
|
<h1>vybe</h1>
|
||||||
|
<h1>threads</h1>
|
||||||
|
<h3>create thread</h3>
|
||||||
|
<form id="createthread">
|
||||||
|
<label for="newthreadname">thread name</label>
|
||||||
|
<input type="text" id="newthreadname" />
|
||||||
|
<button id="submitthread" type="submit">create</button>
|
||||||
|
</form>
|
||||||
|
<h3>choose existing thread</h3>
|
||||||
|
<div id="threadlist">loading...</div>
|
||||||
|
</div>
|
||||||
|
<div id="chat" class="column hidden">
|
||||||
<h3 class="thread">
|
<h3 class="thread">
|
||||||
current thread: <strong id="threadname">meow</strong>
|
current thread: <strong id="threadname">meow</strong>
|
||||||
<button id="change">change thread</button>
|
<button id="change">change thread</button>
|
||||||
|
@ -64,17 +84,6 @@
|
||||||
<button type="submit" class="hidden" id="sendmsg"></button>
|
<button type="submit" class="hidden" id="sendmsg"></button>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
<div id="threads" class="hidden">
|
|
||||||
<h1>threads</h1>
|
|
||||||
<h3>create thread</h3>
|
|
||||||
<form id="createthread">
|
|
||||||
<label for="newthreadname">thread name</label>
|
|
||||||
<input type="text" id="newthreadname" />
|
|
||||||
<button id="submitthread" type="submit">create</button>
|
|
||||||
</form>
|
|
||||||
<h3>choose existing thread</h3>
|
|
||||||
<div id="threadlist">loading...</div>
|
|
||||||
</div>
|
|
||||||
<script src="/openpgp.min.js"></script>
|
<script src="/openpgp.min.js"></script>
|
||||||
<script src="/chat.js"></script>
|
<script src="/chat.js"></script>
|
||||||
<script src="/socket.io.min.v4.6.1.js"></script>
|
<script src="/socket.io.min.v4.6.1.js"></script>
|
||||||
|
|
2
index.js
2
index.js
|
@ -17,7 +17,7 @@ const actions = require("./src/actions");
|
||||||
io.on("connection", (socket) => {
|
io.on("connection", (socket) => {
|
||||||
for (let action in actions) {
|
for (let action in actions) {
|
||||||
socket.on(action, (msg) =>
|
socket.on(action, (msg) =>
|
||||||
actions[action](msg, (response) => socket.emit(action, response), socket)
|
actions[action](msg, (response) => socket.emit(action, response), socket, io)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
const db = require("../db");
|
const db = require("../db");
|
||||||
|
|
||||||
const authwrap = (fn) => async (msg, respond, socket) => {
|
const authwrap = (fn) => async (msg, respond, socket, io) => {
|
||||||
if (!msg.__session) {
|
if (!msg.__session) {
|
||||||
return respond({
|
return respond({
|
||||||
success: false,
|
success: false,
|
||||||
|
@ -19,7 +19,7 @@ const authwrap = (fn) => async (msg, respond, socket) => {
|
||||||
message: "User not found",
|
message: "User not found",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return await fn({ ...msg, auth_user: result.rows[0] }, respond, socket);
|
return await fn({ ...msg, auth_user: result.rows[0] }, respond, socket, io);
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = authwrap;
|
module.exports = authwrap;
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
const db = require("../db");
|
const db = require("../db");
|
||||||
const authwrap = require("./authwrap");
|
const authwrap = require("./authwrap");
|
||||||
|
|
||||||
const create_thread = async (msg, respond) => {
|
const create_thread = async (msg, respond, socket, io) => {
|
||||||
// validate inputs
|
// validate inputs
|
||||||
if (!msg.name) {
|
if (!msg.name) {
|
||||||
return respond({
|
return respond({
|
||||||
|
@ -14,6 +14,10 @@ const create_thread = async (msg, respond) => {
|
||||||
"insert into threads (name, creator) values (?, ?) returning id",
|
"insert into threads (name, creator) values (?, ?) returning id",
|
||||||
[msg.name, msg.auth_user.id]
|
[msg.name, msg.auth_user.id]
|
||||||
);
|
);
|
||||||
|
io.emit('new_thread', {
|
||||||
|
name: msg.name,
|
||||||
|
id: insert.rows[0].id
|
||||||
|
});
|
||||||
// respond
|
// respond
|
||||||
return respond({
|
return respond({
|
||||||
success: true,
|
success: true,
|
||||||
|
|
Loading…
Reference in New Issue