Commit Graph

2 Commits

Author SHA1 Message Date
Disco DeDisco
0693a422d2 my-sea: second spectate broadcast — seat ring updates live on deposit / BYE — TDD
Extends the async-witness WS so a visitor joining (deposit) or leaving (BYE)
pushes the seat ring to the other watchers — they see members come + go without
a refresh, same channel as the live draw.

- views.py: `_my_sea_seats(owner)` extracted (owner 1C + present invitees 2C-6C
  by deposit order, sans per-viewer is_self) — used by BOTH the my_sea_visit
  render (layers is_self on) AND a new guarded `_notify_sea_seats(owner_id)`
  broadcast. Fired from my_sea_visit_insert_token (seat taken) +
  my_sea_visit_leave (seat freed).
- consumers.py: MySeaSpectateConsumer gains a `sea_seats` handler.
- my_sea_visit.html: the WS client re-renders the `.table-seat` ring from a
  `sea_seats` message, re-marking the viewer's own --self chair via the embedded
  seat token + re-firing the one-shot seated glow (localStorage-gated).

Tests: +1 channels relay IT (sea_seats received) + 2 view ITs (deposit / BYE
each broadcast the ring). Existing multi-seat ITs stay green on the refactored
helper. Client re-render needs live 3-party verification on staging.

Code architected by Disco DeDisco <discodedisco@outlook.com>
Git commit message Co-Authored-By:
Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-29 23:42:22 -04:00
Disco DeDisco
01ee8dc1fb my-sea: async witness — spectators see the owner's draw land live via WS, no refresh — TDD
The bud watching @owner's sea now sees each card appear in real time instead of
having to refresh. Follows the epic RoomConsumer broadcast pattern (view ->
group_send -> consumer handler -> send_json), keyed on the owner (mysea_<owner>)
since my-sea has no Room.

- apps/gameboard/consumers.py: MySeaSpectateConsumer — read-only WS; membership
  gate matches voice (owner OR present invitee: ACCEPTED + deposited + not
  left). Relays a `sea_draw` event carrying the owner's full hand.
- apps/gameboard/routing.py + core/asgi.py: ws/my-sea-spectate/<owner_id>/.
- gameboard/views.py: _notify_sea_draw(owner_id, hand) — best-effort, guarded
  group_send so a down/missing channel layer can't break the solo draw. Fired
  from my_sea_lock (both the create + the mid-draw-upsert branch) and from
  my_sea_delete (empty hand -> clears the spectators' cross).
- my_sea_visit.html: a WS listener fills the cross live — SeaDeal.register(card,
  '.sea-pos-'+pos, isLevity) reuses _fillSlot (incl. the --rank-long squeeze) +
  seeds the slot clickable into the stage; a DEL re-empties cleared slots.
  Capped reconnect for transient blips.

Tests: 5 channels ITs (owner/present-invitee connect + receive; unauth /
stranger / accepted-not-present rejected); +2 view ITs (lock broadcasts owner+
hand; lock still 200s when the broadcast raises). Client fill needs live
two-party verification on staging (Redis up).

Code architected by Disco DeDisco <discodedisco@outlook.com>
Git commit message Co-Authored-By:
Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-29 23:14:48 -04:00