Companion Buttons 1.1.0: pages in the + picker, buttons chosen on the tile

The picker row (page list, Clear, Done) is gone. Each Companion page is now
its own + entry, titled with the page's name, showing the whole page minus
page up/down. The grid icon switches the tile to choosing: click buttons to
take them out or put them back, click the icon again when done. The gear
holds one switch, Page layout (Companion's rows and columns, or packed).

- Tiles follow their page by Companion's page id and buttons by row/column,
  so inserted pages and re-imported pages keep showing.
- A tile remounted after a settings change asks GET /state for the snapshot
  the already-open stream sent, instead of waiting blank.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-15 11:48:24 -04:00
co-authored by Claude Opus 5.5
parent 415453ef5f
commit 0a6cec88aa
8 changed files with 642 additions and 804 deletions
+35 -34
View File
@@ -1,14 +1,11 @@
# Companion Buttons
A [ProdDash](http://chronicles-ab.waterschurch.org:3000/michael/ProdDash) module
that shows any button from Bitfocus Companion — any page, any button — on a
dashboard tile, exactly as Companion draws it: colours, text, icons and live
feedback. It is meant for status buttons and anything else that says what is
happening right now.
that shows Bitfocus Companion pages on dashboard tiles — a whole page, or just
the buttons you pick from it — every button exactly as Companion draws it:
colours, text, icons and live feedback. It is meant for status buttons and
anything else that says what is happening right now.
- **One tile, one or many buttons.** A single button fills the tile; several
share it in whatever grid makes each one biggest, and resizing the tile
re-flows them.
- **Live.** Every time Companion redraws a button (a status turning red, a
tally lighting up), the tile shows it. Identical redraws — a status page that
repaints every second with the same picture — are not re-sent.
@@ -21,26 +18,27 @@ happening right now.
running Companion and its web interface port (8000 unless changed in
Companion's settings). Use `127.0.0.1` when Companion runs on the same
machine as ProdDash.
2. **+ Add tile → Companion Buttons.** A new tile opens the picker: choose a
page from the list and tap the buttons to show. The numbers on the picked
buttons are the order they appear in. **Done** shows them.
3. To change the buttons later, use the grid icon in the tile's title bar.
The gear has one switch, **Captions**, which writes the page name under
each button.
2. **+ Add tile:** every Companion page is listed under **Companion
Buttons**. Pick one — "19 Status", say — and the tile shows that page,
titled with its name. Page up/down buttons are left out.
3. **To show only some buttons,** click the grid icon in the tile's title bar.
The whole page appears; click a button to take it out (it fades) or put it
back. Click the icon again when done. Putting every button back means the
whole page again, including buttons added to it later.
4. **The gear** has one switch, **Page layout**: on, the buttons keep
Companion's rows and columns; off, they are packed into whatever grid makes
each one biggest.
Hover a button for its page and Companion location (`page/row/column`).
### What a tile follows
Each picked button is saved with its Companion id **and** its page, row and
column. While Companion still has that button anywhere, the tile follows it,
so dragging it to another spot or inserting a page in front changes nothing.
If the id is gone — a page re-imported from a `.companionconfig` gives every
button a new id — the tile shows whatever is at the saved page, row and column
instead. Either way the tile saves back what it found, so it stays current.
A button that is gone with nothing at its place shows **Not in Companion**,
and the status dot turns amber.
A tile follows its page by Companion's own page id, so inserting or moving
pages changes nothing. Buttons are followed by their row and column on that
page, so a page re-imported from a `.companionconfig` (every button gets a new
internal id) keeps showing. A chosen place that is emptied in Companion shows
a dashed outline. A page deleted in Companion leaves the tile empty; the
dashboard folds it away.
### When Companion is down
@@ -53,20 +51,23 @@ last pictures to grey, so nobody reads them as live. ProdDash keeps retrying
Companion 4 and 5 have no HTTP route that returns a button's picture. Their
own web buttons and emulator get them from the tRPC websocket on the web
interface port (`ws://<host>:<port>/trpc`). The module's server holds one such
connection for all dashboards and uses two read-only subscriptions:
`pages.watch` (pages, names, which button is where) and
`preview.graphics.controlId` (a button's PNG, on every redraw). That is
Companion's internal API rather than a documented one, so a future Companion
release could change it; it was built and tested against Companion 5.0.7.
connection for all dashboards and uses three read-only subscriptions:
`pages.watch` (pages, names, which button is where),
`preview.graphics.controlId` (a button's PNG, on every redraw) and
`controls.watchControl` (read once per button, to leave out page up/down).
That is Companion's internal API rather than a documented one, so a future
Companion release could change it; it was built and tested against Companion
5.0.7.
| Route | What it serves |
| --- | --- |
| `GET /pages` | Every page and the buttons on it — the picker's list |
| `GET /image/<id>` | One button's current picture as PNG — picker thumbnails |
| `GET /stream/<page.row.column.id>/…` | SSE `button` events for a tile's buttons: all of them on connect, then each redraw or move |
| `GET /stream/<page>[/<row.col>/…]` | SSE for one tile: `page` (what to lay out) and `button` (one picture) on connect, then on every change |
| `GET /state/<page>[/<row.col>/…]` | The same as one snapshot, for a tile that joins a stream the dashboard already has open |
| `GET /page-options` | The pages, for a tile added without one (the gear's Page) |
A tile holds one stream for all its buttons, because ProdDash carries at most
32 streams per page and a status board can show more buttons than that.
The + entries come from the server's `tiles()`, one per page. A tile holds
one stream for all its buttons, because ProdDash carries at most 32 streams
per page and a status board can show more buttons than that.
## Requirements
@@ -81,9 +82,9 @@ A tile holds one stream for all its buttons, because ProdDash carries at most
| File | |
| --- | --- |
| `module.json` | Manifest |
| `server.js` | Routes, button subscriptions, the per-tile streams |
| `server.js` | + entries, routes, button subscriptions, the per-tile streams |
| `companion.js` | The connection to Companion's tRPC websocket and the page list |
| `client.js`, `style.css` | The tile and its picker |
| `client.js`, `style.css` | The tile and its choosing mode |
| `test/companion.test.js` | Tests: `node test/companion.test.js` |
| `test/companion-mock.js` | A stand-in Companion: `node test/companion-mock.js 18000`, then point the module at `127.0.0.1` port `18000` |