import { useMemo } from 'react'; import { TbCalendar, TbCalendarClock, TbCalendarDown, TbCalendarStar, TbFlagDown, TbFlagStar } from 'react-icons/tb'; import { isOntimeBlock, OntimeBlock, OntimeEvent, TimerType } from 'ontime-types'; import { isPlaybackActive, millisToString } from 'ontime-utils'; import Tooltip from '../../../common/components/tooltip/Tooltip'; import { useClock, useCurrentBlockId, useNextFlag, useRuntimeOverview, useRuntimePlaybackOverview, useTimer, } from '../../../common/hooks/useSocket'; import { useEntry } from '../../../common/hooks-query/useRundown'; import { getOffsetState, getOffsetText } from '../../../common/utils/offset'; import { cx, enDash, timerPlaceholder } from '../../../common/utils/styleUtils'; import { formatTime, useTimeUntilStart } from '../../../common/utils/time'; import { calculateEndAndDaySpan, formattedTime } from '../overview.utils'; import { TimeColumn } from './TimeLayout'; import style from './TimeElements.module.scss'; export function StartTimes() { const { plannedEnd, plannedStart, actualStart, expectedEnd } = useRuntimeOverview(); const [maybePlannedEnd, maybePlannedDaySpan] = useMemo(() => calculateEndAndDaySpan(plannedEnd), [plannedEnd]); const [maybeExpectedEnd, maybeExpectedDaySpan] = useMemo(() => calculateEndAndDaySpan(expectedEnd), [expectedEnd]); const muted = maybeExpectedEnd === null; return (
Start
} /> {formatTime(plannedStart)}
} /> {formattedTime(actualStart)}
End
} /> {maybePlannedDaySpan >= 0 ? ( } > {formatTime(maybePlannedEnd)} ) : ( {formatTime(maybePlannedEnd)} )}
} /> {maybeExpectedEnd !== null && maybeExpectedDaySpan >= 0 ? ( } > {formattedTime(maybeExpectedEnd)} ) : ( {formattedTime(maybeExpectedEnd)} )}
); } export function MetadataTimes() { return (
); } function GroupTimes() { const { blockStartedAt, clock, blockExpectedEnd } = useRuntimePlaybackOverview(); const { currentBlockId } = useCurrentBlockId(); const entry = useEntry(currentBlockId); if (!currentBlockId) { return (
Group
} /> {timerPlaceholder}
} /> {timerPlaceholder}
); } const remainingBlockDuration = (() => { if (blockStartedAt === null || !entry) return timerPlaceholder; if (!isOntimeBlock(entry)) return timerPlaceholder; return formattedTime(blockStartedAt + entry.duration - clock, 3, TimerType.CountDown); })(); const timeUntilBlockEnd = (() => { if (blockExpectedEnd === null) return timerPlaceholder; return formattedTime(blockExpectedEnd - clock, 3, TimerType.CountDown); })(); const groupTitle = (entry as OntimeBlock | null)?.title || 'Group'; return (
{groupTitle}
} /> {remainingBlockDuration}
} /> {timeUntilBlockEnd}
); } function FlagTimes() { const { clock } = useClock(); const { nextFlag } = useNextFlag(); const entry = useEntry(nextFlag?.id ?? null); // TODO(v4): can we make a good approximation of time until next flag? const timeUntil = useTimeUntilStart({ timeStart: nextFlag?.start ?? 0, delay: 0, dayOffset: 0, totalGap: 0, isLinkedToLoaded: true, }); if (!nextFlag) { return (
Flag
} /> {timerPlaceholder}
} /> {timerPlaceholder}
); } const muted = nextFlag === null; const flagTitle = (entry as OntimeEvent | null)?.title || 'Flag'; const timeToNextFlag = nextFlag.start - clock; const display = millisToString(timeToNextFlag, { fallback: timerPlaceholder }); const timeUntilDisplay = millisToString(timeUntil, { fallback: timerPlaceholder }); return (
{flagTitle}
} /> {display}
} /> {timeUntilDisplay}
); } export function ProgressOverview() { const { numEvents, selectedEventIndex } = useRuntimePlaybackOverview(); const current = selectedEventIndex !== null ? selectedEventIndex + 1 : enDash; const progressText = numEvents ? `${current} of ${numEvents || enDash}` : enDash; return ; } export function OffsetOverview() { const { offset, playback } = useRuntimePlaybackOverview(); const isPlaying = isPlaybackActive(playback); const correctedOffset = offset * -1; const offsetState = getOffsetState(correctedOffset); const offsetClasses = cx([style.offset, offsetState && style[offsetState]]); const offsetText = getOffsetText(isPlaying ? correctedOffset : null); return ; } export function ClockOverview() { const { clock } = useClock(); return ; } export function TimerOverview() { const { current } = useTimer(); const display = millisToString(current, { fallback: timerPlaceholder }); return ; }