Files
ds-chat/frontend
ksmithandClaude Sonnet 5 ccd92787d6 Send push notifications when the app is backgrounded, not just closed (#31)
Root cause (found earlier): the server only pushes to users it
believes are "connected" to a room, but that was a raw WebSocket-
connection check with no concept of whether the tab was actually
foregrounded -- a backgrounded-but-still-connected tab looked exactly
like someone actively watching, so the push got suppressed even
though nothing could surface on a hidden page.

No backend change needed: the server's presence tracking (and the
push-suppression logic built on it) was already correct for "not
joined to this room's channel" -- the gap was purely that the client
never told it about backgrounding. useChatSocket.ts now tracks
document.visibilityState and sends "leave" for every desired room
when hidden (without forgetting the app still wants them joined), and
"join" again when visible -- reusing the exact join/leave path a real
room switch already goes through, no new WS message type or backend
logic required.

Rejoining also triggers a message-history refetch in ChatPane (keyed
off the server's existing "joined" ack), so anything sent while
backgrounded gets backfilled instead of silently missing -- as a side
effect, this also fixes reconnect-after-a-dropped-connection never
backfilling either, which had the same gap.

Verified end-to-end: simulated backgrounding in the browser and
confirmed via direct Redis inspection that the room's presence hash
(what push-suppression actually reads) goes empty on hide and
repopulates with a message resync on show.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-16 15:58:39 -06:00
..

DS Chat frontend (Phase 1)

React + Vite PWA. Login, room list, and chat views wired to the backend's REST API and /ws/chat WebSocket endpoint. See ../README.md and ../backend/README.md for full local setup.

Dev

npm install
npm run dev

The dev server proxies /api and /ws to http://localhost:8000 (see vite.config.ts), so the backend must be running for anything beyond the login page to work.

Build

npm run build

Generates the PWA manifest and service worker via vite-plugin-pwa into dist/.

Layout

src/
  main.tsx, App.tsx        routes: /login, /rooms, /rooms/:roomId
  api/                       fetch wrappers (client, auth, rooms)
  ws/useChatSocket.ts          WebSocket hook (join/send/receive)
  context/AuthContext.tsx        current-user state, hydrated via GET /api/auth/me
  components/                      ProtectedRoute, RoomListItem, MessageList, MessageInput
  pages/                             LoginPage, RoomListPage, ChatRoomPage