mirror of
https://github.com/cpvalente/ontime.git
synced 2026-08-16 12:53:32 +00:00
refactor(teleprompter): drop the two options that cannot justify themselves yet
Options are permanent surface. They live in URLs and in saved presets, so one can be added later without breaking anything while removing one breaks every preset that named it. That asymmetry says to keep only what earns its place before the view ships, not after. Autoplay goes. Its own code said as much: it was the single option needing a lint suppression because it is a starting condition rather than a live setting, which is not how any other option here behaves. It also has no coherent use. Starting a scroll on load runs the script at a fixed rate whether or not anybody is speaking, and following the loaded event, which is on by default, immediately pulls the position somewhere else. Anyone wanting a prompter to roll unattended needs the transport control we have not built. Alignment goes. Nothing in the research pointed at it as a control operators reach for, and centring multi line paragraphs leaves a ragged left edge which is harder to track back to on each new line. Left is the safer default and the option can come back cheaply if somebody asks for it. Seventeen options remain, and each maps to something the research called for or to the font and colour trio the other views already share. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Cb8RVPNQ2ETPJxdy4b8CHf
This commit is contained in:
@@ -64,7 +64,6 @@
|
||||
|
||||
font-size: var(--tp-font-size);
|
||||
line-height: var(--tp-line-height);
|
||||
text-align: var(--tp-align);
|
||||
|
||||
/**
|
||||
* The first line has to be able to reach the reading line, and the last line
|
||||
|
||||
@@ -87,7 +87,6 @@ function Teleprompter({ rundown, rundownMetadata, customFields }: TeleprompterDa
|
||||
atEnd,
|
||||
} = useTeleprompterScroll({
|
||||
initialSpeed: options.speed,
|
||||
autoplay: options.autoplay,
|
||||
followLoaded: options.followLoaded,
|
||||
selectedEventId,
|
||||
readingLinePos: options.readingLinePos,
|
||||
@@ -121,7 +120,6 @@ function Teleprompter({ rundown, rundownMetadata, customFields }: TeleprompterDa
|
||||
// the overlays and by 1dvh for the content padding. Percentage padding would
|
||||
// resolve against width and put the first line nowhere near the reading line
|
||||
'--tp-reading-line': options.readingLinePos,
|
||||
'--tp-align': options.align,
|
||||
'--tp-background': options.keyColour,
|
||||
'--tp-color': options.textColour,
|
||||
...(options.font ? { '--font-family-override': options.font } : {}),
|
||||
|
||||
@@ -11,12 +11,10 @@ describe('getOptionsFromParams()', () => {
|
||||
hideEmpty: true,
|
||||
showGroups: true,
|
||||
speed: DEFAULT_SPEED,
|
||||
autoplay: false,
|
||||
followLoaded: true,
|
||||
fontSize: 64,
|
||||
lineHeight: 1.5,
|
||||
textWidth: 90,
|
||||
align: 'left',
|
||||
dimPast: true,
|
||||
readingLine: 'line',
|
||||
readingLinePos: 40,
|
||||
@@ -44,10 +42,9 @@ describe('getOptionsFromParams()', () => {
|
||||
});
|
||||
|
||||
test('booleans which default to false can be turned on', () => {
|
||||
const options = getOptionsFromParams(new URLSearchParams('autoplay=true&flipH=true&flipV=true'));
|
||||
const options = getOptionsFromParams(new URLSearchParams('flipH=true&flipV=true'));
|
||||
|
||||
expect(options).toMatchObject({
|
||||
autoplay: true,
|
||||
flipH: true,
|
||||
flipV: true,
|
||||
});
|
||||
@@ -68,7 +65,6 @@ describe('getOptionsFromParams()', () => {
|
||||
test('rejects an unknown value for an enumerated option', () => {
|
||||
expect(getOptionsFromParams(new URLSearchParams('heading=banana')).heading).toBe('title');
|
||||
expect(getOptionsFromParams(new URLSearchParams('readingLine=banana')).readingLine).toBe('line');
|
||||
expect(getOptionsFromParams(new URLSearchParams('align=banana')).align).toBe('left');
|
||||
});
|
||||
|
||||
test('adds the hash back to colour params', () => {
|
||||
|
||||
@@ -23,14 +23,8 @@ const readingLineOptions = [
|
||||
{ value: 'none', label: 'None' },
|
||||
];
|
||||
|
||||
const alignOptions = [
|
||||
{ value: 'left', label: 'Left' },
|
||||
{ value: 'center', label: 'Centre' },
|
||||
];
|
||||
|
||||
const headingSources: readonly HeadingSource[] = ['none', 'title', 'cue', 'both'];
|
||||
const readingLineVariants: readonly ReadingLineVariant[] = ['none', 'line', 'arrows'];
|
||||
const alignments = ['left', 'center'] as const;
|
||||
|
||||
/**
|
||||
* Defaults and bounds for every option, in one place.
|
||||
@@ -45,12 +39,10 @@ const defaults = {
|
||||
hideEmpty: true,
|
||||
showGroups: true,
|
||||
speed: DEFAULT_SPEED,
|
||||
autoplay: false,
|
||||
followLoaded: true,
|
||||
fontSize: 64,
|
||||
lineHeight: 1.5,
|
||||
textWidth: 90,
|
||||
align: 'left',
|
||||
readingLine: 'line',
|
||||
readingLinePos: 40,
|
||||
dimPast: true,
|
||||
@@ -110,13 +102,6 @@ export const getTeleprompterOptions = (customFields: CustomFields): ViewOption[]
|
||||
type: 'number',
|
||||
defaultValue: defaults.speed,
|
||||
},
|
||||
{
|
||||
id: 'autoplay',
|
||||
title: 'Start scrolling on load',
|
||||
description: 'Whether the script starts scrolling as soon as the view opens',
|
||||
type: 'boolean',
|
||||
defaultValue: defaults.autoplay,
|
||||
},
|
||||
{
|
||||
id: 'followLoaded',
|
||||
title: 'Follow loaded event',
|
||||
@@ -171,14 +156,6 @@ export const getTeleprompterOptions = (customFields: CustomFields): ViewOption[]
|
||||
type: 'number',
|
||||
defaultValue: defaults.textWidth,
|
||||
},
|
||||
{
|
||||
id: 'align',
|
||||
title: 'Text alignment',
|
||||
description: 'Alignment of the script text',
|
||||
type: 'option',
|
||||
values: alignOptions,
|
||||
defaultValue: defaults.align,
|
||||
},
|
||||
{
|
||||
id: 'readingLine',
|
||||
title: 'Reading line',
|
||||
@@ -288,13 +265,11 @@ export function getOptionsFromParams(
|
||||
showGroups: toBoolean(getValue('showGroups'), defaults.showGroups),
|
||||
|
||||
speed: clampSpeed(toNumber(getValue('speed'), bounds.speed, defaults.speed)),
|
||||
autoplay: toBoolean(getValue('autoplay'), defaults.autoplay),
|
||||
followLoaded: toBoolean(getValue('followLoaded'), defaults.followLoaded),
|
||||
|
||||
fontSize: toNumber(getValue('fontSize'), bounds.fontSize, defaults.fontSize),
|
||||
lineHeight: toNumber(getValue('lineHeight'), bounds.lineHeight, defaults.lineHeight),
|
||||
textWidth: toNumber(getValue('textWidth'), bounds.textWidth, defaults.textWidth),
|
||||
align: toEnum(getValue('align'), alignments, defaults.align),
|
||||
dimPast: toBoolean(getValue('dimPast'), defaults.dimPast),
|
||||
readingLine: toEnum(getValue('readingLine'), readingLineVariants, defaults.readingLine),
|
||||
readingLinePos: toNumber(getValue('readingLinePos'), bounds.readingLinePos, defaults.readingLinePos),
|
||||
|
||||
@@ -32,12 +32,10 @@ export type TeleprompterOptions = {
|
||||
showGroups: boolean;
|
||||
/** lines per minute */
|
||||
speed: number;
|
||||
autoplay: boolean;
|
||||
followLoaded: boolean;
|
||||
fontSize: number;
|
||||
lineHeight: number;
|
||||
textWidth: number;
|
||||
align: 'left' | 'center';
|
||||
font?: string;
|
||||
keyColour: string;
|
||||
textColour: string;
|
||||
|
||||
@@ -27,7 +27,6 @@ const EXTERNAL_SCROLL_EPSILON = 2;
|
||||
|
||||
interface UseTeleprompterScrollArgs {
|
||||
initialSpeed: number;
|
||||
autoplay: boolean;
|
||||
followLoaded: boolean;
|
||||
selectedEventId: string | null;
|
||||
/** percentage from the top of the screen */
|
||||
@@ -52,7 +51,6 @@ interface UseTeleprompterScrollArgs {
|
||||
*/
|
||||
export function useTeleprompterScroll({
|
||||
initialSpeed,
|
||||
autoplay,
|
||||
followLoaded,
|
||||
selectedEventId,
|
||||
readingLinePos,
|
||||
@@ -234,14 +232,6 @@ export function useTeleprompterScroll({
|
||||
return () => document.removeEventListener('visibilitychange', onVisibilityChange);
|
||||
}, []);
|
||||
|
||||
// autoplay once, on mount
|
||||
useEffect(() => {
|
||||
if (!autoplay) return;
|
||||
runningRef.current = true;
|
||||
setIsRunning(true);
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps -- autoplay is a starting condition, not a live one
|
||||
}, []);
|
||||
|
||||
/**
|
||||
* Whether the loaded event currently has a block to scroll to.
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user