Files
uniweb/web/src
egutierrez 5fbf319172 feat(uniweb): sidebar shows the real last message and time per room
The sidebar showed room.lastTs/lastMessage that busService created as 0/""
on every load, so the time rendered as the epoch-0 "01:00" and there was no
preview. busService now owns a room store that keeps these fields live.

- busService gains a room store: the room list plus a per-room metadata
  subscription. Since the wire has no message history (NATS delivers live
  only), staying subscribed to every room is the only way to know each room's
  latest message and to count unread for rooms the user is not viewing. Each
  delivered message updates the room's lastTs, lastMessage (a "name: body"
  preview, truncated, reusing the directory resolver) and bumps unread when
  the room is not active.
- New surface: watchRooms(listener) to mirror the store into React,
  loadRooms() to (re)populate and subscribe, setActiveRoom(id) to clear a
  room's unread. createRoom adds the new room to the store and, because its
  data-plane refresh() drops all subscriptions, re-subscribes every room.
  subscribeRoom now shares the same decode core (subscribeRoomInternal) used
  by the metadata subscription. The store is reset on login/logout.
- ChatShell mirrors the store via watchRooms instead of a one-shot listRooms,
  selects a room through setActiveRoom (clearing its unread), and auto-selects
  the first room once the list loads.
- Sidebar: timeShort renders an em dash for a room with no message yet instead
  of the epoch-0 "01:00".

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-14 15:31:08 +02:00
..