From f598e8dab18adf2af76f1b6c297fb4b3fcf89109 Mon Sep 17 00:00:00 2001 From: Carlos Valente Date: Tue, 14 Jul 2026 14:30:59 +0200 Subject: [PATCH] refactor(time control): improve handling of overtime and count to end --- apps/client/src/common/hooks/useSocket.ts | 11 ++++++ .../playback-timer/PlaybackTimer.module.scss | 4 +++ .../playback/playback-timer/PlaybackTimer.tsx | 36 ++++++++++++------- 3 files changed, 38 insertions(+), 13 deletions(-) diff --git a/apps/client/src/common/hooks/useSocket.ts b/apps/client/src/common/hooks/useSocket.ts index ab14f259e..97f9b9448 100644 --- a/apps/client/src/common/hooks/useSocket.ts +++ b/apps/client/src/common/hooks/useSocket.ts @@ -139,6 +139,17 @@ export const setEventPlayback = { pause: () => sendSocket('pause', undefined), }; +export const useTimerProgress = createSelector((state: RuntimeStore) => ({ + playback: state.timer.playback, + phase: state.timer.phase, + addedTime: state.timer.addedTime, + secondaryTimer: state.timer.secondaryTimer, + current: state.timer.current, + expectedFinish: state.timer.expectedFinish, + startedAt: state.timer.startedAt, + isCountToEnd: state.eventNow?.countToEnd ?? false, +})); + export const useTimer = createSelector((state: RuntimeStore) => ({ ...state.timer, })); diff --git a/apps/client/src/features/control/playback/playback-timer/PlaybackTimer.module.scss b/apps/client/src/features/control/playback/playback-timer/PlaybackTimer.module.scss index 025b838fc..e287313e9 100644 --- a/apps/client/src/features/control/playback/playback-timer/PlaybackTimer.module.scss +++ b/apps/client/src/features/control/playback/playback-timer/PlaybackTimer.module.scss @@ -73,6 +73,10 @@ margin-right: 0.25rem; } +.tagOvertime { + color: $playback-over; +} + .time { color: $section-white; font-size: $text-body-size; diff --git a/apps/client/src/features/control/playback/playback-timer/PlaybackTimer.tsx b/apps/client/src/features/control/playback/playback-timer/PlaybackTimer.tsx index ec4672e61..cd11cdc3c 100644 --- a/apps/client/src/features/control/playback/playback-timer/PlaybackTimer.tsx +++ b/apps/client/src/features/control/playback/playback-timer/PlaybackTimer.tsx @@ -1,12 +1,13 @@ import { MaybeNumber, Playback, TimerPhase } from 'ontime-types'; -import { dayInMs, millisToString } from 'ontime-utils'; +import { millisToString } from 'ontime-utils'; import { PropsWithChildren } from 'react'; import AppLink from '../../../../common/components/link/app-link/AppLink'; import Tooltip from '../../../../common/components/tooltip/Tooltip'; import useReport from '../../../../common/hooks-query/useReport'; -import { useTimer } from '../../../../common/hooks/useSocket'; -import { formatDuration } from '../../../../common/utils/time'; +import { useTimerProgress } from '../../../../common/hooks/useSocket'; +import { cx } from '../../../../common/utils/styleUtils'; +import { formatDuration, normaliseWallClock } from '../../../../common/utils/time'; import TimerDisplay from '../timer-display/TimerDisplay'; import style from './PlaybackTimer.module.scss'; @@ -24,15 +25,14 @@ function resolveAddedTimeLabel(addedTime: number) { } export default function PlaybackTimer({ children }: PropsWithChildren) { - const timer = useTimer(); + 'use memo'; + const timer = useTimerProgress(); const isRolling = timer.playback === Playback.Roll; const isWaiting = timer.phase === TimerPhase.Pending; const isOvertime = timer.phase === TimerPhase.Overtime; const hasAddedTime = Boolean(timer.addedTime); - const rollLabel = isRolling ? 'Roll mode active' : ''; - const addedTimeLabel = resolveAddedTimeLabel(timer.addedTime); return ( @@ -51,7 +51,13 @@ export default function PlaybackTimer({ children }: PropsWithChildren) { {isWaiting ? ( Roll: Countdown to start ) : ( - + )} {children} @@ -62,16 +68,18 @@ export default function PlaybackTimer({ children }: PropsWithChildren) { interface RunningStatusProps { startedAt: MaybeNumber; expectedFinish: MaybeNumber; - playback: Playback; + isStopped: boolean; + isCountToEnd: boolean; + isOvertime: boolean; } -function RunningStatus({ startedAt, expectedFinish, playback }: RunningStatusProps) { - if (playback === Playback.Stop) { + +function RunningStatus({ startedAt, expectedFinish, isStopped, isCountToEnd, isOvertime }: RunningStatusProps) { + if (isStopped) { return ; } const started = millisToString(startedAt); - const finishedMs = expectedFinish !== null ? expectedFinish % dayInMs : null; - const finish = millisToString(finishedMs); + const finish = millisToString(expectedFinish === null ? null : normaliseWallClock(expectedFinish)); return ( <> @@ -80,7 +88,9 @@ function RunningStatus({ startedAt, expectedFinish, playback }: RunningStatusPro {started} - Expect end + + {isCountToEnd ? 'Scheduled end' : 'Expected end'} + {finish}