fix: replay channel state on SPA reconnect #61

Merged
sneak merged 7 commits from fix/spa-reconnect-channel-tabs into main 2026-03-10 11:08:13 +01:00

7 Commits

Author SHA1 Message Date
db9031448b Merge branch 'main' into fix/spa-reconnect-channel-tabs
All checks were successful
check / check (push) Successful in 1m3s
2026-03-10 11:06:45 +01:00
clawbot
aa746177e5 fix: decouple lint stage from web-builder in Dockerfile
All checks were successful
check / check (push) Successful in 5s
Remove COPY --from=web-builder from the lint stage so it can run
independently and fail fast. Create placeholder files for the
go:embed directive instead. The build stage still uses the real
SPA assets from web-builder.

Update README to reflect that lint no longer depends on web-builder.
2026-03-10 02:45:27 -07:00
user
91da9eb8c7 docs: update README project structure and Dockerfile description
All checks were successful
check / check (push) Successful in 4s
- Remove web/dist/ individual files from project structure (now generated
  at Docker build time, not committed)
- Add web/src/, build.sh, package.json, package-lock.json to structure
- Update Dockerfile description from two-stage to four-stage build
  (web-builder, lint, builder, final)
- Remove outdated example Dockerfile snippet
2026-03-09 17:35:19 -07:00
user
4b2888cb90 fix: remove build artifacts from repo, build SPA in Docker
All checks were successful
check / check (push) Successful in 4s
- Remove web/dist/ from git tracking (build output)
- Add web/dist/ to .gitignore
- Add Node.js web-builder stage to Dockerfile to compile SPA at build time
- Update REPO_POLICIES.md from upstream sneak/prompts (build artifacts policy)
2026-03-09 17:25:49 -07:00
78d657111b Rename replay → initChannelState
All checks were successful
check / check (push) Successful in 2m20s
Rename the query parameter, function, and all related comments
from 'replay' to 'initChannelState' to better reflect the
semantics: the server initializes channel state for the
reconnecting client rather than replaying past events.
2026-03-09 17:00:56 -07:00
user
096fb2b207 docs: document ?replay=1 query parameter for GET /state 2026-03-09 17:00:56 -07:00
user
737686006e fix: replay channel state on SPA reconnect
When a client reconnects to an existing session (e.g. browser tab
closed and reopened), the server now enqueues synthetic JOIN messages
plus TOPIC/NAMES numerics for every channel the session belongs to.
These are delivered only to the reconnecting client, not broadcast
to other users.

Server changes:
- Add replayChannelState() to handlers that enqueues per-channel
  JOIN + join-numerics (332/353/366) to a specific client.
- HandleState accepts ?replay=1 query parameter to trigger replay.
- HandleLogin (password auth) also replays channel state for the
  new client since it creates a fresh client for an existing session.

SPA changes:
- On resume, call /state?replay=1 instead of /state so the server
  enqueues channel state into the message queue.
- processMessage now creates channel tabs when receiving a JOIN
  where msg.from matches the current nick (handles both live joins
  and replayed joins on reconnect).
- onLogin no longer re-sends JOIN commands for saved channels on
  resume — the server handles it via the replay mechanism, avoiding
  spurious JOIN broadcasts to other channel members.

Closes #60
2026-03-09 17:00:56 -07:00