One shared room where every member talks together, at /chatroom.
What it does
- A single live room: every member reads and writes the same stream. Day separators, messages grouped by author for five minutes, and a compact composer at the bottom.
- Live updates: when [TabRe Socket](../tabre_socket/) is running, new messages and deletions arrive through the public
chat/chat_deleteevents and appear without a reload. The header pill shows Live while the socket is open and Auto-refresh when the room falls back to a 9-second catch-up poll. The poll also runs after the tab was hidden, and when the network comes back. - History: the newest 60 messages load first; Load older messages fetches earlier pages without moving the scroll position.
- Send: Enter sends, Shift+Enter adds a line, IME composition is respected, and mobile keyboards keep Enter as a newline (the send button is the way). Markdown is rendered safely on the server.
- Delete: a member can delete their own message, moderators any message; a second click confirms (
Delete?). Deletions propagate live. - Guests see a sign-in card instead of the room. Groups without the reply permission read but cannot post.
- Left menu entry under Community with a hash icon; it is active on
/chatroom.
Settings (Admin → Plugins → TabRe Chat Room)
| Setting | Default | Meaning |
|---|---|---|
| Longest message (characters) | 500 | 100–2000 |
| Seconds between two messages | 2 | Per member; 0 = off |
| Messages per minute | 20 | Per member; 0 = no limit |
| Messages kept | 500 | Older rows are pruned as the room fills |
Data and endpoints
One table, dropped on uninstall: plugin_tabre_chatroom_msg (id, user_id, body, created_at).
| Route | Purpose |
|---|---|
/chatroom | the room (or the sign-in card for a guest) |
/chatroom/feed | JSON: latest page, ?after={id} for live catch-up, ?before={id} for older |
/chatroom/send | POST: store one message, answer with the escaped row HTML |
/chatroom/delete | POST: remove one message the member or a moderator owns |
Pruning runs on every 25th insert and hourly from cron (prune). The room keeps the newest keep_messages rows.
Without JavaScript
The page is a normal server-rendered stream; the composer is a real form with a CSRF field and posts to /chatroom/send, then redirects back. Delete buttons are forms too. Live updates and the jump pill are additions on top.
Notes for plugin authors
The room listens to the tabre-socket DOM event documented in the socket plugin's README:
document.addEventListener('tabre-socket', function (e) {
if (e.detail.kind === 'chat') { /* post_id is the message id */ }
if (e.detail.kind === 'chat_delete') { /* post_id was removed */ }
});