Blink and blackout are two ways of hiding the same timer, and having both on
does not mean anything the audience can read differently from either alone.
Turning one on now turns the other off, enforced where the two toggles are
sent so the invariant holds regardless of which control calls it.
The screen buttons move from a row below the stage to a column on its right,
which is where they act and costs less height than a row. The stage and the
button column live in a grid so the buttons can be a fixed, content-sized
width instead of stretching to match the stage's height. A container query
against the panel's own width collapses back to a stacked layout, buttons in
a row below the stage, for a narrower fit (a resized /messagecontrol window,
for instance) where the two can't sit side by side.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011CHxSQ6nWHuyar8feieRra
Recovering from "message up, blinking, secondary on" took four clicks in
three places, which is the wrong shape for something done under pressure.
One control now returns the stage to a plain timer in a single patch,
keeping whatever the operator has typed. It is disabled while nothing is
active, so an accidental click is a no-op.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011CHxSQ6nWHuyar8feieRra
The panel absorbs whatever height the playback control above it leaves, and
its content was a fixed stack taller than that space on a 1280x800 screen -
with the container set to hide overflow, the secondary message input was
silently clipped off the bottom.
The stage preview is now the only elastic element and the controls are the
fixed floor, which is the way round an operator needs it. The control stack
also gets shorter: blink and blackout share a row, and the secondary source
select moves next to the secondary text input.
That regrouping removes the duelling owners of `secondarySource`. The select
picks the source and the eye toggles the line on and off, so the "Show
secondary" button - which wrote the same field from a second place, and made
picking an aux read as "secondary message hidden" - is gone along with the
local mirror of the remote state it needed.
Also: blackout now uses the destructive button variant, the toggles expose
`aria-pressed`, and the input rows use the shared editor label.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011CHxSQ6nWHuyar8feieRra
The icon rail was absolutely positioned over the same box as the preview
content, so at narrow widths it collided with the render - and now that the
preview shows a real timer, it also sat under the blackout overlay. It moves
into the options column as a compact row, where it reads as editor chrome
rather than part of the stage.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011CHxSQ6nWHuyar8feieRra
The preview showed the word "Timer" where the timer goes, so it could not
tell an operator what the audience will actually see. It now embeds the same
component the picture-in-picture window uses.
Making PipTimer embeddable also fixes the pop-out window, which rendered a
running timer while the stage was blacked out and did not blink with the
stage. The timer font size, the message padding and the overtime outline move
from viewport to container units: inside the preview they resolve against the
stage frame, and in the pip window - which has no ancestor query container -
they resolve against its viewport exactly as before.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011CHxSQ6nWHuyar8feieRra
* 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>
* feat: update auto cue numbering
* feat: renumber from ui
* refactor: patchEntries is not used
* chore: format
* fix: correct cue at top of group
* fix: handle precision
* refactor dialog
* bump limit for performance time test
* extract type
* add class name to lable
* fix rebase
* refator: extract renumering logic
* chore: comments for getIntegerAndFraction function
* chore: add the for renumber mutation
* fix: fraction match precision
* refactor: small cleanup
* refactor: use more narrow validator
---------
Co-authored-by: alex-Arc <omnivox@LAPTOP-RC5SNBVV.localdomain>
* chore: migrate eslint to oxlint
* chore: migrate prettier to oxfmt
* chore: migrate typescript
* chore: toThrow should have a expected value
* chore: cast test value as Day
* chore: small title fix
* chore: mocks should be hoisted
* chore: incorrect async useage
* chore: test should be inside description
* chore: test sohuld include an expeced
* chore: oxfmt
---------
Co-authored-by: alex-Arc <omnivox@LAPTOP-RC5SNBVV.localdomain>
* feat: add group start time to state
* refactor: calculate expected times when offset mode changes
* feat: show relative data in ui
* fixup! feat: add group start time to state
* fixup! refactor: calculate expected times when offset mode changes
* fixup! feat: show relative data in ui
* try to handle multiday
* show planed/expected rundown end day offset values
* refactor: style tweaks to timers
* refactor: cleanup data use
* day offset
* update tests
* test getExpectedStart multiday
* write start epoch to restore file
* current day in relative mode
* remove todo
* move find day offset to utils
---------
Co-authored-by: arc-alex <ac@omnivox.dk>
* refactor: align header columns
* refactor: improve scrollbar visibility
* refactor: center align table elements
* refactor: make param elements stateful
* fix: issue with collapsed elements not loosing value
* fix: prevent search params containing multiple alias references
* fix: the issue where a file disappears if it is both migrated and recovered in the same load operation (#1744)
* refactor: disable group action for elements in groups
* refactor: move context menu items into the event element (#1747)
* feat: sheet import new features for v4 (#1730)
* import milestone
* fixup! import milestone
* test: milestone import
* add entries to group
stop on new group or on group-end type
* fixup! add entries to group
* cleanup
* add event target duration
* link start if undefined
* add skip import type
* extract some to the excel paresing functions
* tweaks to presentation
* move file
---------
Co-authored-by: Carlos Valente <carlosvalente@pm.me>
* fix: notify runtimeStore of events bieng groupd
* fix: improve authentication and stage detection in demo
* chore: ship logo with project
* fix: client is referenced by name
* fix: prevent reflow in event editor
* fix: stale render on selected event due to ref mismatch
* Create/Load/Delete multiple rundowns (#1696)
* refactor: restore last loaded rundown
* refactor: initialise rundown in ProjectService
* feat: allow switching rundowns
ensure on coordination between the db object and the working object
server provide list of rundowns
implement switch in the UI
implement delete
implement new rundown button
* fix: render order for floating button
* refactor: appropriate names to service
* refactor: rundown endpoints
* refactor: save last loaded rundown ID
* refactor: rundown management UI
* refactor: emit refetch all on project load
---------
Co-authored-by: Carlos Valente <carlosvalente@pm.me>
* feat: recover single event subscription
* fixup! feat: sheet import new features for v4 (#1730)
* fix: prevent dropping a group inside another
* fixup! refactor: move context menu items into the event element (#1747)
* fix: prevent stale references to custom fields
* fix: propagate updates to all rundowns
* refactor: client rundown metadata (#1728)
* generate metadata in the hook
* move test
* ensure there is always a last element
* use for-loop
* update metadata in useEfect
* fully extract metadata generation
* use direct assignment
* cleanup
---------
Co-authored-by: Carlos Valente <carlosvalente@pm.me>
* refactor: small imporvement and tests for coerce functions (#1752)
* refactor: small imporvement and tests for coerce functions
add test `coerceString`
add test `coerceBoolean`
add test `coerceColour`
* remove old todo
* fix: consistent quick add behaviour
* refactor: create flat rundown with metadata
* fix: show add buttons on top
* feat: allow editing milestones
* refactor: style tweaks to rundown elements
refactor: milestones are full width
refactor: cuesheet header alignment
fix: editor styling in cuesheet
* refactor: virtualise table
* refactor: improve overscan (#1758)
* bump version to 4.0.0-alpha.5
---------
Co-authored-by: Alex Christoffer Rasmussen <ac@omnivox.dk>
* refactor: runtime types
* refactor: runtimeState functions to use the split type
* refactor: RuntimeService to use the new split data
* refactor: use the split data in the UI
* update comments
* refactor: rename runtime to offset
* fix utils test
* refactor: split event data and state data
* refactor: calculate the start time insted of until
* cleanup
* send next flag expected start from server
* refactor: render
* fix test
* use same icon
* refactor: group duration
* Optimize (#1711)
* refactor: consolidate block, flag and end loading and expected times
* work on test
* cal end value
* lint
* fix test
* remove todo