Repository navigation
Room chat stage 3: chat in the room, anywhere in the app, and on the big screen (MAD-842..845) - #71
Merged
Merged
Conversation
A room has a chat. Messages are plain text, trimmed, 1-500 characters,
and remember the song that was playing. Members and guests read and
post; paired displays read along. You can delete your own, and the
room's owner or an admin can delete anyone's.
- Migration 00033 adds chat_messages. A night isn't a row until it
ends, so ending one gives it the room's messages that have no night.
- POST/GET /rooms/{id}/messages (newest first, paged by ID) and
DELETE /rooms/{id}/messages/{messageId}.
- chat.message and chat.deleted on the room socket.
- Sending is rate limited with the reactions' token bucket, now
userLimiter with a rate per use: a burst of 5, then one every 2s.
- screens.chat (floating, log or off) says how the big screen shows it.
Left out of an update, it stays as it was.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…AD-844)
A Chat button on the room page opens the chat: a sheet on a phone, a
panel down the side on a computer. Messages are grouped by sender and
time, with a "during <song>" chip whenever the song changed, its
artists linked. Scrolling up loads older pages and keeps your place;
new messages stick to the bottom unless you've scrolled up, then a pill
says how many came in. You can delete your own (anyone's, as the host)
from a hover button or a long press. The composer follows the visual
viewport so the keyboard never covers it, and Enter sends on a computer.
RoomLive keeps the room's chat loaded on every screen. Unread counts,
per device in local storage, show on the Chat button and the Room tab.
A device that's never read a room's chat starts with nothing unread.
New messages pop up anywhere in the app as a small glass bubble near
the top, in their own slot away from the toaster. Never for your own,
or while the chat is open. A burst collapses ("Sam and 2 others").
Tap to open the chat, swipe to dismiss. The Me page can mute them on
this device; the unread count still counts.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The TV shows the room's chat in the look the room picks (screens.chat, in the big screen settings): Floating drifts messages across the top of the screen as glass bubbles with the sender's name in their color, clear of the lyrics and the title, two lanes and four at most. Side log keeps the last few from the past 15 minutes in the top right. Off shows none. A deleted message leaves the screen at once. The app's visualizer shows the same. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Stage 3 of Phase 13 (MAD-836), its last stage: people in a room can chat. Messages show in a chat panel in the room, pop up wherever you are in the app, and float by on the TV.
The decisions are written up in ADR 0018 (
docs/adr/0018-room-chat.md).MAD-842: ADR, data model, API and realtime
internal/chatpackage and migration 00033 (chat_messages).nights.end), every message in that room without a night, up to the end time, is assigned to it.night_idis kept in case a recap or export wants the messages later.queue_item_id), and the API returns that song's snapshot (track) with the message, so the panel can show the song without another request.POST /rooms/{id}/messages: plain text, trimmed, 1–500 characters (counted in runes).GET /rooms/{id}/messages?before=&limit=: newest first, paged by ID (IDs are UUIDv7, so time-ordered). Deleted messages are left out.DELETE /rooms/{id}/messages/{messageId}: your own message, or anyone's if you're the room owner or an admin. The text is cleared and the row is kept, so paging stays stable.listChatMessagesis a display op). A room you can't open returns 404, as everywhere else.userLimiter, which takes arateeach time it's used. Chat allows a burst of 5, then one every 2s.chat.messageandchat.deletedare sent on the room topic. They're in the spec'sRoomEventenum, so they're in the generated TS types.screens.chat(floating|log|off, defaultfloating). If a screens update leaves it out, the current value is kept, so older clients don't reset it.MAD-843: Chat panel
ArtistLinks.RoomLivekeeps the chat loaded on every screen, so the counts stay right.visualViewport, so the phone keyboard doesn't cover it.MAD-844: Popups anywhere
MAD-845: Big screen
Testing
go test -race ./...,golangci-lint(0 issues), and webpnpm test(298), typecheck, lint and build all pass.TestChat: send (trimmed, remembers the song), on the socket, validation, paging, display read-only, delete permissions andchat.deleted, private-room 404, rate limit, and messages assigned to the night when it ends.TestChatGuests: guests can read and post in their own room, and are blocked from other rooms.chatpackage: send, list and delete against the store and bus.TestRoomScreenscoversscreens.chat.lib/chat.test.ts: grouping, unread counts, read marks, cache updates, popup collapsing and timing./tv🤖 Generated with Claude Code