Timed speaker notes on the stage display - #5
Merged
Merged
Conversation
A cue carried one note. It now carries a list, and each note starts at a
point inside the cue.
`at_ms` is time into the cue, which is how a running order reads. The
screen converts to time remaining, against the cue's planned length. So
an operator who gives the speaker two more minutes moves every later
note with them. Nothing stored changes.
An import takes a list of `{at, text}`. `at` reads `5:00`, or a bare `5`
for minutes, the way `duration` does. The one string older rundowns and
snapshots carry still loads. It becomes a single note that starts with
the cue. An error names the note that failed.
The CSV column holds the same list as text, one note per line opening
with its time. An indented line continues the note above it, so a note
keeps its line breaks. A line opening with a bare number stays text.
"3 things to cover" is prose, not a cue point three minutes in.
A cue holds 10 notes of 500 characters. An import carrying more than
100,000 characters of notes gets a refusal. All of it rides in every
state frame to every client, and a slow client holds a backlog of them.
BREAKING CHANGE: `cues[].notes` is a list of `{at_ms, text}` in the
state frame, where it was a string. A controller that reads a cue note
needs the new shape.
The note moved from the footer to under the timer, where the speaker can read it. It wraps, keeps the operator's line breaks, and gives up after five lines. The old style was one clipped line at 40vw, so a 34 character note already lost its end. `currentNote` picks the note that is due. It runs with the readout rather than on a state frame, because the answer changes with the time left. It clamps remaining to the cue's planned length. Otherwise time added before the start would delay the opening note. A cue with no length shows the opening note, which covers count-up and time-of-day. Picking the note is display work, so it lives in the browser. No server tick has to know about it.
The cue editor held one Note field. It now holds a row for each note. Each row carries the time into the cue, the text, and a remove button. A new row lands five minutes after the last, which is where an author is working. A time that does not parse keeps the form open and says so. It does not drop the note. Each rundown row now says how many notes a cue holds. The notes sat behind Edit with nothing pointing at them. That is how the toggle for them came to look like an unfinished feature.
operations.md gains a section for the notes. How the time reads, what the screen does with it, and both document shapes. The ceilings entry carries the new numbers. architecture.md records the decision worth keeping. A note carries time-in and reads as time-remaining. `currentNote` holds that rule in the browser, because no server tick needs it.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
A cue's notes become a list, each one starting at a point inside the cue. The
stage display shows the note that is due, under the timer, where the speaker
can read it.
What changed
room: a cue carriesnotesas a list of{at_ms, text}, sorted by time.Ten notes of 500 characters each. The single string older rundowns and
snapshots carry still loads as one note at the cue start.
rundown_io: JSON carriesnotesas[{at, text}], whereatreads5:00or a bare5. The CSV column carries the same list as text, one noteper line opening with its time, an indented line continuing the one above.
An import over 100,000 characters of notes gets a refusal.
viewer: the note sits under the timer, wraps over as many as five lines,and changes as the time left reaches each note.
console: the cue editor holds one row per note. Each rundown row says howmany notes a cue holds.
Why
A note was one clipped line in the footer, and the only way to write one was
the Edit form. The toggle for it read as an unfinished feature.
Authoring in time-in and reading in time-remaining is the point. An operator
who buys the speaker two more minutes moves every later note with them, and no
stored note changes. Per-change rationale is in the commit bodies.
Breaking:
cues[].notesis a list in the state frame, where it was astring. Anything reading a cue note over the API needs the new shape.
How it was tested
make lintandmake testare clean: 360 Rust tests and 115 JavaScriptassertions, including the picker at every threshold and the added-time case.
Drove a real browser against a live binary: the note at 30:00, 25:00 and 5:00
remaining and into overtime, a CSV round trip carrying a multi-line note, the
row editor adding and removing notes, and both the room toggle and
?notes=0.