Oh man that's a lot of changes.

This commit is contained in:
2026-02-28 15:59:03 -05:00
parent 226c4a8b52
commit de55288d37
11 changed files with 864 additions and 336 deletions

View File

@@ -9,6 +9,7 @@ import {
addNotice,
getReplyTo,
addUser,
removeUser,
updateUser,
getGroupedUsers,
setMyId,
@@ -39,8 +40,7 @@ export function initWebSocket(username, chatEl, inputContainer, usersListEl) {
socket.onopen = () => {
// Announce join.
socket.send(JSON.stringify({ type: "join", data: { username } }));
//addNotice(`Connected as <span class="name">${username}</span>`);
socket.send(JSON.stringify({ type: "join", data: { name: username } }));
renderChat(chatEl, inputContainer);
};
@@ -48,32 +48,60 @@ export function initWebSocket(username, chatEl, inputContainer, usersListEl) {
const packet = JSON.parse(event.data);
switch (packet.type) {
case "welcome": {
// Initial user list.
const myId = packet.data.you;
// Initial handshake. Populate ids, online list, and history if provided.
clearData();
setMyId(myId);
const users = packet.data.users || [];
users.forEach(({ id, username }) => addUser(id, username));
const { id, online = [], history = [] } = packet.data;
setMyId(String(id));
online.forEach(({ id: uid, name }) => addUser(String(uid), name));
history.forEach((m) => {
addMessage({
id: String(m.id),
username: m.author?.name || "Anon",
authorId: m.author?.id ? String(m.author.id) : null,
content: m.content,
ts: m.timestamp,
parent:
m.parent === null || m.parent === undefined || m.parent === "-1"
? null
: String(m.parent),
});
});
const groups = getGroupedUsers();
usersListEl.innerHTML = "Online: " + groups.join(", ");
//addNotice(`<i>Users online: ${groups.join(", ")}</i>`);
usersListEl.innerHTML = groups.length
? "Online: " + groups.join(", ")
: "Online: ?";
break;
}
case "join-event": {
case "join_evt": {
// A new user joined.
const { id, username } = packet.data;
addUser(id, username);
const { id, name } = packet.data;
addUser(String(id), name);
addNotice(
`<span class="name">${new Option(username).innerHTML}</span> joined.`,
`<span class="name">${new Option(name).innerHTML}</span> joined.`,
);
const groups = getGroupedUsers();
usersListEl.innerHTML = "Online: " + groups.join(", ");
break;
}
case "name-event": {
case "leave_evt": {
const { id, name } = packet.data;
const sid = String(id);
const lastName = users.get(sid) || name;
addNotice(
`<span class="name">${new Option(lastName).innerHTML}</span> left.`,
);
removeUser(sid);
const groups = getGroupedUsers();
usersListEl.innerHTML = "Online: " + groups.join(", ");
break;
}
case "name_evt": {
// A user changed name.
const { id, new: newName, old: oldName } = packet.data;
updateUser(id, newName);
const {
user: { id, name: oldName },
new_name: newName,
} = packet.data;
updateUser(String(id), newName);
addNotice(
`<span class="name">${new Option(oldName).innerHTML}</span> changed name to <span class="name">${new Option(newName).innerHTML}</span>`,
);
@@ -81,19 +109,53 @@ export function initWebSocket(username, chatEl, inputContainer, usersListEl) {
usersListEl.innerHTML = "Online: " + groups.join(", ");
break;
}
case "msg-event": {
case "msg_evt": {
// A chat message arrived.
const { id, username: u, content, ts, parent } = packet.data;
addMessage({ id, username: u, content, ts, parent });
const { id, author, content, parent, timestamp } = packet.data;
const username = author?.name || "Anon";
const ts = timestamp || Math.floor(Date.now() / 1000);
if (author?.id) addUser(String(author.id), username);
addMessage({
id: String(id),
username,
authorId: author?.id ? String(author.id) : null,
content,
ts,
parent:
parent === null || parent === undefined || parent === "-1"
? null
: String(parent),
});
break;
}
case "msg-ack": {
const { id } = packet.data;
if (getReplyTo() === null) {
setFocused(id);
setReplyTo(id);
case "msg_ack": {
const { status, id } = packet.data;
if (status !== "success") {
addNotice(
`<span class="err">Message failed: ${new Option(status).innerHTML}</span>`,
);
} else if (id) {
const replyTarget = getReplyTo();
if (replyTarget === null) {
const sid = String(id);
setFocused(sid);
setReplyTo(sid);
}
}
renderChat(chatEl, inputContainer);
break;
}
case "name_ack": {
const { status, name } = packet.data;
if (status !== "success") {
addNotice(
`<span class="err">Name change failed: ${new Option(status).innerHTML}</span>`,
);
}
break;
}
case "ping": {
const ts = packet.data?.ts ?? Math.floor(Date.now() / 1000);
socket.send(JSON.stringify({ type: "pong", data: { ts } }));
break;
}
default:
@@ -122,7 +184,12 @@ export function initWebSocket(username, chatEl, inputContainer, usersListEl) {
*/
function sendMessage(content) {
const parent = getReplyTo();
socket.send(JSON.stringify({ type: "msg", data: { content, parent } }));
socket.send(
JSON.stringify({
type: "msg",
data: { content, parent: parent == null ? -1 : parent },
}),
);
}
/**
@@ -130,7 +197,7 @@ export function initWebSocket(username, chatEl, inputContainer, usersListEl) {
* @param {string} username - The new username to set.
*/
function sendName(username) {
socket.send(JSON.stringify({ type: "name", data: { username } }));
socket.send(JSON.stringify({ type: "name", data: { name: username } }));
}
return { socket, sendMessage, sendName };