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 ;
}