diff --git a/apps/client/src/features/control/playback/PlaybackControl.tsx b/apps/client/src/features/control/playback/PlaybackControl.tsx index ce4127a5f..b45fa1e7b 100644 --- a/apps/client/src/features/control/playback/PlaybackControl.tsx +++ b/apps/client/src/features/control/playback/PlaybackControl.tsx @@ -2,6 +2,7 @@ import { Playback } from 'ontime-types'; import { usePlaybackControl } from '../../../common/hooks/useSocket'; +import AddTime from './add-time/AddTime'; import { ExtraTimer } from './extra-timer/ExtraTimer'; import PlaybackButtons from './playback-buttons/PlaybackButtons'; import PlaybackTimer from './playback-timer/PlaybackTimer'; @@ -13,7 +14,9 @@ export default function PlaybackControl() { return (
- + + + { + const newTime = forgivingStringToMillis(value); + setTime(newTime); + }; + + const handleAddTime = (direction: 'add' | 'remove') => { + // API expects input in seconds + if (direction === 'add') { + setPlayback.addTime(time / MILLIS_PER_SECOND); + } else { + setPlayback.addTime((-1 * time) / MILLIS_PER_SECOND); + } + }; + + const canAddTime = playback === Playback.Play || playback === Playback.Pause; + const doDisableButtons = !canAddTime || time === 0; + + return ( +
+ +
+ + handleAddTime('remove')} disabled={doDisableButtons} className={style.tallButtons}> + + + + + handleAddTime('add')} disabled={doDisableButtons} className={style.tallButtons}> + + + +
+
+ ); +} 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 a5a7b3987..1fd3fdbdb 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 @@ -1,16 +1,17 @@ .timeContainer { display: grid; grid-template-areas: - 'ind clk clk btn' - '... sta fin btn'; + 'indicators timer addtime' + 'status status addtime'; grid-template-rows: 1fr auto; - grid-template-columns: 1.25rem 1fr 1fr 5rem; + grid-template-columns: 1.25rem 1fr 6.5rem; gap: $element-inner-spacing; - justify-items: start; } +// ---------> INDICATORS + .indicators { - grid-area: ind; + grid-area: indicators; width: 100%; height: 100%; display: flex; @@ -18,72 +19,46 @@ justify-content: space-evenly; } -.indRoll, -.indDelay, -.indNegative { +.indicatorRoll, +.indicatorDelay, +.indicatorNegative { background-color: $black-10; } -.indRoll, -.indRollActive, -.indDelay, -.indDelayActive { +.indicatorRoll, +.indicatorDelay { margin: 0 auto; - border-radius: 6px; - width: 12px; - height: 12px; + border-radius: 5px; + width: 10px; + height: 10px; } -.indRollActive { +.indicatorRoll[data-active='true'] { background-color: $ontime-roll; } -.indNegative, -.indNegativeActive { - margin: 0 auto; - width: 90%; - height: 0.25rem; -} - -.indNegativeActive { - background-color: $playback-negative; -} - -.indDelayActive { +.indicatorDelay[data-active='true'] { background-color: $ontime-delay; } -.btn { - grid-area: btn; - display: grid; - grid-template-columns: 1fr 1fr; - grid-template-rows: 1fr 1fr; - width: 100%; - gap: $element-inner-spacing; +.indicatorNegative { + margin: 0 auto; + width: 90%; + height: 0.25rem; + + &[data-active='true'] { + background-color: $playback-negative; + } } -.minus { - grid-area: min; - display: flex; - flex-direction: column; -} +// ---------> LABELS -.start, -.finish, -.roll { +.status { + grid-area: status; height: 1.5rem; -} - -.start { - grid-area: sta; -} - -.finish { - grid-area: fin; -} - -.roll { - grid-area: 2 / 2 / 2 / 4 ; + display: flex; + gap: $section-spacing; + margin-left: 1.5rem; } .tag { 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 e3d77996f..fb8f78f0e 100644 --- a/apps/client/src/features/control/playback/playback-timer/PlaybackTimer.tsx +++ b/apps/client/src/features/control/playback/playback-timer/PlaybackTimer.tsx @@ -1,10 +1,9 @@ +import { PropsWithChildren } from 'react'; import { Tooltip } from '@chakra-ui/react'; import { Playback } from 'ontime-types'; import { dayInMs, millisToMinutes, millisToSeconds, millisToString } from 'ontime-utils'; -import { setPlayback, useTimer } from '../../../../common/hooks/useSocket'; -import { tooltipDelayMid } from '../../../../ontimeConfig'; -import TapButton from '../tap-button/TapButton'; +import { useTimer } from '../../../../common/hooks/useSocket'; import TimerDisplay from '../timer-display/TimerDisplay'; import style from './PlaybackTimer.module.scss'; @@ -13,8 +12,30 @@ interface PlaybackTimerProps { playback: Playback; } -export default function PlaybackTimer(props: PlaybackTimerProps) { - const { playback } = props; +function resolveAddedTimeLabel(addedTime: number) { + function resolveClosestUnit(ms: number) { + if (ms < 6000) { + return `${millisToSeconds(ms)} seconds`; + } else if (ms < 12000) { + return '1 minute'; + } else { + return `${millisToMinutes(ms)} minutes`; + } + } + + if (addedTime > 0) { + return `Added ${resolveClosestUnit(addedTime)}`; + } + + if (addedTime < 0) { + return `Removed ${resolveClosestUnit(addedTime)}`; + } + + return ''; +} + +export default function PlaybackTimer(props: PropsWithChildren) { + const { playback, children } = props; const timer = useTimer(); const started = millisToString(timer.startedAt); @@ -22,88 +43,43 @@ export default function PlaybackTimer(props: PlaybackTimerProps) { const finish = millisToString(expectedFinish); const isRolling = playback === Playback.Roll; - const isStopped = playback === Playback.Stop; const isWaiting = timer.secondaryTimer !== null && timer.secondaryTimer > 0 && timer.current === null; - const disableButtons = isStopped || isRolling; const isOvertime = timer.current !== null && timer.current < 0; const hasAddedTime = Boolean(timer.addedTime); const rollLabel = isRolling ? 'Roll mode active' : ''; - const resolveAddedTimeLabel = () => { - function resolveClosestUnit(ms: number) { - if (ms < 6000) { - return `${millisToSeconds(ms)} seconds`; - } else if (ms < 12000) { - return '1 minute'; - } else { - return `${millisToMinutes(ms)} minutes`; - } - } - - if (timer.addedTime > 0) { - return `Added ${resolveClosestUnit(timer.addedTime)}`; - } - - if (timer.addedTime < 0) { - return `Removed ${resolveClosestUnit(timer.addedTime)}`; - } - - return ''; - }; - - const addedTimeLabel = resolveAddedTimeLabel(); + const addedTimeLabel = resolveAddedTimeLabel(timer.addedTime); return (
-
+
-
+
-
+
- {isWaiting ? ( -
+
+ {isWaiting ? ( Roll: Countdown to start -
- ) : ( - <> -
- Started at - {started} -
-
- Expect end - {finish} -
- - )} -
- - setPlayback.addTime(-60)} disabled={disableButtons} aspect='square'> - -1 - - - - setPlayback.addTime(60)} disabled={disableButtons} aspect='square'> - +1 - - - - setPlayback.addTime(-5 * 60)} disabled={disableButtons} aspect='square'> - -5 - - - - setPlayback.addTime(+5 * 60)} disabled={disableButtons} aspect='square'> - +5 - - + ) : ( + <> + + Started at + {started} + + + Expect end + {finish} + + + )}
+ {children}
); } diff --git a/apps/client/src/features/control/playback/timer-display/TimerDisplay.module.scss b/apps/client/src/features/control/playback/timer-display/TimerDisplay.module.scss index ee4613a55..3a4e8c07a 100644 --- a/apps/client/src/features/control/playback/timer-display/TimerDisplay.module.scss +++ b/apps/client/src/features/control/playback/timer-display/TimerDisplay.module.scss @@ -1,7 +1,7 @@ @use '../../../../theme/viewerDefs' as *; .timer { - grid-area: clk; + grid-area: timer; white-space: nowrap; max-width: 18.75rem; min-width: 5em; diff --git a/apps/client/src/features/editors/Editor.module.scss b/apps/client/src/features/editors/Editor.module.scss index 3a622f82d..9b15b6473 100644 --- a/apps/client/src/features/editors/Editor.module.scss +++ b/apps/client/src/features/editors/Editor.module.scss @@ -1,7 +1,7 @@ @use './EditorMixin' as editor; $min-playback-width: 27rem; -$max-playback-width: 35rem; +$max-playback-width: 30rem; $panel-gap: 0.5rem; .corner {