import { memo, PropsWithChildren, ReactNode, useMemo } from 'react'; import { millisToString } from 'ontime-utils'; import ErrorBoundary from '../../common/components/error-boundary/ErrorBoundary'; import { useIsOnline, useRuntimeOverview, useRuntimePlaybackOverview, useTimer } from '../../common/hooks/useSocket'; import useProjectData from '../../common/hooks-query/useProjectData'; import { cx, enDash, timerPlaceholder } from '../../common/utils/styleUtils'; import { TimeColumn, TimeRow } from './composite/TimeLayout'; import { calculateEndAndDaySpan, formatedTime, getOffsetText } from './overviewUtils'; import style from './Overview.module.scss'; export const EditorOverview = memo(_EditorOverview); function _EditorOverview({ children }: PropsWithChildren) { const { plannedEnd, plannedStart, actualStart, expectedEnd } = useRuntimeOverview(); const [maybePlannedEnd, maybePlannedDaySpan] = useMemo(() => calculateEndAndDaySpan(plannedEnd), [plannedEnd]); const plannedEndText = formatedTime(maybePlannedEnd); const [maybeExpectedEnd, maybeExpectedDaySpan] = useMemo(() => calculateEndAndDaySpan(expectedEnd), [expectedEnd]); const expectedEndText = formatedTime(maybeExpectedEnd); return (
); } export const CuesheetOverview = memo(_CuesheetOverview); function _CuesheetOverview({ children }: PropsWithChildren) { const { plannedEnd, expectedEnd } = useRuntimeOverview(); const [maybePlannedEnd, maybePlannedDaySpan] = useMemo(() => calculateEndAndDaySpan(plannedEnd), [plannedEnd]); const plannedEndText = formatedTime(maybePlannedEnd); const [maybeExpectedEnd, maybeExpectedDaySpan] = useMemo(() => calculateEndAndDaySpan(expectedEnd), [expectedEnd]); const expectedEndText = formatedTime(maybeExpectedEnd); return (
); } interface OverviewWrapperProps { navElements: ReactNode; } function OverviewWrapper({ navElements, children }: PropsWithChildren) { const { isOnline } = useIsOnline(); return (
{navElements}
{children}
); } function TitlesOverview() { const { data } = useProjectData(); if (!data.title && !data.description) { return null; } return (
{data.title}
{data.description}
); } function CurrentBlockOverview() { const { currentBlock, clock } = useRuntimePlaybackOverview(); const timeInBlock = formatedTime(currentBlock.startedAt === null ? null : clock - currentBlock.startedAt); return ( ); } function TimerOverview() { const { current } = useTimer(); const display = millisToString(current, { fallback: timerPlaceholder }); return ; } function ProgressOverview() { const { numEvents, selectedEventIndex } = useRuntimePlaybackOverview(); const current = selectedEventIndex !== null ? selectedEventIndex + 1 : enDash; const ofTotal = numEvents || enDash; const progressText = numEvents ? `${current} of ${ofTotal}` : '-'; return ; } function RuntimeOverview() { const { clock, offset } = useRuntimePlaybackOverview(); const offsetText = getOffsetText(offset); const offsetClasses = offset === null ? undefined : offset <= 0 ? style.behind : style.ahead; return ( <> ); }