From a7f3df93468e07eaefcaa6b9307127afee00aac2 Mon Sep 17 00:00:00 2001 From: Ilia Denisov Date: Wed, 17 Jun 2026 11:14:25 +0200 Subject: [PATCH] fix(chat): don't restore unread on a failed read-ack (would loop the in-game effect; REST re-seed self-heals) --- ui/src/lib/app.svelte.ts | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/ui/src/lib/app.svelte.ts b/ui/src/lib/app.svelte.ts index 0dc571a..c1e529f 100644 --- a/ui/src/lib/app.svelte.ts +++ b/ui/src/lib/app.svelte.ts @@ -166,14 +166,15 @@ export function seedChatUnread(gameId: string, unread: boolean): void { * markChatRead clears a game's unread badge and tells the backend the player has read the chat — * called when the move history or the chat opens. It hits the backend only when something is * actually unread, so opening the history does not call the backend on every tap. The clear is - * optimistic; a failed ack restores the badge so a later open retries. + * optimistic and the ack is best-effort: a failed ack leaves the server bit set, which the next + * authoritative REST view (lobby list / game state) re-seeds, so the badge self-heals — it is + * deliberately not restored here, since the in-game effect re-runs while the history is shown and + * a restore would loop on a persistently failing ack. */ export function markChatRead(gameId: string): void { if (!app.chatUnread[gameId]) return; app.chatUnread = { ...app.chatUnread, [gameId]: false }; - void gateway.markChatRead(gameId).catch(() => { - app.chatUnread = { ...app.chatUnread, [gameId]: true }; - }); + void gateway.markChatRead(gameId).catch(() => {}); } /** handleError maps a GatewayError to a toast; an invalid session logs out. A connectivity