Commit Graph

124 Commits

Author SHA1 Message Date
Claude 169714b3ae feat(teleprompter): stop playback at the end of the event
A user reading a podcast script found the prompter ran past the end of the
event and on into the next one. An event is a unit of time with a stop of
its own, but auto-scroll bounded against the end of the whole document, so
nothing held it at the boundary. At a conference that means the prompter
reads the next speaker's script while they are still walking on.

Playback now runs to the end of the segment being read and parks there,
saying so. Loading the next event releases it through the existing follow,
and pressing play again carries on into the next segment for a reader who
wants to keep going. Only playback is held: a jump, a page or a nudge is
the reader asking to leave the segment and still crosses freely.

The segment is chosen once when playback starts, and held by identity
rather than as a pixel bound. Re-deciding it against a position which is
moving let the bound outrun the reader and never arrive; holding the id
rather than the offset keeps the stop on the same words when an edit moves
the script underneath it.

Add an option to show only the event being played, for the case where the
rest of the script is a distraction. It falls back to the whole script
while nothing is playing, where narrowing would leave a blank screen. The
script of the event being played is now held out from the rest, which stays
readable so a reader who is ahead or behind can still find their place.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Cb8RVPNQ2ETPJxdy4b8CHf
2026-08-26 17:53:21 +00:00
Claude 1d8ca453c9 feat(teleprompter): anchor the read position and step between events
The scroll position was a pixel offset into a document that changes while
it is being read. Growing an event above the reader left scrollTop where it
was, so the text under the reading line slid: measured going from "Lucas
Bennett" to "Lunch" on an unchanged offset of 900.

Hold the position as a place in the script instead — the block under the
reading line plus an offset into it — and re-resolve it to pixels whenever
the document is measured. This follows how professional prompters cue a
story plus an offset rather than a scroll offset, so a reorder carries the
reader with the block and an edit above them changes nothing. A deleted
block falls back to the end of the nearest surviving event before it.

Add event-to-event stepping on Shift with the vertical arrows, matching
Shift being the coarser step on the horizontal ones, and take the step from
where the scroll is headed so pressing again mid-ease moves on rather than
re-aiming at the same event.

Free scrolling and the existing nudge and page keys are unchanged, but they
now hand over the scroll by one rule: how far the reader moved the script
themselves, accumulated. Distance from the follow target could not tell a
catch-up still running from a reader who had moved, so touching the wheel
while the prompter eased towards a newly loaded event stopped it following.
Accumulating also measures a wheel gesture the browser spreads over many
frames, which the old per-event check sampled only once.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Cb8RVPNQ2ETPJxdy4b8CHf
2026-08-25 11:12:10 +00:00
Claude 57362d85de fix(teleprompter): make follow-lock tolerant and its state legible
Two problems were feeding the confusion:

- Any wheel, touch, or pointerdown event broke the follow, with no tolerance.
  A stray touch or trackpad momentum after a deliberate gesture disengaged it
  as readily as a real scroll away from the read position, with no way to
  tell the two apart from the outside. The operator view solved the same
  problem with a distance check against the loaded item's expected position,
  which this now mirrors: it takes a real scroll (past 1.5 lines) to count as
  taking over, in a new hasBrokenFollow(), unit tested like the rest of the
  scroll maths.

- The runtime flag and the view option shared adjacent, opposite-valence
  names (followLocked / followLoaded) and were ANDed together in a third
  place to get the value the button actually needed. Renamed the runtime
  flag to autoScrollLocked, matching the operator's own lockAutoScroll for
  the same concept, and moved the AND into the hook so it exposes one signal
  the view no longer has to assemble itself.

