Fix desktop tray unread indicator: clear only on genuine room entry

The tray indicator must stay visible while a message is unread and
clear only when the user actually opens the room containing it --
never merely because the window was shown, focused, restored, or
opened from the tray.

Adds window.dsDesktop.roomOpened() (called exactly once per genuine
transition to a real room id, via useDesktopRoomBridge) and wires up
window.dsDesktop.setUnreadCount() (declared but never actually called
before this) to fire whenever the unread-room count changes. Both are
no-ops in browser builds, matching this bridge's existing optional-
chaining convention.

Frontend unread state stays authoritative -- clearRoomIndicators is
pulled out of ChatShellPage as a pure function (same behavior, now
directly testable) so opening one room only clears that room's
unread/mention flags, leaving every other room's state untouched.

Also adds a frontend test runner (vitest + React Testing Library) --
none existed in this project before. 10 new tests cover: roomOpened
firing once on entry, not refiring on an unrelated rerender with the
same room id, refiring on a genuine room-to-room transition, never
firing with no room id, setUnreadCount firing independently of
roomOpened, clearing one room preserving every other room's unread
state, and the desktop bridge remaining fully optional.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
ksmithandClaude Sonnet 5 committed 2026-09-28 17:21:45 -06:00
1 parent 047f47d524
commit 3349cadea2
9 files changed
+1155 -16

No files matched your search

+13
View File
@@ -0,0 +1,13 @@
import { defineConfig } from 'vitest/config'
import react from '@vitejs/plugin-react'
// Deliberately separate from vite.config.ts, not an extension of it -- that
// file's VitePWA plugin does real build-time work (service worker
// injection, manifest generation) that has nothing to do with running unit
// tests and would just slow every test run down for no benefit.
export default defineConfig({
plugins: [react()],
test: {
environment: 'jsdom',
},
})