Commit Graph
109 Commits
Author SHA1 Message Date
Waters ChurchandClaude Fable 5 444f03938d Timers: LTC timecode via the stage-display websocket
ProPresenter's HTTP API has no timecode route (verified: 21.4 returns
404), but its classic stage-display websocket still answers — so LTC now
comes from a stage layout field labeled "LTC": a zero-dependency RFC6455
client (stage-ws.js) authenticates (new stagePassword admin config),
resolves the LTC-labeled frame's uid from the layout list, and treats any
message carrying that uid as the timecode text. "Receiving" is a 2.5s
staleness heuristic; frozen or placeholder text reads as no-signal. The
HTTP probe stays authoritative when it ever answers (a 404 verdict is
retried once a minute), and the LTC card surfaces the reason when
timecode is unavailable (bad stage password, no LTC field). pp-timers-mock
grows a /stagedisplay websocket with --stage-pwd and --no-ltc-field to
exercise every path.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-31 17:05:23 -04:00
Claude 18ab8e92f1 Animated bars, inline ProdCom timestamps, fullscreen auto-fit, dual resize corners
Title bars (tiles and the main menubar, which gains the same notch tab)
now collapse and reopen with a height animation instead of popping. The
menubar's hidden state persists per browser. ProdCom timestamps move
inline to the right of the channel name, keeping their text style; the
clock button toggles just their visibility. New fullscreen button (left
of +): entering fullscreen auto-hides the menubar and auto-fits the
layout — occupied columns stretch proportionally across the width, tiles
whose bottom edge lands within two rows of the viewport bottom stretch
to end exactly at it, small tiles (h ≤ 2) alone in their columns are
exempt, and scrolling is disabled when nothing extends below the fold
(deeper layouts keep natural rows and scrolling). All fullscreen fitting
is visual-only and reverts on exit; editing affordances are parked while
in it. Corner resize indicators now appear only on tile hover, and a
second resize handle on the bottom-left corner resizes from that edge.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RNYUv9EyrGSFmCnmH7WYKH
2026-08-31 20:55:28 +00:00
Claude a06bc921ce Unified endpoint config type: one Host/IP : Port control in admin
New configSchema type 'endpoint' declared in the module spec: anything
that points at a device or service on the network must be one endpoint
field, rendered identically for every module in /admin as a joined
Host/IP : Port control and stored/handed to the module server as
{ host, port }. Migrates all three connection modules — ProdCom (was a
full URL field), ProPresenter and Timers (were separate host + port
fields). Legacy stored configs (prodcomUrl / flat host+port) keep
working until the admin form is re-saved, at which point the new shape
replaces them. MODULE-GUIDE documents the type and the presentation
rule: no split host/port fields, and full URLs only for genuine web
addresses.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RNYUv9EyrGSFmCnmH7WYKH
2026-08-31 19:33:08 +00:00
Waters ChurchandClaude Fable 5 12245cba93 Timers: present each timer and LTC in the Add-tile picker
Adopt main's new multi-tile contract: the module's server exports
tiles() (answered from the poller's held state, never a fresh upstream
request) listing All timers, one entry per discovered timer, and LTC
timecode. The client branches on moduleApi.variant — solo tiles render
exactly one card with no selection menu, and a solo timer that vanishes
from ProPresenter shows a labeled "Not in ProPresenter" card instead of
erroring (visible even in the compact layout). pp-timers-mock gains
--drop=<uuid,...> to simulate a timer deleted in ProPresenter.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-31 14:34:59 -04:00
Waters ChurchandClaude Fable 5 a8a382c171 Timers module: live ProPresenter timers and LTC timecode
New propresenter-timers module: polls /v1/timers + /v1/timers/current
(shapes verified against openapi.propresenter.com), probes the
undocumented /v1/timecode/status for LTC and honestly reports
"not available on this ProPresenter" when absent. Per-tile timer/LTC
selection via a Timers ▾ header menu (never-seen timers default on),
responsive auto-sized cards with state-derived colors (the API exposes
no per-timer color), unmistakable overrun. Includes tools/pp-timers-mock.js
for developing without a real ProPresenter.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-31 14:31:04 -04:00
Claude 54338ddf16 Icon topbar, module title-bar controls, hideable title bars, renames
Topbar: the add button is now just + and the layout button a 3-segment
grid icon (two squares + one tall rectangle). Modules no longer build
their own toolbars — moduleApi.header.addButton/addMenu put controls in
the tile's title bar next to the gear/close (menus are fixed-positioned
by the shell so a tile's overflow can't clip them, and everything a
module adds is removed automatically on unmount). Each title bar grows a
notch on its bottom edge that hides/shows the bar, ProdCom-Listener
style; the choice persists with the layout. Modules renamed: ProdCom and
ProPresenter. The ProdCom tile regains the original listener tools as
icon buttons in its title bar: timestamps toggle (clock), A−/A+ text
size, jump-to-latest, and a circle-with-cross clear button, plus the
Channels menu. MODULE-GUIDE documents the header API; README updated.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RNYUv9EyrGSFmCnmH7WYKH
2026-08-30 16:39:22 +00:00
Claude 9298b4d142 propresenter-now-next module: Now/Next tile fed by propresenter-core
Milestone 4. propresenter-core copied in unchanged (single home for every
ProPresenter 7/20 quirk). Server part owns the one polling connection and
exposes GET /state plus GET /stream (SSE, change-detected, heartbeated);
health reported for the admin page. Client ports the wall display's
rendering: fill-the-box title fit that never breaks words, tidied titles,
slide meta + progress bar, NEXT list with hidden-row '+ N more' overflow,
playlist name and live chip, all scaled to the tile via a JS-set --unit.
Verified against pp-mock.js including the arrangement-repeat case (the
counter follows core's honest-live-index rule, never X > Y) and
kill-and-restart recovery.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RNYUv9EyrGSFmCnmH7WYKH
2026-08-30 15:09:46 +00:00
Claude a549bb065a prodcom-transcript module: ProdCom proxy + live transcript tile
Milestone 3. Server part proxies /prodcom/* (SSE passthrough included) to
the admin-configured ProdCom URL, adding the Bearer key server-side so it
never reaches browsers; reports proxy health for the admin page. Client
ports the prodcom-listener UI into the module contract: history load,
live SSE with in-place updates of in-progress speech, channel colors,
channel visibility toggles + group presets (persisted per tile), hard
channel filter / text size / timestamps as instance settings, auto-scroll
with a jump-to-latest pill. tools/prodcom-mock.js simulates ProdCom
(word-by-word in-progress speech) for testing; verified against it,
including kill-and-restart recovery.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RNYUv9EyrGSFmCnmH7WYKH
2026-08-30 15:03:12 +00:00
Claude 3ac70fc44d Module system: discovery, route mounting, client loader, clock module
Milestone 2. Server scans modules/*/module.json, serves module assets at
/modules/<id>/, mounts optional server routes (exact + trailing-/* prefix
patterns) under /api/modules/<id>/ with per-module config from
config/modules.json, and lists enabled manifests at GET /api/modules.
Shell dynamically imports each module's client.js and hands it the
moduleApi (config, instanceSettings, scoped fetch, auto-reconnecting sse,
setStatus). Clock module proves the contract end to end; password-typed
config fields never leave the server.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RNYUv9EyrGSFmCnmH7WYKH
2026-08-30 14:55:25 +00:00