fixed up the frontend display for the local messages
Some checks failed
Release / release (ubuntu-22.04) (push) Has been cancelled
Release / release (windows-latest) (push) Has been cancelled

This commit is contained in:
2026-04-19 02:04:54 -04:00
parent 3c3118c74d
commit c7cb73b360
5 changed files with 76 additions and 25 deletions

View File

@@ -1,6 +1,6 @@
{ {
"name": "oxyde", "name": "oxyde",
"version": "0.1.1", "version": "0.1.3",
"description": "A simple Tauri chat app, built with rust, vite, and surrealdb", "description": "A simple Tauri chat app, built with rust, vite, and surrealdb",
"type": "module", "type": "module",
"scripts": { "scripts": {

2
src-tauri/Cargo.lock generated
View File

@@ -3824,7 +3824,7 @@ dependencies = [
[[package]] [[package]]
name = "oxyde" name = "oxyde"
version = "0.1.1" version = "0.1.3"
dependencies = [ dependencies = [
"futures-util", "futures-util",
"serde", "serde",

View File

@@ -1,6 +1,6 @@
[package] [package]
name = "oxyde" name = "oxyde"
version = "0.1.1" version = "0.1.3"
description = "A simple Tauri chat app, built with rust, vite, and surrealdb" description = "A simple Tauri chat app, built with rust, vite, and surrealdb"
authors = ["qdust41"] authors = ["qdust41"]
edition = "2021" edition = "2021"

View File

@@ -1,7 +1,7 @@
{ {
"$schema": "https://schema.tauri.app/config/2", "$schema": "https://schema.tauri.app/config/2",
"productName": "oxyde", "productName": "oxyde",
"version": "0.1.1", "version": "0.1.3",
"identifier": "com.jimweaver.oxyde", "identifier": "com.jimweaver.oxyde",
"build": { "build": {
"beforeDevCommand": "pnpm dev", "beforeDevCommand": "pnpm dev",

View File

@@ -26,6 +26,7 @@
let hasOlderMessages = $state(false); let hasOlderMessages = $state(false);
let isLoadingOlder = $state(false); let isLoadingOlder = $state(false);
let unreadCounts = $state<Record<string, number>>({}); let unreadCounts = $state<Record<string, number>>({});
let roomSelectionToken = 0;
let view = $state<"loading" | "auth" | "app">("loading"); let view = $state<"loading" | "auth" | "app">("loading");
let authMode = $state<"signin" | "signup">("signin"); let authMode = $state<"signin" | "signup">("signin");
@@ -101,6 +102,7 @@
} }
async function signout() { async function signout() {
roomSelectionToken += 1;
await cmd("signout").catch(() => {}); await cmd("signout").catch(() => {});
if (subId) { if (subId) {
await cmd("unsubscribe_room", { subId }).catch(() => {}); await cmd("unsubscribe_room", { subId }).catch(() => {});
@@ -119,42 +121,72 @@
} }
// ─── Rooms ──────────────────────────────────────────────────────────────── // ─── Rooms ────────────────────────────────────────────────────────────────
function isCurrentRoomSelection(token: number, roomId: string) {
return (
token === roomSelectionToken &&
activeRoom !== null &&
sid(activeRoom.id) === roomId
);
}
function onlyRoomMessages(roomId: string, source: Message[]) {
return source.filter((message) => sid(message.room) === roomId);
}
async function loadRooms() { async function loadRooms() {
rooms = await cmd<Room[]>("get_rooms"); rooms = await cmd<Room[]>("get_rooms");
if (rooms.length && !activeRoom) await selectRoom(rooms[0]); if (rooms.length && !activeRoom) await selectRoom(rooms[0]);
} }
async function selectRoom(room: Room) { async function selectRoom(room: Room) {
if (subId) { const token = ++roomSelectionToken;
await cmd("unsubscribe_room", { subId }).catch(() => {}); const roomId = sid(room.id);
subId = null; const previousSubId = subId;
} const previousUnlisten = unlisten;
if (unlisten) {
unlisten(); subId = null;
unlisten = null; unlisten = null;
}
activeRoom = room; activeRoom = room;
messages = [];
hasOlderMessages = false;
isLoadingOlder = false;
replyTo = null; replyTo = null;
const cached = await cmd<Message[]>("get_cached_messages", { roomId: sid(room.id) }); if (previousSubId) {
await cmd("unsubscribe_room", { subId: previousSubId }).catch(() => {});
}
if (previousUnlisten) {
previousUnlisten();
}
if (token !== roomSelectionToken) return;
const cached = await cmd<Message[]>("get_cached_messages", { roomId });
if (!isCurrentRoomSelection(token, roomId)) return;
if (cached.length > 0) { if (cached.length > 0) {
messages = cached; messages = onlyRoomMessages(roomId, cached);
hasOlderMessages = false; hasOlderMessages = false;
} }
const fresh = await cmd<Message[]>("get_messages", { const fresh = await cmd<Message[]>("get_messages", {
roomId: sid(room.id), roomId,
limit: 50, limit: 50,
}); });
messages = fresh; if (!isCurrentRoomSelection(token, roomId)) return;
messages = onlyRoomMessages(roomId, fresh);
hasOlderMessages = fresh.length === 50; hasOlderMessages = fresh.length === 50;
unreadCounts = { ...unreadCounts, [sid(room.id)]: 0 }; unreadCounts = { ...unreadCounts, [roomId]: 0 };
await cmd("mark_room_read", { roomId: sid(room.id) }).catch(() => {}); await cmd("mark_room_read", { roomId }).catch(() => {});
if (!isCurrentRoomSelection(token, roomId)) return;
subId = await cmd<string>("subscribe_room", { roomId: sid(room.id) }); const nextSubId = await cmd<string>("subscribe_room", { roomId });
if (!isCurrentRoomSelection(token, roomId)) {
await cmd("unsubscribe_room", { subId: nextSubId }).catch(() => {});
return;
}
subId = nextSubId;
const { listen } = await import("@tauri-apps/api/event"); const { listen } = await import("@tauri-apps/api/event");
unlisten = await listen<LiveEvent>("chat:message", ({ payload }) => { const nextUnlisten = await listen<LiveEvent>("chat:message", ({ payload }) => {
const { action, data } = payload; const { action, data } = payload;
const eventRoomId = sid(data.room); const eventRoomId = sid(data.room);
const currentRoomId = activeRoom ? sid(activeRoom.id) : ""; const currentRoomId = activeRoom ? sid(activeRoom.id) : "";
@@ -185,6 +217,15 @@
} }
cmd("mark_room_read", { roomId: currentRoomId }).catch(() => {}); cmd("mark_room_read", { roomId: currentRoomId }).catch(() => {});
}); });
if (!isCurrentRoomSelection(token, roomId)) {
nextUnlisten();
if (subId === nextSubId) {
await cmd("unsubscribe_room", { subId: nextSubId }).catch(() => {});
subId = null;
}
return;
}
unlisten = nextUnlisten;
} }
async function loadOlderMessages() { async function loadOlderMessages() {
@@ -195,19 +236,24 @@
messages.length === 0 messages.length === 0
) )
return; return;
const roomId = sid(activeRoom.id);
const token = roomSelectionToken;
isLoadingOlder = true; isLoadingOlder = true;
try { try {
const older = await cmd<Message[]>("get_messages", { const older = await cmd<Message[]>("get_messages", {
roomId: sid(activeRoom.id), roomId,
before: messages[0].created, before: messages[0].created,
limit: 50, limit: 50,
}); });
messages = [...older, ...messages]; if (!isCurrentRoomSelection(token, roomId)) return;
messages = [...onlyRoomMessages(roomId, older), ...messages];
hasOlderMessages = older.length === 50; hasOlderMessages = older.length === 50;
} catch (e) { } catch (e) {
err = String(e); err = String(e);
} finally { } finally {
isLoadingOlder = false; if (isCurrentRoomSelection(token, roomId)) {
isLoadingOlder = false;
}
} }
} }
@@ -275,10 +321,15 @@
try { try {
await cmd("toggle_reaction", { messageId: msgId, emoji }); await cmd("toggle_reaction", { messageId: msgId, emoji });
if (activeRoom) { if (activeRoom) {
messages = await cmd<Message[]>("get_messages", { const roomId = sid(activeRoom.id);
roomId: sid(activeRoom.id), const token = roomSelectionToken;
const refreshed = await cmd<Message[]>("get_messages", {
roomId,
limit: Math.max(50, Math.min(messages.length, 100)), limit: Math.max(50, Math.min(messages.length, 100)),
}); });
if (isCurrentRoomSelection(token, roomId)) {
messages = onlyRoomMessages(roomId, refreshed);
}
} }
} catch (e) { } catch (e) {
err = String(e); err = String(e);