From db8ed93d41cf486896a9c94ac04abd6c1d802e62 Mon Sep 17 00:00:00 2001 From: Carlos Valente Date: Wed, 28 Aug 2024 19:00:14 +0200 Subject: [PATCH] fix: handle multiple days --- .../features/viewers/timeline/Timeline.tsx | 29 +++++++++---------- .../viewers/timeline/timeline.utils.ts | 8 ++--- packages/types/src/utils/guards.ts | 2 +- .../src/date-utils/checkIsNextDay.test.ts | 7 +++++ .../utils/src/date-utils/checkIsNextDay.ts | 5 ++-- 5 files changed, 29 insertions(+), 22 deletions(-) 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; }