Also fixes the threshold check reading a stale position: a burst of wheel
events can fire faster than the animation frame that keeps the scroll ref in
sync, so it now reads the element's scrollTop directly rather than the ref a
frame behind it. Caught by testing the tolerance in a live browser rather
than trusting the unit tests alone.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Cb8RVPNQ2ETPJxdy4b8CHf
2026-08-25 11:12:10 +00:00
Carlos Valente f655c47282 feat(teleprompter): add teleprompter view 2026-08-25 11:12:10 +00:00
Carlos Valente a84b8b5530 refactor(ui): polish navigation menu and view params editor 2026-08-23 13:42:21 +02:00
Carlos Valente c19aa4ca28 fix(cuesheet): prevent stale column width on refresh 2026-08-23 13:28:24 +02:00
Carlos Valente 805663e2ea chore(deps): migrate to @tanstack/react-table v9 2026-08-23 13:28:24 +02:00
Carlos Valente 4d04fe35c3 refactor(e2e): improve test stability 2026-08-09 10:41:12 +02:00
Carlos Valente 24be49ef66 refactor(settings): polish settings UI 2026-08-02 13:44:28 +02:00
Carlos Valente c6248b0c72 refactor(import): improve preview UI 2026-07-25 14:28:45 +02:00
Alex Christoffer Rasmussen 41a09bf5c3 fix: send refetch on all rundown edits (#2098)
* fix(server): send refetch on all rundown edits

* fix(test): cuesheet tabing

* chore: remove unneeded async

* refactor: small cleanups

* chore: spelling

Co-authored-by: Carlos Valente <34649812+cpvalente@users.noreply.github.com>

* chore: remove unneded async/await

---------

Co-authored-by: Carlos Valente <34649812+cpvalente@users.noreply.github.com>
2026-06-20 12:21:11 +02:00
Alex Christoffer Rasmussen b946b245c2 feat: create the first event from the cuesheet (#2105)
* 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
2026-06-17 22:31:13 +02:00
Carlos Valente 199dea5df6 fix(cuesheet): prevent timer cells from submitting on tab-out or escape (#2083) 2026-06-07 12:59:18 +02:00
Alex Christoffer Rasmussen 1a08b39b8b feat: auto cue re-numbering (#2016)
* 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>
2026-05-03 18:39:00 +02:00
Carlos Valente ba1c3235b3 refactor: improve gsheet import UX 2026-05-03 18:17:17 +02:00
Carlos Valente f739ba122b refactor: improve sheet flow management 2026-04-06 21:19:23 +02:00
Carlos Valente f53cb687bf refactor: improve sheet import UX 2026-04-06 21:19:23 +02:00
Carlos Valente 8c14c330f5 refactor: cache is rundown aware 2026-04-04 14:58:58 +02:00
Alex Christoffer Rasmussen c7d8b137ca chore: tooling (#2040)
* chore: only run release action if we have a tag

* chore: typescript 6 is out of beta

* chore: update flaky test

* chore: update pnpm

* chore: update playwright and node types

* chore: migrate tsup to tsdown

* chore: update node to node 22.22.2(LTS)

* chore: fix lockfile

---------

Co-authored-by: alex-Arc <omnivox@LAPTOP-RC5SNBVV.localdomain>
2026-03-27 19:31:41 +01:00
Alex Christoffer Rasmussen 73eff20d08 chore: format (#2030)
* chore: format

* chore: add formatter in CI check

---------

Co-authored-by: alex-Arc <omnivox@LAPTOP-RC5SNBVV.localdomain>
2026-03-24 09:49:22 +01:00
Carlos Valente 7e3aaa8c30 feat: UI access for custom views (#2020)
* style: consistent casing on menu

* refactor: bundle demo from code

* feat: allow uploading custom views
2026-03-24 09:19:45 +01:00
Alex Christoffer Rasmussen cf206e6220 feat: Vite 8 (#2018)
* chore: upgrade vite

* fix: inconsistentCjsInterop for ReactQR

* chore: e2e tests should use relativve path and get host from playwright config

* refactor: drop qr code dependency

---------

Co-authored-by: alex-Arc <omnivox@LAPTOP-RC5SNBVV.localdomain>
2026-03-24 09:11:57 +01:00
Carlos Valente 1849b4d39f Deps migration (#1988)
* 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>
2026-03-08 16:22:12 +01:00
Alex Christoffer Rasmussen c1fcdf7065 Remove serverport from project file (#1957)
* feat: get server port from app satate or env

optional startup port from env will always override

function for parsing port from env

populate default port in app state

add test for migration

* bump version
2026-03-02 06:02:29 -08:00
Carlos Valente df588b8845 refactor: extract cuesheet permissions 2026-02-23 15:23:49 +01:00
Carlos Valente 6268e327b9 refactor: mask cuesheet presets 2026-02-23 15:23:49 +01:00
Carlos Valente 1c81b3a23c refactor: hide edit button for users with no write permissions 2026-02-23 15:23:49 +01:00
Carlos Valente 63cfc9ec19 refactor: optimistic add elements in UI 2026-02-14 08:56:16 +01:00
Carlos Valente b6a01a52e2 fix: table re-renders no longer lose cell focus 2026-02-08 17:41:05 +01:00
Carlos Valente da02ecd113 feat: editor layout 2026-02-08 11:20:09 +01:00
Carlos Valente 967e92e2c8 feat: extend rundown shortcuts 2026-02-08 11:20:09 +01:00
Carlos Valente c5045ad82e refactor: table mode and context 2026-02-08 11:20:09 +01:00
Carlos Valente 3f1f06f7c5 Improve Clone (#1897)
* refactor(rundown): optimise copy-paste performance

* chore: configure opt-in compiler

* refactor(rundown): stabilise frequently accessed data

* feat(clone): allow cloning any element

* remove paste above and cue increment from test

---------

Co-authored-by: arc-alex <ac@omnivox.dk>
2025-11-28 16:20:52 +01:00
Carlos Valente e09b6bbc16 refactor: close menu in small screen navigation 2025-11-16 07:44:49 +01:00
Carlos Valente 15f3b9625c refactor: review overview styles 2025-11-09 06:44:24 +01:00
Carlos Valente 50599eccd2 refactor: show countdown if less than 10 min from start 2025-11-02 18:53:03 +01:00
Alex Christoffer Rasmussen da7c0d4ff2 Small clean-up (#1815)
* chore: remove old comment

* chore: smal lclean up of a e2e test

* chore: bump to beta.6

* chore: cleanup imports

* fix integration values com in ms

* allow linkStart and timeStrategy from API

* remove local mac dist
2025-10-10 17:37:55 +02:00
Alex Christoffer Rasmussen 147862e647 Fix opview with groups (#1814)
* create failing test

* fix: op evet used past state of the group
2025-10-08 21:19:57 +02:00
Alex Christoffer Rasmussen c4e6215b29 Update test time until (#1809)
* test views

test timeline

* timeline show seconds when less than 2m

* fix: countown typings

* refactor: backstage schedule item

* chore: lint
2025-10-07 12:32:12 +02:00
Carlos Valente 4b81725e80 chore: upgrade base-ui 2025-10-07 12:32:12 +02:00
Carlos Valente 8d2db7ffcd Relative mode (#1764)
* 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>
2025-09-21 07:42:47 +02:00
Carlos Valente ae15f3cdc5 Alpha 5 (#1741)
* 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>
2025-09-03 15:50:20 +02:00
Alex Christoffer Rasmussen 0e770655dc Fix: still counting to un-flaged event (#1726)
* create failing test

* ensuere all values a reset before calculations
2025-08-18 06:16:53 +02:00
Carlos Valente e5d2457717 chore: rename blocks to groups 2025-08-18 06:16:53 +02:00
Carlos Valente 6c6f5c2c0f feat: cuesheet sharing
feat: locked presets

refactor: simplify locked param

refactor: create share links
2025-08-18 06:16:53 +02:00
Carlos Valente 307f0ffd34 feat: expose presets in view options 2025-08-18 06:16:53 +02:00
Carlos Valente a1fab10bfd feat: improve preset building 2025-07-26 10:51:00 +02:00
Carlos Valente 1e1f547ce1 breaking: convert offset > over-under
change offset direction and relabel to over-under
2025-07-14 11:39:16 +02:00
Alex Christoffer Rasmussen e9dda817e5 block end calculation (#1683) 2025-07-14 11:38:27 +02:00
Carlos Valente e811a82be2 refactor: make minimal and clock as presets 2025-07-14 11:38:27 +02:00