Files
coms/client/public/data.js
2026-03-11 01:20:31 -04:00

208 lines
4.2 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { notifyNotice } from "./notifications.js";
// Clients own session ID.
let myId = null;
// Map of all messages and notices by ID (string IDs).
const threads = new Map();
// Map of connected users by unique ID.
const users = new Map();
// Ordered list of rootlevel IDs (messages and notices, stored as strings).
const rootIds = [];
// Negative counter to generate unique IDs for notices.
let noticeCounter = -1;
// ID of the message were currently replying to (string or null).
let replyTo = null;
// ID of the message currently focused for navigation (string or null).
let focusedId = null;
// Set the focused message ID (or null to clear).
function setFocused(id) {
focusedId = id;
}
// Get the currently focused message ID.
function getFocused() {
return focusedId;
}
function clearFocused() {
focusedId = null;
}
// USER MANAGEMENT STUFF.
/**
* Register a user with their unique ID.
* @param {string} id
* @param {string} name
*/
function addUser(id, name) {
users.set(id, name);
}
/**
* Remove a user by their ID.
* @param {string} id
*/
function removeUser(id) {
users.delete(id);
}
/**
* Update a users name.
* @param {string} id
* @param {string} name
*/
function updateUser(id, name) {
users.set(id, name);
}
/**
* Get a list of {id, name} objects for all users.
* @returns {{id:string, name:string}[]}
*/
function getUsers() {
return Array.from(users.entries()).map(([id, name]) => ({ id, name }));
}
/**
* Get grouped display strings: e.g. ["Anon (3x)", "Alice (1x)"]
* @returns {string[]}
*/
function getGroupedUsers() {
const counts = {};
for (const name of users.values()) {
counts[name] = (counts[name] || 0) + 1;
}
return Object.entries(counts).map(([name, count]) => {
const nameSpan = `<span class="name">${new Option(name).innerHTML}</span>`;
return count > 1 ? `${nameSpan} (${count}x)` : nameSpan;
});
}
/**
* Add a new chat message to the thread structure.
* @param {{id: string|number, username: string, content: string, ts: number, parent?: string|number|null, authorId?: string|number|null}} msg
*/
function addMessage({
id,
username,
content,
ts,
parent = null,
authorId = null,
}) {
const sid = String(id);
const sparent = parent === null ? null : String(parent);
threads.set(sid, {
id: sid,
username,
authorId: authorId === null ? null : String(authorId),
content,
ts,
parent: sparent,
children: [],
});
if (sparent !== null && threads.has(sparent)) {
threads.get(sparent).children.push(sid);
} else {
rootIds.push(sid);
}
}
/**
* Insert a system notice as a rootlevel thread item.
* @param {string} content — HTML or plain text for the notice
* @param {boolean} [shouldNotify=true] — whether to trigger a browser notification
*/
function addNotice(content, shouldNotify = true) {
const ts = Math.floor(Date.now() / 1000);
const id = String(noticeCounter--);
threads.set(id, {
id,
username: "",
content,
ts,
parent: null,
children: [],
});
rootIds.push(id);
if (shouldNotify) notifyNotice(content);
}
/**
* Reset all data (useful for unit tests or full reinitialization).
*/
function clearData() {
threads.clear();
rootIds.length = 0;
noticeCounter = -1;
replyTo = null;
users.clear();
}
/** @returns {Map<string,object>} The threads map. */
function getThreads() {
return threads;
}
/** @returns {string[]} The ordered list of rootlevel IDs. */
function getRootIds() {
return rootIds;
}
/**
* Set this clients own session ID.
* @param {string|number} id
*/
function setMyId(id) {
myId = String(id);
}
/**
* Get this clients own session ID.
* @returns {string|null}
*/
function getMyId() {
return myId;
}
/** @returns {string|null} The current replyto ID. */
function getReplyTo() {
return replyTo;
}
/** @param {string|null} id — Set the current replyto ID. */
function setReplyTo(id) {
replyTo = id;
}
export {
threads,
rootIds,
users,
addMessage,
addNotice,
addUser,
removeUser,
updateUser,
getUsers,
getGroupedUsers,
clearData,
getThreads,
getRootIds,
getReplyTo,
setReplyTo,
getFocused,
setFocused,
clearFocused,
setMyId,
getMyId,
};