diff --git a/apps/client/src/common/components/title-card/TitleCard.tsx b/apps/client/src/common/components/title-card/TitleCard.tsx
index e2d79d587..6613f895b 100644
--- a/apps/client/src/common/components/title-card/TitleCard.tsx
+++ b/apps/client/src/common/components/title-card/TitleCard.tsx
@@ -5,7 +5,7 @@ import { useTranslation } from '../../../translation/TranslationProvider';
import './TitleCard.scss';
interface TitleCardProps {
- title: string;
+ title?: string;
label?: 'now' | 'next';
secondary?: string;
className?: string;
diff --git a/apps/client/src/views/timer/Timer.tsx b/apps/client/src/views/timer/Timer.tsx
index e92b55153..ae14a9e5e 100644
--- a/apps/client/src/views/timer/Timer.tsx
+++ b/apps/client/src/views/timer/Timer.tsx
@@ -18,12 +18,13 @@ 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 } from '../../features/viewers/common/viewUtils';
+import { getFormattedTimer, getTimerByType } from '../../features/viewers/common/viewUtils';
import { useTranslation } from '../../translation/TranslationProvider';
import { MotionTitleCard, titleVariants } from './timer.animations';
import { getTimerOptions, useTimerOptions } from './timer.options';
import {
+ getCardData,
getEstimatedFontSize,
getIsPlaying,
getSecondaryDisplay,
@@ -84,10 +85,14 @@ export default function Timer(props: TimerProps) {
const showProgressBar = !hideProgress && getShowProgressBar(time.timerType);
// 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 { showNow, nowMain, nowSecondary, showNext, nextMain, nextSecondary } = getCardData(
+ eventNow,
+ eventNext,
+ mainSource,
+ secondarySource,
+ time.playback,
+ time.phase,
+ );
// gather timer data
const totalTime = getTotalTime(time.duration, time.addedTime);
@@ -183,7 +188,7 @@ export default function Timer(props: TimerProps) {
{!hideCards && (
<>
- {eventNow?.title && (
+ {showNow && (
)}
- {eventNext?.title && (
+ {showNext && (
)}
diff --git a/apps/client/src/views/timer/timer.utils.ts b/apps/client/src/views/timer/timer.utils.ts
index 240a2c493..b46bc5a3f 100644
--- a/apps/client/src/views/timer/timer.utils.ts
+++ b/apps/client/src/views/timer/timer.utils.ts
@@ -1,6 +1,16 @@
-import { MaybeNumber, MessageState, Playback, TimerMessage, TimerPhase, TimerType, ViewSettings } from 'ontime-types';
+import {
+ MaybeNumber,
+ MessageState,
+ OntimeEvent,
+ Playback,
+ TimerMessage,
+ TimerPhase,
+ TimerType,
+ ViewSettings,
+} from 'ontime-types';
+import { isPlaybackActive } from 'ontime-utils';
-import { getFormattedTimer } from '../../features/viewers/common/viewUtils';
+import { getFormattedTimer, getPropertyValue } from '../../features/viewers/common/viewUtils';
/**
* Whether a message should be shown
@@ -126,3 +136,48 @@ export function getSecondaryDisplay(
}
return;
}
+
+/**
+ * What should we be showing in the cards?
+ */
+export function getCardData(
+ eventNow: OntimeEvent | null,
+ eventNext: OntimeEvent | null,
+ mainSource: keyof OntimeEvent | null,
+ secondarySource: keyof OntimeEvent | null,
+ playback: Playback,
+ phase: TimerPhase,
+) {
+ 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) : undefined;
+ const nextMain = hasActiveTimer
+ ? getPropertyValue(eventNext, mainSource ?? 'title')
+ : getPropertyValue(eventNow, mainSource ?? 'title');
+ const nextSecondary = hasActiveTimer
+ ? getPropertyValue(eventNext, secondarySource)
+ : getPropertyValue(eventNow, secondarySource);
+
+ return {
+ showNow: Boolean(nowMain) || Boolean(nowSecondary),
+ nowMain,
+ nowSecondary,
+ showNext: Boolean(nextMain) || Boolean(nextSecondary),
+ nextMain,
+ nextSecondary,
+ };
+}