mirror of
https://github.com/cpvalente/ontime.git
synced 2026-08-04 23:18:01 +00:00
192 lines
5.0 KiB
TypeScript
192 lines
5.0 KiB
TypeScript
import {
|
|
MaybeNumber,
|
|
MessageState,
|
|
OntimeEvent,
|
|
Playback,
|
|
RundownEntries,
|
|
TimerMessage,
|
|
TimerPhase,
|
|
TimerType,
|
|
} from 'ontime-types';
|
|
import { isPlaybackActive } from 'ontime-utils';
|
|
|
|
import { getFormattedTimer, getPropertyValue } from '../common/viewUtils';
|
|
|
|
/**
|
|
* Whether a message should be shown
|
|
*/
|
|
export function getShowMessage(message: TimerMessage): boolean {
|
|
return message.text !== '' && message.visible;
|
|
}
|
|
|
|
/**
|
|
* Whether the playback is playing
|
|
*/
|
|
export function getIsPlaying(playback: Playback): boolean {
|
|
return playback === Playback.Play || playback === Playback.Roll;
|
|
}
|
|
|
|
/**
|
|
* Gets the total time from the duration and added time of an event
|
|
*/
|
|
export function getTotalTime(duration: MaybeNumber, addedTime: MaybeNumber): number {
|
|
return (duration ?? 0) + (addedTime ?? 0);
|
|
}
|
|
|
|
/**
|
|
* Whether the progress bar should be shown for this timer type
|
|
*/
|
|
export function getShowProgressBar(timerType: TimerType) {
|
|
return timerType !== TimerType.None && timerType !== TimerType.Clock;
|
|
}
|
|
|
|
/**
|
|
* Whether the clock should be shown with this timer type
|
|
*/
|
|
export function getShowClock(timerType: TimerType) {
|
|
return timerType !== TimerType.Clock;
|
|
}
|
|
|
|
const fontSizeMap: { [key: number]: number } = {
|
|
4: 28, // 9:01
|
|
5: 28, // -9:01, 10:01, 9 min
|
|
6: 25, // -10:01, 10 min
|
|
8: 18, // 23:01:01
|
|
9: 18, // -23:01:01
|
|
};
|
|
|
|
/**
|
|
* Finds a font size that fits the timer in the screen
|
|
* Unfortunately hand tweaked
|
|
*/
|
|
export function getEstimatedFontSize(stageTimer: string, secondaryContent?: string): number {
|
|
const stageTimerCharacters = stageTimer.length;
|
|
let timerFontSize = (100 / (stageTimerCharacters - 1)) * 1.25;
|
|
|
|
if (fontSizeMap[stageTimerCharacters]) {
|
|
timerFontSize = fontSizeMap[stageTimerCharacters];
|
|
}
|
|
|
|
// we need to shrink the timer if the external is going to be there
|
|
// this number has been tweaked to fit in a landscape mobile screen
|
|
if (secondaryContent) {
|
|
timerFontSize *= 0.6;
|
|
}
|
|
|
|
return timerFontSize;
|
|
}
|
|
|
|
/**
|
|
* which, if any, modifier should be shown at any time
|
|
*/
|
|
export function getShowModifiers(
|
|
timerType: TimerType,
|
|
countToEnd: boolean,
|
|
phase: TimerPhase,
|
|
freezeOvertime: boolean,
|
|
freezeMessage: string,
|
|
hidePhase: boolean,
|
|
) {
|
|
if (hidePhase) {
|
|
return {
|
|
showEndMessage: false,
|
|
showFinished: false,
|
|
showWarning: false,
|
|
showDanger: false,
|
|
};
|
|
}
|
|
|
|
const showModifiers = timerType === TimerType.CountDown || countToEnd;
|
|
if (!showModifiers) {
|
|
return {
|
|
showEndMessage: false,
|
|
showFinished: false,
|
|
showWarning: false,
|
|
showDanger: false,
|
|
};
|
|
}
|
|
|
|
return {
|
|
showEndMessage: phase === TimerPhase.Overtime && freezeOvertime && freezeMessage !== '',
|
|
showFinished: phase === TimerPhase.Overtime,
|
|
showWarning: phase === TimerPhase.Warning,
|
|
showDanger: phase === TimerPhase.Danger,
|
|
};
|
|
}
|
|
|
|
/**
|
|
* What, if anything, should be displayed in the secondary field
|
|
*/
|
|
export function getSecondaryDisplay(
|
|
message: MessageState,
|
|
currentAux: MaybeNumber,
|
|
localisedMinutes: string,
|
|
removeSeconds: boolean,
|
|
removeLeadingZero: boolean,
|
|
hideSecondary: boolean,
|
|
): string | undefined {
|
|
if (hideSecondary) {
|
|
return;
|
|
}
|
|
if (
|
|
message.timer.secondarySource === 'aux1' ||
|
|
message.timer.secondarySource === 'aux2' ||
|
|
message.timer.secondarySource === 'aux3'
|
|
) {
|
|
return getFormattedTimer(currentAux, TimerType.CountDown, localisedMinutes, {
|
|
removeSeconds,
|
|
removeLeadingZero,
|
|
});
|
|
}
|
|
if (message.timer.secondarySource === 'secondary' && message.secondary) {
|
|
return message.secondary;
|
|
}
|
|
return;
|
|
}
|
|
|
|
/**
|
|
* What should we be showing in the cards?
|
|
*/
|
|
export function getCardData(
|
|
eventNow: OntimeEvent | null,
|
|
eventNext: OntimeEvent | null,
|
|
mainSource: keyof OntimeEvent | null | 'none',
|
|
secondarySource: keyof OntimeEvent | null | 'none',
|
|
playback: Playback,
|
|
phase: TimerPhase,
|
|
entries: RundownEntries,
|
|
) {
|
|
if (playback === Playback.Stop) {
|
|
return {
|
|
showNow: false,
|
|
nowMain: undefined,
|
|
nowSecondary: undefined,
|
|
showNext: false,
|
|
nextMain: undefined,
|
|
nextSecondary: undefined,
|
|
};
|
|
}
|
|
|
|
// pending roll timers would be classified as active
|
|
const hasActiveTimer = isPlaybackActive(playback) && phase !== TimerPhase.Pending;
|
|
|
|
// if we are loaded, we show the upcoming event as next
|
|
const nowMain = hasActiveTimer ? getPropertyValue(eventNow, mainSource ?? 'title') : undefined;
|
|
const nowSecondary = hasActiveTimer ? getPropertyValue(eventNow, secondarySource, entries) : undefined;
|
|
const nextMain = hasActiveTimer
|
|
? getPropertyValue(eventNext, mainSource ?? 'title')
|
|
: getPropertyValue(eventNow, mainSource ?? 'title');
|
|
const nextSecondary = hasActiveTimer
|
|
? getPropertyValue(eventNext, secondarySource, entries)
|
|
: getPropertyValue(eventNow, secondarySource, entries);
|
|
|
|
return {
|
|
showNow: mainSource !== 'none' && (Boolean(nowMain) || Boolean(nowSecondary)),
|
|
nowMain,
|
|
nowSecondary,
|
|
showNext: mainSource !== 'none' && (Boolean(nextMain) || Boolean(nextSecondary)),
|
|
nextMain,
|
|
nextSecondary,
|
|
};
|
|
}
|