The rundown editor's list and table views render in the same container but
showed different loading states: the table now uses the shared animated
Loader while the list still showed a hardcoded "Connecting to server" ghost.
Use Loader in the list too so both view modes match.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Vq5XLTSQhU9ckZmCSW2SEr
Every viewer page (Timer, Countdown, Backstage, Studio, Timeline,
ProjectInfo, Operator) re-implemented the same data-loader flow by hand,
each with a hard-coded, unlocalized error string and drifting empty-state
styling. This centralizes that flow and elevates the shared presentation.
- Add ViewDataBoundary: a single component that renders the shared
loading, error and optional no-data states from a QueryStatus, so every
view handles them the same obvious way. Refactor all seven view loaders
through it.
- Localize the error state via new common.fetch_error /
common.fetch_error_hint keys (en + de/es/fr/it/pt), replacing the
duplicated English literal with a two-line "Something went wrong /
Please refresh the page" message.
- Elevate the shared Empty component: legible viewer-secondary color
(was 10% white), responsive title sizing, softened illustration,
optional supporting subtitle line, and a reduced-motion-safe fade-in.
- Unify loading: Cuesheet and the rundown table now use the animated
Loader like every other view instead of an untranslated "Loading..."
page.
- Tidy up: EmptyTableBody uses Empty's text prop, drop Countdown's
now-redundant size override, and remove a stray semicolon rendered in
the ProjectInfo empty state.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Vq5XLTSQhU9ckZmCSW2SEr
* fix: issue where a count-to-end would lead to incorrect expected times
* fix: include add time in overtime when countToEnd
* fix: ui and server use same calculation for expected end
The Stage Timer and PiP Timer views relied on `align-content: center` to
vertically center the timer digits inside `.timer-container`, which is a
plain block element. Aligning children of a block container via
`align-content` only works in Chromium 123+ (Firefox 125+, Safari 17.4+).
Embedded browsers such as vMix Browser Input (CEF V115) and other older
CEF/Chromium-based production tools ignore the property, so the digits
fall back to the top of the container while every other element renders
correctly.
Make `.timer-container` a real flex column and center with
`justify-content: center`, which is universally supported and matches the
centering approach used elsewhere in the codebase. The removed
`justify-self`/`align-self` were no-ops on a full-width flex item.
Fixes#2126
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014T6ENZ3r6JXZb1fpYw2oNY
Surface {{groupNow.*}} template variables (title, note, colour, times,
custom fields) in the automation template autocomplete so events inside a
group can reference their group. The runtime store already carries
groupNow, so substitution and filters worked already; this makes it
discoverable.
Extend the message-secondary action with an optional text field so an
automation can set the secondary message content, not just its source.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LZYPZVdZLWowU7DyzGkWyy
* feat: create the first event from the cuesheet
* chore: cleanup css
* test: cuesheet beckground edit from empty state
* feat: only show +event button when user is in edit mode and have full write perms
* refactor: allow secondary rundowns
* ui: move dropdown
* feat: follow loaded
* ui: background edit warning
ui: fix disable radio button
* feat(ui): add loaded sufix in the rundown list
* feat(ui): add direct link to background edit from rundown manager
* fix: better fallback
* fix: default to is isCurrentRundown for nav bar colour
* chore: rename navigate to cuesheet
---------
Co-authored-by: alex-arc <ac@omnivox.dk>