diff --git a/apps/client/src/features/viewers/timeline/Timeline.tsx b/apps/client/src/features/viewers/timeline/Timeline.tsx
index 088e1cb53..cd7a9b00f 100644
--- a/apps/client/src/features/viewers/timeline/Timeline.tsx
+++ b/apps/client/src/features/viewers/timeline/Timeline.tsx
@@ -1,6 +1,6 @@
import { memo } from 'react';
import { useViewportSize } from '@mantine/hooks';
-import { isOntimeEvent, MaybeNumber, OntimeEvent } from 'ontime-types';
+import { isOntimeEvent, isPlayableEvent, MaybeNumber, OntimeRundown } from 'ontime-types';
import { checkIsNextDay, dayInMs, getLastEvent, MILLIS_PER_HOUR } from 'ontime-utils';
import { useTimelineOverview } from '../../../common/hooks/useSocket';
@@ -14,7 +14,7 @@ import style from './Timeline.module.scss';
interface TimelineProps {
selectedEventId: string | null;
- rundown: OntimeEvent[];
+ rundown: OntimeRundown;
}
export default memo(Timeline);
@@ -27,15 +27,14 @@ function Timeline(props: TimelineProps) {
if (plannedStart === null || plannedEnd === null) {
return null;
}
-
const { lastEvent } = getLastEvent(rundown);
const startHour = getStartHour(plannedStart);
const endHour = getEndHour(plannedEnd + (lastEvent?.delay ?? 0));
- let hasTimelinePassedMidnight = false;
let previousEventStartTime: MaybeNumber = null;
// we use selectedEventId as a signifier on whether the timeline is live
let eventStatus: ProgressStatus = selectedEventId ? 'done' : 'future';
+ let elapsedDays = 0;
return (
@@ -44,7 +43,7 @@ function Timeline(props: TimelineProps) {
{rundown.map((event) => {
// for now we dont render delays and blocks
- if (!isOntimeEvent(event)) {
+ if (!isOntimeEvent(event) || !isPlayableEvent(event)) {
return null;
}
@@ -56,17 +55,14 @@ function Timeline(props: TimelineProps) {
eventStatus = 'live';
}
- if (!hasTimelinePassedMidnight) {
- // we need to offset the start to account for midnight
- hasTimelinePassedMidnight = previousEventStartTime !== null && event.timeStart < previousEventStartTime;
+ // we only need to check for next day if we have a previous event
+ if (
+ previousEventStartTime !== null &&
+ checkIsNextDay(previousEventStartTime, event.timeStart, event.duration)
+ ) {
+ elapsedDays++;
}
- // TODO: timeline must accumulate normalised time over days
- const isNextDay =
- previousEventStartTime !== null
- ? checkIsNextDay(previousEventStartTime, event.timeStart, event.duration)
- : false;
- const normalisedStart = hasTimelinePassedMidnight || isNextDay ? event.timeStart + dayInMs : event.timeStart;
- previousEventStartTime = normalisedStart;
+ const normalisedStart = event.timeStart + elapsedDays * dayInMs;
const { left: elementLeftPosition, width: elementWidth } = getElementPosition(
startHour * MILLIS_PER_HOUR,
@@ -76,6 +72,9 @@ function Timeline(props: TimelineProps) {
screenWidth,
);
+ // prepare values for next iteration
+ previousEventStartTime = normalisedStart;
+
return (
event.isPublic);
+ scopedRundown = scopedRundown.filter((event) => !isOntimeEvent(event) || event.isPublic);
}
return scopedRundown;
@@ -121,7 +121,7 @@ type UpcomingEvents = {
/**
* Returns upcoming events from current: now, next and followedBy
*/
-export function getUpcomingEvents(events: OntimeEvent[], selectedId: MaybeString): UpcomingEvents {
+export function getUpcomingEvents(events: OntimeRundown, selectedId: MaybeString): UpcomingEvents {
if (events.length === 0) {
return { now: null, next: null, followedBy: null };
}
diff --git a/packages/types/src/utils/guards.ts b/packages/types/src/utils/guards.ts
index 1741c26c5..dee51b607 100644
--- a/packages/types/src/utils/guards.ts
+++ b/packages/types/src/utils/guards.ts
@@ -11,7 +11,7 @@ export function isOntimeEvent(event: MaybeEvent): event is OntimeEvent {
}
export function isPlayableEvent(event: OntimeEvent): event is PlayableEvent {
- return !event.skip;
+ return !event?.skip;
}
export function isOntimeDelay(event: MaybeEvent): event is OntimeDelay {
diff --git a/packages/utils/src/date-utils/checkIsNextDay.test.ts b/packages/utils/src/date-utils/checkIsNextDay.test.ts
index e71c2a81a..8a0a7782a 100644
--- a/packages/utils/src/date-utils/checkIsNextDay.test.ts
+++ b/packages/utils/src/date-utils/checkIsNextDay.test.ts
@@ -57,4 +57,11 @@ describe('checkIsNextDay', () => {
const timeStart = 2 * MILLIS_PER_HOUR;
expect(checkIsNextDay(previousStart, timeStart, previousDuration)).toBeTruthy();
});
+
+ it('should account for normalised start over multiple days', () => {
+ const previousStart = 90000000; // 25:00:00
+ const previousDuration = 1 * MILLIS_PER_HOUR;
+ const timeStart = 0;
+ expect(checkIsNextDay(previousStart, timeStart, previousDuration)).toBeTruthy();
+ });
});
diff --git a/packages/utils/src/date-utils/checkIsNextDay.ts b/packages/utils/src/date-utils/checkIsNextDay.ts
index 93a0492c6..e6a9732f3 100644
--- a/packages/utils/src/date-utils/checkIsNextDay.ts
+++ b/packages/utils/src/date-utils/checkIsNextDay.ts
@@ -24,8 +24,9 @@ export function checkIsNextDay(previousStart: number, timeStart: number, previou
return false;
}
- if (timeStart <= previousStart) {
- const normalisedPreviousEnd = previousStart + previousDuration;
+ const cappedStart = previousStart % dayInMs;
+ if (timeStart <= cappedStart) {
+ const normalisedPreviousEnd = cappedStart + previousDuration;
if (normalisedPreviousEnd === dayInMs) {
return true;
}