From 59bff62f76875a3f2fcf5860becd1c1f47a458b2 Mon Sep 17 00:00:00 2001 From: Claude Date: Sat, 1 Aug 2026 07:15:12 +0000 Subject: [PATCH] refactor: address review feedback on aux timer naming - Revert the automation action labels back to "Aux N: action" (no functional reason to change this wording). - Simplify the aux timers header in the playback control: the flex container now only handles layout, and the label text reuses the same font-size/color as the per-timer labels below it, instead of a bespoke style block duplicating those values. - Replace the generic, length-driven normaliser with an explicit sanitiseAuxTimerNames() that always deals with exactly three timers, and rename it away from "normalise" (which didn't convey that it trims, caps length and fills in missing entries). Static defaults now use a plain ['', '', ''] literal instead of calling the sanitiser with no input to sanitise. - Settings.type.ts and AuxTimerSettings.tsx no longer generate their three fields from a loop; the form mirrors the same explicit, one-field-per-row style already used by GeneralSettings.tsx. - Trim comments that only restated what the following line already says, keeping the ones that explain non-obvious behaviour (why AuxTimerService needs to be resynced separately from the data provider, why SimpleTimer.reset() preserves the name). Co-Authored-By: Claude Sonnet 5 Claude-Session: https://claude.ai/code/session_01WCZejVTzuAY3tHTE6nB3JH --- .../src/common/models/OntimeSettings.ts | 3 +- apps/client/src/common/utils/auxTimerUtils.ts | 6 ---- .../automations-panel/OntimeActionForm.tsx | 24 +++++++-------- .../panel/settings-panel/AuxTimerSettings.tsx | 28 ++++++++--------- .../playback/PlaybackControl.module.scss | 3 ++ .../control/playback/PlaybackControl.tsx | 2 +- .../api-data/db/migration/db.migration.v3.ts | 3 +- .../api-data/db/migration/db.migration.v4.ts | 4 +-- .../__tests__/settings.parser.test.ts | 4 +-- .../src/api-data/settings/settings.parser.ts | 6 ++-- .../api-data/settings/settings.validation.ts | 8 ++--- apps/server/src/app.ts | 14 ++++----- .../src/classes/simple-timer/SimpleTimer.ts | 3 -- apps/server/src/models/dataModel.ts | 4 +-- apps/server/src/models/demoProject.ts | 3 +- .../aux-timer-service/AuxTimerService.ts | 10 +++---- .../project-service/ProjectService.ts | 4 +-- packages/utils/index.ts | 6 +--- .../src/aux-timer-utils/auxTimerUtils.test.ts | 23 +++++++------- .../src/aux-timer-utils/auxTimerUtils.ts | 30 ++++++++----------- .../src/rundown-utils/rundownUtils.mock.ts | 4 +-- 21 files changed, 80 insertions(+), 112 deletions(-) diff --git a/apps/client/src/common/models/OntimeSettings.ts b/apps/client/src/common/models/OntimeSettings.ts index 2ef016c05..a12319f64 100644 --- a/apps/client/src/common/models/OntimeSettings.ts +++ b/apps/client/src/common/models/OntimeSettings.ts @@ -1,5 +1,4 @@ import { Settings } from 'ontime-types'; -import { normaliseAuxTimerNames } from 'ontime-utils'; export const ontimePlaceholderSettings: Settings = { version: '4.0.0', @@ -7,5 +6,5 @@ export const ontimePlaceholderSettings: Settings = { operatorKey: null, timeFormat: '24', language: 'en', - auxTimerNames: normaliseAuxTimerNames(), + auxTimerNames: ['', '', ''], }; diff --git a/apps/client/src/common/utils/auxTimerUtils.ts b/apps/client/src/common/utils/auxTimerUtils.ts index 4acf8caf3..ba4ccd77f 100644 --- a/apps/client/src/common/utils/auxTimerUtils.ts +++ b/apps/client/src/common/utils/auxTimerUtils.ts @@ -1,9 +1,3 @@ -/** - * Resolves the display label for an aux timer. - * Falls back to the provided default when no custom name is set. - * @param name - the aux timer's custom name (from the runtime store) - * @param fallback - label to use when no custom name is set - */ export function getAuxTimerLabel(name: string | undefined, fallback: string): string { const custom = name?.trim(); return custom ? custom : fallback; diff --git a/apps/client/src/features/app-settings/panel/automations-panel/OntimeActionForm.tsx b/apps/client/src/features/app-settings/panel/automations-panel/OntimeActionForm.tsx index c7527d1ab..11f6413b4 100644 --- a/apps/client/src/features/app-settings/panel/automations-panel/OntimeActionForm.tsx +++ b/apps/client/src/features/app-settings/panel/automations-panel/OntimeActionForm.tsx @@ -51,21 +51,21 @@ export default function OntimeActionForm({ }} value={watch(`outputs.${index}.action`)} options={[ - { value: 'aux1-pause', label: 'Aux timer 1: pause' }, - { value: 'aux2-pause', label: 'Aux timer 2: pause' }, - { value: 'aux3-pause', label: 'Aux timer 3: pause' }, + { value: 'aux1-pause', label: 'Aux 1: pause' }, + { value: 'aux2-pause', label: 'Aux 2: pause' }, + { value: 'aux3-pause', label: 'Aux 3: pause' }, - { value: 'aux1-start', label: 'Aux timer 1: start' }, - { value: 'aux2-start', label: 'Aux timer 2: start' }, - { value: 'aux3-start', label: 'Aux timer 3: start' }, + { value: 'aux1-start', label: 'Aux 1: start' }, + { value: 'aux2-start', label: 'Aux 2: start' }, + { value: 'aux3-start', label: 'Aux 3: start' }, - { value: 'aux1-stop', label: 'Aux timer 1: stop' }, - { value: 'aux2-stop', label: 'Aux timer 2: stop' }, - { value: 'aux3-stop', label: 'Aux timer 3: stop' }, + { value: 'aux1-stop', label: 'Aux 1: stop' }, + { value: 'aux2-stop', label: 'Aux 2: stop' }, + { value: 'aux3-stop', label: 'Aux 3: stop' }, - { value: 'aux1-set', label: 'Aux timer 1: set' }, - { value: 'aux2-set', label: 'Aux timer 2: set' }, - { value: 'aux3-set', label: 'Aux timer 3: set' }, + { value: 'aux1-set', label: 'Aux 1: set' }, + { value: 'aux2-set', label: 'Aux 2: set' }, + { value: 'aux3-set', label: 'Aux 3: set' }, { value: 'playback-start', label: 'Playback: start' }, { value: 'playback-stop', label: 'Playback: stop' }, diff --git a/apps/client/src/features/app-settings/panel/settings-panel/AuxTimerSettings.tsx b/apps/client/src/features/app-settings/panel/settings-panel/AuxTimerSettings.tsx index cff483035..d6fdf4a6b 100644 --- a/apps/client/src/features/app-settings/panel/settings-panel/AuxTimerSettings.tsx +++ b/apps/client/src/features/app-settings/panel/settings-panel/AuxTimerSettings.tsx @@ -1,5 +1,5 @@ import { Settings } from 'ontime-types'; -import { auxTimerNameMaxLength, numberOfAuxTimers } from 'ontime-utils'; +import { auxTimerNameMaxLength } from 'ontime-utils'; import { useEffect } from 'react'; import { useForm } from 'react-hook-form'; @@ -12,9 +12,6 @@ import useSettings from '../../../../common/hooks-query/useSettings'; import { preventEscape } from '../../../../common/utils/keyEvent'; import * as Panel from '../../panel-utils/PanelUtils'; -/** zero based index of each aux timer, used to address the auxTimerNames array */ -const auxTimerIndexes = Array.from({ length: numberOfAuxTimers }, (_, index) => index); - export default function AuxTimerSettings() { const { data, status, refetch } = useSettings(); const { @@ -30,7 +27,6 @@ export default function AuxTimerSettings() { }, }); - // update form if we get new data from server useEffect(() => { if (data) { reset(data); @@ -79,16 +75,18 @@ export default function AuxTimerSettings() { {errors.root?.message} - {auxTimerIndexes.map((index) => ( - - - - - ))} + + + + + + + + + + + + diff --git a/apps/client/src/features/control/playback/PlaybackControl.module.scss b/apps/client/src/features/control/playback/PlaybackControl.module.scss index 2d6ab5f0a..eee06cbab 100644 --- a/apps/client/src/features/control/playback/PlaybackControl.module.scss +++ b/apps/client/src/features/control/playback/PlaybackControl.module.scss @@ -8,6 +8,9 @@ align-items: center; justify-content: space-between; margin-top: 1rem; +} + +.label { font-size: $inner-section-text-size; color: $label-gray; } diff --git a/apps/client/src/features/control/playback/PlaybackControl.tsx b/apps/client/src/features/control/playback/PlaybackControl.tsx index bdc7065ef..8b69cdcb7 100644 --- a/apps/client/src/features/control/playback/PlaybackControl.tsx +++ b/apps/client/src/features/control/playback/PlaybackControl.tsx @@ -27,7 +27,7 @@ export default function PlaybackControl() { timerPhase={data.timerPhase} />
- Aux timers + Aux timers ): { const operatorKey = settings?.operatorKey; const timeFormat = settings?.timeFormat; const language = settings?.language; - const auxTimerNames = normaliseAuxTimerNames(settings?.auxTimerNames); + const auxTimerNames = sanitiseAuxTimerNames(settings?.auxTimerNames); const version = '4.5.0'; db.settings = { version, diff --git a/apps/server/src/api-data/settings/__tests__/settings.parser.test.ts b/apps/server/src/api-data/settings/__tests__/settings.parser.test.ts index 48906eb2e..aab720630 100644 --- a/apps/server/src/api-data/settings/__tests__/settings.parser.test.ts +++ b/apps/server/src/api-data/settings/__tests__/settings.parser.test.ts @@ -20,7 +20,7 @@ describe('parseSettings()', () => { }); }); - it('carries custom aux timer names through and normalises to a length-3 array', () => { + it('carries custom aux timer names through and pads to a length-3 array', () => { const result = parseSettings({ settings: { version: '1', auxTimerNames: ['Speaker'] } as unknown as Settings, }); @@ -35,7 +35,6 @@ describe('parseSettings()', () => { }); it('creates the aux timer names for project files made before the feature existed', () => { - // a settings object as found in a project file which predates aux timer naming const oldSettings = { version: '4.5.0', editorKey: null, @@ -47,7 +46,6 @@ describe('parseSettings()', () => { const result = parseSettings({ settings: oldSettings as Settings }); expect(result.auxTimerNames).toStrictEqual(['', '', '']); - // the rest of the settings are untouched expect(result).toMatchObject({ timeFormat: '24', language: 'en' }); }); }); diff --git a/apps/server/src/api-data/settings/settings.parser.ts b/apps/server/src/api-data/settings/settings.parser.ts index 3e19847f0..1e7d89e0c 100644 --- a/apps/server/src/api-data/settings/settings.parser.ts +++ b/apps/server/src/api-data/settings/settings.parser.ts @@ -1,5 +1,5 @@ import { DatabaseModel, Settings } from 'ontime-types'; -import { normaliseAuxTimerNames } from 'ontime-utils'; +import { sanitiseAuxTimerNames } from 'ontime-utils'; import { getPartialProject } from '../../models/dataModel.js'; @@ -23,7 +23,7 @@ export function parseSettings(data: Partial): Settings { operatorKey: data.settings.operatorKey ?? defaultSettings.operatorKey, timeFormat: data.settings.timeFormat ?? defaultSettings.timeFormat, language: data.settings.language ?? defaultSettings.language, - // property added in v4.6.0, older project files will not contain it - auxTimerNames: normaliseAuxTimerNames(data.settings.auxTimerNames), + // older project files predate this property + auxTimerNames: sanitiseAuxTimerNames(data.settings.auxTimerNames), }; } diff --git a/apps/server/src/api-data/settings/settings.validation.ts b/apps/server/src/api-data/settings/settings.validation.ts index eebac488e..e83ea679d 100644 --- a/apps/server/src/api-data/settings/settings.validation.ts +++ b/apps/server/src/api-data/settings/settings.validation.ts @@ -1,5 +1,5 @@ import { body } from 'express-validator'; -import { normaliseAuxTimerNames } from 'ontime-utils'; +import { sanitiseAuxTimerNames } from 'ontime-utils'; import { requestValidationFunction } from '../validation-utils/validationFunction.js'; @@ -28,11 +28,7 @@ export const validateSettings = [ pinValidator('operatorKey'), body('timeFormat').isString().isIn(['12', '24']).withMessage('Time format can only be "12" or "24"'), body('language').isString().trim().notEmpty(), - body('auxTimerNames') - .isArray() - .withMessage('auxTimerNames must be an array') - // normalise to a fixed length array of trimmed, length capped strings - .customSanitizer(normaliseAuxTimerNames), + body('auxTimerNames').isArray().withMessage('auxTimerNames must be an array').customSanitizer(sanitiseAuxTimerNames), requestValidationFunction, ]; diff --git a/apps/server/src/app.ts b/apps/server/src/app.ts index 395a35cc0..a3560b2ce 100644 --- a/apps/server/src/app.ts +++ b/apps/server/src/app.ts @@ -5,7 +5,7 @@ import cookieParser from 'cookie-parser'; import cors from 'cors'; import express from 'express'; import { LogOrigin, SimpleDirection, SimplePlayback, runtimeStorePlaceholder } from 'ontime-types'; -import { normaliseAuxTimerNames } from 'ontime-utils'; +import { sanitiseAuxTimerNames } from 'ontime-utils'; import serverTiming from 'server-timing'; import { oscServer } from './adapters/OscAdapter.js'; @@ -206,7 +206,7 @@ export const startServer = async (): Promise<{ message: string; serverPort: numb * Module initialises the services and provides initial payload for the store */ const state = getState(); - const auxTimerNames = normaliseAuxTimerNames(getDataProvider().getSettings().auxTimerNames); + const [auxName1, auxName2, auxName3] = sanitiseAuxTimerNames(getDataProvider().getSettings().auxTimerNames); eventStore.init({ clock: state.clock, timer: state.timer, @@ -222,27 +222,27 @@ export const startServer = async (): Promise<{ message: string; serverPort: numb current: timerConfig.auxTimerDefault, playback: SimplePlayback.Stop, direction: SimpleDirection.CountDown, - name: auxTimerNames[0] ?? '', + name: auxName1, }, auxtimer2: { duration: timerConfig.auxTimerDefault, current: timerConfig.auxTimerDefault, playback: SimplePlayback.Stop, direction: SimpleDirection.CountDown, - name: auxTimerNames[1] ?? '', + name: auxName2, }, auxtimer3: { duration: timerConfig.auxTimerDefault, current: timerConfig.auxTimerDefault, playback: SimplePlayback.Stop, direction: SimpleDirection.CountDown, - name: auxTimerNames[2] ?? '', + name: auxName3, }, ping: 1, }); - // seed the aux timer names onto the running service so they persist across commands - auxTimerService.loadNames(auxTimerNames); + // AuxTimerService owns its own SimpleTimer instances, so the store above doesn't update them + auxTimerService.loadNames(getDataProvider().getSettings().auxTimerNames); // initialise message service messageService.init(eventStore.set, eventStore.get); diff --git a/apps/server/src/classes/simple-timer/SimpleTimer.ts b/apps/server/src/classes/simple-timer/SimpleTimer.ts index 8969b74ef..157e9c2a1 100644 --- a/apps/server/src/classes/simple-timer/SimpleTimer.ts +++ b/apps/server/src/classes/simple-timer/SimpleTimer.ts @@ -29,9 +29,6 @@ export class SimpleTimer { }; } - /** - * Sets the custom name of the timer - */ public setName(name: string): SimpleTimerState { this.state.name = name; return this.state; diff --git a/apps/server/src/models/dataModel.ts b/apps/server/src/models/dataModel.ts index 5bd188db8..e77c557d0 100644 --- a/apps/server/src/models/dataModel.ts +++ b/apps/server/src/models/dataModel.ts @@ -1,5 +1,5 @@ import { DatabaseModel, Rundown } from 'ontime-types'; -import { generateId, normaliseAuxTimerNames } from 'ontime-utils'; +import { generateId } from 'ontime-utils'; import { ONTIME_VERSION } from '../ONTIME_VERSION.js'; @@ -30,7 +30,7 @@ const dbModel: DatabaseModel = { operatorKey: null, timeFormat: '24', language: 'en', - auxTimerNames: normaliseAuxTimerNames(), + auxTimerNames: ['', '', ''], }, viewSettings: { overrideStyles: false, diff --git a/apps/server/src/models/demoProject.ts b/apps/server/src/models/demoProject.ts index 5dd5755d6..0bc1ad97c 100644 --- a/apps/server/src/models/demoProject.ts +++ b/apps/server/src/models/demoProject.ts @@ -1,5 +1,4 @@ import { DatabaseModel, OntimeView } from 'ontime-types'; -import { normaliseAuxTimerNames } from 'ontime-utils'; import { backstageRundown, broadcastRundown, stageRundown } from './demoRundowns.js'; @@ -30,7 +29,7 @@ export const demoDb: DatabaseModel = { operatorKey: null, timeFormat: '24', language: 'en', - auxTimerNames: normaliseAuxTimerNames(), + auxTimerNames: ['', '', ''], }, viewSettings: { dangerColor: '#ff7300', diff --git a/apps/server/src/services/aux-timer-service/AuxTimerService.ts b/apps/server/src/services/aux-timer-service/AuxTimerService.ts index affd60664..2437cabb4 100644 --- a/apps/server/src/services/aux-timer-service/AuxTimerService.ts +++ b/apps/server/src/services/aux-timer-service/AuxTimerService.ts @@ -1,5 +1,5 @@ import { RuntimeStore, SimpleDirection, SimplePlayback } from 'ontime-types'; -import { normaliseAuxTimerNames } from 'ontime-utils'; +import { sanitiseAuxTimerNames } from 'ontime-utils'; import { SimpleTimer } from '../../classes/simple-timer/SimpleTimer.js'; import { timerConfig } from '../../setup/config.js'; @@ -26,13 +26,11 @@ export class AuxTimerService { } /** - * Applies custom names to the aux timers and broadcasts the change. - * Names are given in aux timer order (index 0 is aux timer 1). - * Used to seed the names at bootstrap and to keep them in sync - * with the settings of the loaded project. + * Called at bootstrap and whenever the loaded project's settings change, + * so the running timers reflect the current project's aux timer names. */ loadNames(names?: string[]) { - const [name1, name2, name3] = normaliseAuxTimerNames(names); + const [name1, name2, name3] = sanitiseAuxTimerNames(names); const patch: AuxTimerStateUpdate = { auxtimer1: this.aux1.setName(name1), auxtimer2: this.aux2.setName(name2), diff --git a/apps/server/src/services/project-service/ProjectService.ts b/apps/server/src/services/project-service/ProjectService.ts index a2c01ae98..3c4a9b4a0 100644 --- a/apps/server/src/services/project-service/ProjectService.ts +++ b/apps/server/src/services/project-service/ProjectService.ts @@ -90,7 +90,7 @@ async function loadProject(projectData: DatabaseModel, fileName: string, rundown // stop the runtime service runtimeService.stop(); - // the aux timer names belong to the project, apply the ones from the newly loaded project + // AuxTimerService holds its own state, independent of the loaded project, so it needs to be updated explicitly auxTimerService.loadNames(projectData.settings.auxTimerNames); // load the rundown given by key otherwise load the first in the project @@ -352,7 +352,7 @@ export async function patchCurrentProject(data: Partial) { // we can pass some stuff straight to the data provider await getDataProvider().mergeIntoData(rest); - // the settings may contain new aux timer names, apply them and notify the clients + // AuxTimerService holds its own state, so a settings patch needs to be applied to it explicitly if (rest.settings) { auxTimerService.loadNames(getDataProvider().getSettings().auxTimerNames); sendRefetch(RefetchKey.Settings); diff --git a/packages/utils/index.ts b/packages/utils/index.ts index 7f6b201b3..b0891f4fb 100644 --- a/packages/utils/index.ts +++ b/packages/utils/index.ts @@ -100,11 +100,7 @@ export { export { isPlaybackActive } from './src/playback-utils/playbackstate.js'; // aux timers -export { - auxTimerNameMaxLength, - normaliseAuxTimerNames, - numberOfAuxTimers, -} from './src/aux-timer-utils/auxTimerUtils.js'; +export { auxTimerNameMaxLength, sanitiseAuxTimerNames } from './src/aux-timer-utils/auxTimerUtils.js'; //Colour export { diff --git a/packages/utils/src/aux-timer-utils/auxTimerUtils.test.ts b/packages/utils/src/aux-timer-utils/auxTimerUtils.test.ts index e2e3d3947..eee892e3b 100644 --- a/packages/utils/src/aux-timer-utils/auxTimerUtils.test.ts +++ b/packages/utils/src/aux-timer-utils/auxTimerUtils.test.ts @@ -1,31 +1,30 @@ -import { auxTimerNameMaxLength, normaliseAuxTimerNames, numberOfAuxTimers } from './auxTimerUtils.js'; +import { auxTimerNameMaxLength, sanitiseAuxTimerNames } from './auxTimerUtils.js'; -describe('normaliseAuxTimerNames()', () => { +describe('sanitiseAuxTimerNames()', () => { it('generates the default value when given nothing', () => { - expect(normaliseAuxTimerNames()).toStrictEqual(['', '', '']); + expect(sanitiseAuxTimerNames()).toStrictEqual(['', '', '']); }); - it('always returns an entry per aux timer', () => { - expect(normaliseAuxTimerNames(['Speaker'])).toHaveLength(numberOfAuxTimers); - expect(normaliseAuxTimerNames(['a', 'b', 'c', 'extra'])).toStrictEqual(['a', 'b', 'c']); + it('always returns exactly three entries', () => { + expect(sanitiseAuxTimerNames(['a', 'b', 'c', 'extra'])).toStrictEqual(['a', 'b', 'c']); }); it('pads missing entries with an empty string', () => { - expect(normaliseAuxTimerNames(['Speaker'])).toStrictEqual(['Speaker', '', '']); + expect(sanitiseAuxTimerNames(['Speaker'])).toStrictEqual(['Speaker', '', '']); }); it('trims whitespace', () => { - expect(normaliseAuxTimerNames([' Speaker ', '', ''])).toStrictEqual(['Speaker', '', '']); + expect(sanitiseAuxTimerNames([' Speaker ', '', ''])).toStrictEqual(['Speaker', '', '']); }); it('caps the name length', () => { const tooLong = 'a'.repeat(auxTimerNameMaxLength + 10); - expect(normaliseAuxTimerNames([tooLong])[0]).toHaveLength(auxTimerNameMaxLength); + expect(sanitiseAuxTimerNames([tooLong])[0]).toHaveLength(auxTimerNameMaxLength); }); it('falls back to defaults for malformed data', () => { - expect(normaliseAuxTimerNames('not-an-array')).toStrictEqual(['', '', '']); - expect(normaliseAuxTimerNames(null)).toStrictEqual(['', '', '']); - expect(normaliseAuxTimerNames([42, {}, undefined])).toStrictEqual(['', '', '']); + expect(sanitiseAuxTimerNames('not-an-array')).toStrictEqual(['', '', '']); + expect(sanitiseAuxTimerNames(null)).toStrictEqual(['', '', '']); + expect(sanitiseAuxTimerNames([42, {}, undefined])).toStrictEqual(['', '', '']); }); }); diff --git a/packages/utils/src/aux-timer-utils/auxTimerUtils.ts b/packages/utils/src/aux-timer-utils/auxTimerUtils.ts index 19260634a..78d6b7ff4 100644 --- a/packages/utils/src/aux-timer-utils/auxTimerUtils.ts +++ b/packages/utils/src/aux-timer-utils/auxTimerUtils.ts @@ -1,22 +1,16 @@ -/** Number of aux timers available in ontime */ -export const numberOfAuxTimers = 3; - /** Maximum length of a user given aux timer name */ export const auxTimerNameMaxLength = 30; -/** - * Normalises user or file provided aux timer names into a - * fixed length array of trimmed, length capped strings. - * Missing or malformed entries fallback to an empty string, - * which consumers render as the default label. - * Used when parsing project files, when validating API payloads - * and to generate the default value. - */ -export function normaliseAuxTimerNames(maybeNames?: unknown): string[] { - const source = Array.isArray(maybeNames) ? maybeNames : []; - - return Array.from({ length: numberOfAuxTimers }, (_, index) => { - const value = source[index]; - return typeof value === 'string' ? value.trim().slice(0, auxTimerNameMaxLength) : ''; - }); +function sanitiseAuxTimerName(value: unknown): string { + return typeof value === 'string' ? value.trim().slice(0, auxTimerNameMaxLength) : ''; +} + +/** + * Ontime has three aux timers. Given whatever was found on disk or in a request body, + * returns a name for each of them, so callers never need to deal with a missing + * or malformed auxTimerNames (eg. a project file saved before this feature existed). + */ +export function sanitiseAuxTimerNames(names?: unknown): [string, string, string] { + const source = Array.isArray(names) ? names : []; + return [sanitiseAuxTimerName(source[0]), sanitiseAuxTimerName(source[1]), sanitiseAuxTimerName(source[2])]; } diff --git a/packages/utils/src/rundown-utils/rundownUtils.mock.ts b/packages/utils/src/rundown-utils/rundownUtils.mock.ts index 84e9b54cb..cab85e3f7 100644 --- a/packages/utils/src/rundown-utils/rundownUtils.mock.ts +++ b/packages/utils/src/rundown-utils/rundownUtils.mock.ts @@ -1,8 +1,6 @@ import type { DatabaseModel } from 'ontime-types'; import { EndAction, OntimeView, SupportedEntry, TimeStrategy, TimerType } from 'ontime-types'; -import { normaliseAuxTimerNames } from '../aux-timer-utils/auxTimerUtils.js'; - export const demoDb: DatabaseModel = { rundowns: { default: { @@ -344,7 +342,7 @@ export const demoDb: DatabaseModel = { operatorKey: null, timeFormat: '24', language: 'en', - auxTimerNames: normaliseAuxTimerNames(), + auxTimerNames: ['', '', ''], }, viewSettings: { dangerColor: '#ff7300',