Chat history.

This commit is contained in:
2026-02-14 22:29:32 -05:00
parent 766510132b
commit 2e8672fc9e
3 changed files with 47 additions and 2 deletions

View File

@@ -31,8 +31,8 @@
<div id="bottom_text"> <div id="bottom_text">
<i>COMS</i> by Jacob Signorovitch. <i>COMS</i> by Jacob Signorovitch.
<a href="#" id="help">Help</a> | <a href="#" id="help">Help</a> |
<a href="//signorovitch.org">Code</a> | <a href="//git.signorovitch.org/jacob/coms">Code</a> |
<a href="//signorovitch.org">API</a> <a href="#">API</a>
</div> </div>
</div> </div>
</div> </div>

View File

@@ -12,6 +12,7 @@ import {
updateUser, updateUser,
getGroupedUsers, getGroupedUsers,
setMyId, setMyId,
clearData,
users, users,
setFocused, setFocused,
setReplyTo, setReplyTo,
@@ -49,11 +50,25 @@ export function initWebSocket(username, chatEl, inputContainer, usersListEl) {
case "welcome": { case "welcome": {
// Initial user list. // Initial user list.
const myId = packet.data.you; const myId = packet.data.you;
clearData();
setMyId(myId); setMyId(myId);
const users = packet.data.users || []; const users = packet.data.users || [];
users.forEach(({ id, username }) => addUser(id, username)); users.forEach(({ id, username }) => addUser(id, username));
const groups = getGroupedUsers(); const groups = getGroupedUsers();
usersListEl.innerHTML = "Online: " + groups.join(", "); usersListEl.innerHTML = "Online: " + groups.join(", ");
// Replay chat history.
const history = packet.data.history || [];
history.forEach((raw) => {
try {
const histPkt = JSON.parse(raw);
if (histPkt.type === "msg-event") {
const { id, username: u, content, ts, parent } = histPkt.data;
addMessage({ id, username: u, content, ts, parent });
}
} catch (e) {
console.error("Invalid history entry", raw);
}
});
//addNotice(`<i>Users online: ${groups.join(", ")}</i>`); //addNotice(`<i>Users online: ${groups.join(", ")}</i>`);
break; break;
} }

View File

@@ -12,6 +12,13 @@
static size_t next_msg_id = 1; static size_t next_msg_id = 1;
// History buffer for last 100 messages.
#define HISTORY_SIZE 100
static char* history[HISTORY_SIZE];
static size_t history_len[HISTORY_SIZE];
static size_t history_pos = 0;
static size_t history_count = 0;
#define CHAT_BUF_SIZE SESSION_CHAT_BUF_SIZE #define CHAT_BUF_SIZE SESSION_CHAT_BUF_SIZE
/* /*
@@ -92,6 +99,7 @@ int cb_chat(
if (session_has_username(s)) { if (session_has_username(s)) {
yyjson_mut_val* uobj = yyjson_mut_obj(wdoc); yyjson_mut_val* uobj = yyjson_mut_obj(wdoc);
yyjson_mut_arr_add_val(wusers, uobj); yyjson_mut_arr_add_val(wusers, uobj);
yyjson_mut_arr_add_val(wusers, uobj);
yyjson_mut_obj_add_uint( yyjson_mut_obj_add_uint(
wdoc, uobj, "id", session_get_id(s) wdoc, uobj, "id", session_get_id(s)
); );
@@ -100,6 +108,19 @@ int cb_chat(
); );
} }
} }
// Include last 100 messages in the welcome history array.
yyjson_mut_val* whist = yyjson_mut_arr(wdoc);
yyjson_mut_obj_add_val(wdoc, wdata, "history", whist);
for (size_t i = 0; i < history_count; ++i) {
size_t idx =
(history_pos + HISTORY_SIZE - history_count + i) %
HISTORY_SIZE;
// Append raw JSON string into history array.
yyjson_mut_val* raw = yyjson_mut_strn(
wdoc, history[idx], history_len[idx]
);
yyjson_mut_arr_add_val(whist, raw);
}
size_t out_len; size_t out_len;
char* out = yyjson_mut_write(wdoc, 0, &out_len); char* out = yyjson_mut_write(wdoc, 0, &out_len);
@@ -291,6 +312,15 @@ int cb_chat(
size_t out_len; size_t out_len;
char* out = yyjson_mut_write(mdoc, 0, &out_len); char* out = yyjson_mut_write(mdoc, 0, &out_len);
/* Store this msg-event JSON in the circular history buffer */
if (history_count == HISTORY_SIZE) {
free(history[history_pos]);
} else {
history_count++;
}
history[history_pos] = strdup(out);
history_len[history_pos] = out_len;
history_pos = (history_pos + 1) % HISTORY_SIZE;
size_t copy_len = out_len < SESSION_CHAT_BUF_SIZE size_t copy_len = out_len < SESSION_CHAT_BUF_SIZE
? out_len ? out_len
: SESSION_CHAT_BUF_SIZE; : SESSION_CHAT_BUF_SIZE;