feat: allow naming aux timers

Adds custom, persisted names for the three aux timers, editable in the
editor settings and surfaced everywhere an aux title is shown.

- Persist `auxTimerNames` on the Settings object (default empty, falls
  back to the stock "Aux N" label when unset). Reuses the existing
  settings pipeline: validation sanitises to a fixed-length trimmed
  array, the parser normalises loaded/legacy data, and migrations carry
  the field forward.
- New "Aux timers" settings section to name each timer, plus a shortcut
  button next to the aux timers in the playback control that jumps
  straight to it.
- Resolve names via a shared getAuxTimerLabel helper in the aux timer
  control, Studio view, secondary-source selector and preview, and the
  automation action labels.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WCZejVTzuAY3tHTE6nB3JH
This commit is contained in:
Claude
2026-07-23 15:48:09 +00:00
parent 5f040092cb
commit 2f7909ccc3
23 changed files with 237 additions and 34 deletions
+1 -1
View File
@@ -49,7 +49,7 @@ function Studio({ customFields, projectData, isMirrored, settings, viewSettings
<div className={cx(['studio-contents', hideCards && 'studio-contents--onecol'])}>
<StudioClock hideCards={hideCards} />
{!hideCards && <StudioTimers viewSettings={viewSettings} />}
{!hideCards && <StudioTimers viewSettings={viewSettings} auxTimerNames={settings?.auxTimerNames} />}
</div>
</div>
);
@@ -2,6 +2,7 @@ import { Playback, TimerPhase, ViewSettings } from 'ontime-types';
import { millisToString } from 'ontime-utils';
import { useAuxTimersTime, useStudioTimersSocket } from '../../common/hooks/useSocket';
import { getAuxTimerLabel } from '../../common/utils/auxTimerUtils';
import { getOffsetState } from '../../common/utils/offset';
import { cx } from '../../common/utils/styleUtils';
import { useTranslation } from '../../translation/TranslationProvider';
@@ -14,9 +15,10 @@ import './StudioTimers.scss';
interface StudioTimersProps {
viewSettings: ViewSettings;
auxTimerNames?: string[];
}
export default function StudioTimers({ viewSettings }: StudioTimersProps) {
export default function StudioTimers({ viewSettings, auxTimerNames }: StudioTimersProps) {
const { getLocalizedString } = useTranslation();
const { mainSource } = useStudioOptions();
const { eventNow, eventNext, message, time, offset, rundown, expectedRundownEnd } = useStudioTimersSocket();
@@ -100,7 +102,7 @@ export default function StudioTimers({ viewSettings }: StudioTimersProps) {
</div>
</div>
<StudioTimersAux />
<StudioTimersAux auxTimerNames={auxTimerNames} />
<div className='card' id='card-timer-message'>
<div>
@@ -119,24 +121,24 @@ export default function StudioTimers({ viewSettings }: StudioTimersProps) {
);
}
function StudioTimersAux() {
function StudioTimersAux({ auxTimerNames }: { auxTimerNames?: string[] }) {
const auxTimer = useAuxTimersTime();
return (
<div className='card' id='card-aux'>
<div className='card__row'>
<div>
<div className='label'>Aux 1</div>
<div className='label'>{getAuxTimerLabel(auxTimerNames, 1, 'Aux 1')}</div>
<div className='extra'>{millisToString(auxTimer.aux1)}</div>
</div>
<div>
<div className='label center'>Aux 2</div>
<div className='label center'>{getAuxTimerLabel(auxTimerNames, 2, 'Aux 2')}</div>
<div className='extra center'>{millisToString(auxTimer.aux2)}</div>
</div>
<div>
<div className='label right'>Aux 3</div>
<div className='label right'>{getAuxTimerLabel(auxTimerNames, 3, 'Aux 3')}</div>
<div className='extra right'>{millisToString(auxTimer.aux3)}</div>
</div>
</div>