Add message actions
Use this when each chat message needs useful controls beyond passive display. The common pattern is one compact action row for frequent actions and a “more” menu for destructive or lower-frequency actions.
Recommended message menu
Section titled “Recommended message menu”| Control | Show it when | Operation | UI result |
|---|---|---|---|
| Reply | The room uses side threads | Threaded reply | Open a thread panel and increment its reply count |
| Quote | Replies should stay in the main flow | Quote a message | Composer shows a compact original-message preview |
| React | Reactions are enabled | React to a message | Update the count and current-user state |
| Edit | The current user can edit the event | Update message content | Replace the visible body after confirmation |
| Delete | The current user can delete the event | Delete event | Remove or tombstone the row |
| Report | The message is visible and reportable | Report message | Confirm receipt; do not immediately imply removal |
Connect the common actions
Section titled “Connect the common actions”These are current sportstalk-sdk methods. event.id is the
TalkLabs-assigned event ID returned in the room stream.
export function actionsFor(client, event) { return { send: (text) => client.executeChatCommand(text), quote: (text) => client.sendQuotedReply(text, event.id), thread: (text) => client.sendThreadedReply(text, event.id), like: () => client.reactToEvent('like', event.id), };}Normal sends belong to the room composer. Quote and thread handlers should open the composer with the target message stored separately from the draft text.
Make each action resilient
Section titled “Make each action resilient”Use the same state transition for every message action:
flowchart LR
A[User activates control] --> B[Disable that control]
B --> C[Send operation]
C -->|Success| D[Merge result by event ID]
C -->|Failure| E[Restore previous state]
D --> F[Reconcile with updates stream]
E --> G[Show action-level error]
- Replies: keep the draft if the request fails.
- Reactions: an optimistic count is appropriate when you can roll it back.
- Edits: do not replace the rendered body until the operation succeeds, or retain the previous body for rollback.
- Deletes: require confirmation when deletion is permanent.
- Reports: prevent repeated submissions while the first request is pending.
Use the event stream as final state
Section titled “Use the event stream as final state”The action response gives immediate confirmation. The room updates stream is the shared state all participants receive.
- Apply the action response immediately.
- Key local messages by event
id. - When the matching update arrives, merge it instead of appending a duplicate.
- Handle
replace,remove,reaction, andpurgeevent types in the same reducer as new messages.
Keep permissions out of presentation logic
Section titled “Keep permissions out of presentation logic”Your UI can hide controls that are irrelevant—for example, edit on someone
else’s message—but the API remains the authority. Handle 403 as a normal
action failure and refresh the affected event or room state.