diff --git a/apps/client/src/views/timer/Timer.tsx b/apps/client/src/views/timer/Timer.tsx index 58acc16b2..558ce1e1d 100644 --- a/apps/client/src/views/timer/Timer.tsx +++ b/apps/client/src/views/timer/Timer.tsx @@ -1,57 +1,42 @@ -import { useSearchParams } from 'react-router-dom'; -import { AnimatePresence, motion } from 'framer-motion'; +import { AnimatePresence } from 'framer-motion'; import { CustomFields, MessageState, OntimeEvent, - Playback, ProjectData, Settings, SimpleTimerState, - TimerPhase, - TimerType, ViewSettings, } from 'ontime-types'; import { FitText } from '../../common/components/fit-text/FitText'; import MultiPartProgressBar from '../../common/components/multi-part-progress-bar/MultiPartProgressBar'; -import TitleCard from '../../common/components/title-card/TitleCard'; import ViewLogo from '../../common/components/view-logo/ViewLogo'; import ViewParamsEditor from '../../common/components/view-params-editor/ViewParamsEditor'; import { useWindowTitle } from '../../common/hooks/useWindowTitle'; import { ViewExtendedTimer } from '../../common/models/TimeManager.type'; +import { cx } from '../../common/utils/styleUtils'; import { formatTime, getDefaultFormat } from '../../common/utils/time'; import SuperscriptTime from '../../features/viewers/common/superscript-time/SuperscriptTime'; -import { - getFormattedTimer, - getPropertyValue, - getTimerByType, - isStringBoolean, -} from '../../features/viewers/common/viewUtils'; +import { getFormattedTimer, getPropertyValue, getTimerByType } from '../../features/viewers/common/viewUtils'; import { useTranslation } from '../../translation/TranslationProvider'; -import { getTimerOptions } from './timer.options'; +import { MotionTitleCard, titleVariants } from './timer.animations'; +import { getTimerOptions, useTimerOptions } from './timer.options'; +import { + getEstimatedFontSize, + getIsPlaying, + getSecondaryDisplay, + getShowClock, + getShowMessage, + getShowModifiers, + getShowProgressBar, + getTimerColour, + getTotalTime, +} from './timer.utils'; import './Timer.scss'; -// motion -const titleVariants = { - hidden: { - x: -2500, - }, - visible: { - x: 0, - transition: { - duration: 1, - }, - }, - exit: { - x: -2500, - }, -}; - -export const MotionTitleCard = motion(TitleCard); - interface TimerProps { auxTimer: SimpleTimerState; customFields: CustomFields; @@ -69,170 +54,126 @@ export default function Timer(props: TimerProps) { const { auxTimer, customFields, eventNow, eventNext, general, isMirrored, message, settings, time, viewSettings } = props; + const { + hideClock, + hideCards, + hideProgress, + hideMessage, + hideTimerSeconds, + removeLeadingZeros, + mainSource, + secondarySource, + } = useTimerOptions(); + const { getLocalizedString } = useTranslation(); - const [searchParams] = useSearchParams(); useWindowTitle('Timer'); - // USER OPTIONS - const userOptions = { - hideClock: false, - hideCards: false, - hideProgress: false, - hideMessage: false, - hideTimerSeconds: false, - hideClockSeconds: false, - removeLeadingZeros: true, - }; + // gather modifiers + const showOverlay = getShowMessage(message.timer); + const { showEndMessage, showFinished, showWarning, showDanger } = getShowModifiers( + time.timerType, + time.countToEnd, + time.phase, + viewSettings, + ); + const isPlaying = getIsPlaying(time.playback); + const showClock = !hideClock && getShowClock(time.timerType); + const showProgressBar = !hideProgress && getShowProgressBar(time.timerType); - const hideClock = searchParams.get('hideClock'); - userOptions.hideClock = isStringBoolean(hideClock); - - const hideCards = searchParams.get('hideCards'); - userOptions.hideCards = isStringBoolean(hideCards); - - const hideProgress = searchParams.get('hideProgress'); - userOptions.hideProgress = isStringBoolean(hideProgress); - - const hideMessage = searchParams.get('hideMessage'); - userOptions.hideMessage = isStringBoolean(hideMessage); - - const hideClockSeconds = searchParams.get('hideClockSeconds'); - userOptions.hideClockSeconds = isStringBoolean(hideClockSeconds); - const clock = formatTime(time.clock); - - const hideTimerSeconds = searchParams.get('hideTimerSeconds'); - userOptions.hideTimerSeconds = isStringBoolean(hideTimerSeconds); - - const showLeadingZeros = searchParams.get('showLeadingZeros'); - userOptions.removeLeadingZeros = !isStringBoolean(showLeadingZeros); - - const secondarySource = searchParams.get('secondary-src'); + // gather card data + const mainFieldNow = getPropertyValue(eventNow, mainSource) ?? eventNow?.title ?? ''; + const mainFieldNext = getPropertyValue(eventNext, mainSource) ?? eventNext?.title ?? ''; const secondaryTextNow = getPropertyValue(eventNow, secondarySource); const secondaryTextNext = getPropertyValue(eventNext, secondarySource); - const main = searchParams.get('main'); - const mainFieldNow = (main ? getPropertyValue(eventNow, main) : eventNow?.title) ?? ''; - const mainFieldNext = (main ? getPropertyValue(eventNext, main) : eventNext?.title) ?? ''; - - const showOverlay = message.timer.text !== '' && message.timer.visible; - const isPlaying = time.playback !== Playback.Pause; - - const timerIsTimeOfDay = time.timerType === TimerType.Clock; - - const finished = time.phase === TimerPhase.Overtime; - const totalTime = (time.duration ?? 0) + (time.addedTime ?? 0); - - const shouldShowModifiers = time.timerType === TimerType.CountDown || time.countToEnd; - const showEndMessage = shouldShowModifiers && finished && viewSettings.endMessage; - const showProgress = - eventNow !== null && - time.timerType !== TimerType.None && - time.timerType !== TimerType.Clock && - time.playback !== Playback.Stop; - const showFinished = shouldShowModifiers && finished && (shouldShowModifiers || showEndMessage); - const showWarning = shouldShowModifiers && time.phase === TimerPhase.Warning; - const showDanger = shouldShowModifiers && time.phase === TimerPhase.Danger; - const showClock = time.timerType !== TimerType.Clock; - - const secondaryContent = ((): string | undefined => { - if (message.timer.secondarySource === 'aux') { - return getFormattedTimer(auxTimer.current, TimerType.CountDown, getLocalizedString('common.minutes'), { - removeSeconds: userOptions.hideTimerSeconds, - removeLeadingZero: userOptions.removeLeadingZeros, - }); - } - if (message.timer.secondarySource === 'external' && message.external) { - return message.external; - } - return; - })(); - - let timerColor = viewSettings.normalColor; - if (!timerIsTimeOfDay && showProgress && showWarning) timerColor = viewSettings.warningColor; - if (!timerIsTimeOfDay && showProgress && showDanger) timerColor = viewSettings.dangerColor; - + // gather timer data + const totalTime = getTotalTime(time.duration, time.addedTime); + const clock = formatTime(time.clock); const stageTimer = getTimerByType(viewSettings.freezeEnd, time); const display = getFormattedTimer(stageTimer, time.timerType, getLocalizedString('common.minutes'), { - removeSeconds: userOptions.hideTimerSeconds, - removeLeadingZero: userOptions.removeLeadingZeros, + removeSeconds: hideTimerSeconds, + removeLeadingZero: removeLeadingZeros, }); - const stageTimerCharacters = display.replace('/:/g', '').length; + const secondaryContent = getSecondaryDisplay( + message, + auxTimer.current, + getLocalizedString('common.minutes'), + hideTimerSeconds, + removeLeadingZeros, + ); - const baseClasses = `stage-timer ${isMirrored ? 'mirror' : ''}`; - - let timerFontSize = 89 / (stageTimerCharacters - 1); - // we need to shrink the timer if the external is going to be there - if (secondaryContent) { - timerFontSize *= 0.8; - } - const externalFontSize = timerFontSize * 0.4; - const timerContainerClasses = `timer-container ${message.timer.blink ? (showOverlay ? '' : 'blink') : ''}`; - const timerClasses = `timer ${!isPlaying ? 'timer--paused' : ''} ${showFinished ? 'timer--finished' : ''}`; + // gather presentation styles + const timerColour = getTimerColour(viewSettings, showWarning, showDanger); + const { timerFontSize, externalFontSize } = getEstimatedFontSize(display, Boolean(secondaryContent)); + // gather option data const defaultFormat = getDefaultFormat(settings?.timeFormat); const timerOptions = getTimerOptions(defaultFormat, customFields); - const disableProgress = timerIsTimeOfDay || time.timerType === TimerType.None; return ( -
+
{general?.projectLogo && } -
- {!userOptions.hideMessage && ( -
- + +
+ + {!hideMessage && ( +
+ {message.timer.text}
)} - {!userOptions.hideClock && ( -
+ {showClock && ( +
{getLocalizedString('common.time_now')}
)} -
+
{showEndMessage ? (
{viewSettings.endMessage}
) : (
{display}
)}
{secondaryContent}
- {!userOptions.hideProgress && ( + {showProgressBar && (