diff --git a/meteor/server/api/rest/v1/ingest.ts b/meteor/server/api/rest/v1/ingest.ts index 32fc262a36a..f1a1ff4018e 100644 --- a/meteor/server/api/rest/v1/ingest.ts +++ b/meteor/server/api/rest/v1/ingest.ts @@ -164,6 +164,8 @@ class IngestServerAPI implements IngestRestAPI { playlistExternalId: rawRundown.playlistExternalId, studioId: unprotectString(rawRundown.studioId), name: rawRundown.name, + type: rawRundown.source.type, + timing: rawRundown.timing, } } @@ -175,6 +177,12 @@ class IngestServerAPI implements IngestRestAPI { rank: rawSegment._rank, rundownId: unprotectString(rawSegment.rundownId), isHidden: rawSegment.isHidden, + timing: rawSegment.segmentTiming + ? { + budgetDuration: rawSegment.segmentTiming.budgetDuration, + countdownType: rawSegment.segmentTiming.countdownType, + } + : undefined, } } diff --git a/meteor/server/lib/rest/v1/ingest.ts b/meteor/server/lib/rest/v1/ingest.ts index 8924b95be58..b4c94148bb7 100644 --- a/meteor/server/lib/rest/v1/ingest.ts +++ b/meteor/server/lib/rest/v1/ingest.ts @@ -250,6 +250,13 @@ export type RundownResponse = { playlistId: string playlistExternalId?: string name: string + type?: string + timing?: { + type: string + expectedStart?: number + expectedDuration?: number + expectedEnd?: number + } } export type SegmentResponse = { @@ -259,6 +266,10 @@ export type SegmentResponse = { name: string rank: number isHidden?: boolean + timing?: { + budgetDuration?: number + countdownType?: string + } } export type PartResponse = { diff --git a/packages/blueprints-integration/src/documents/rundown.ts b/packages/blueprints-integration/src/documents/rundown.ts index f8c08405731..f6994645c0f 100644 --- a/packages/blueprints-integration/src/documents/rundown.ts +++ b/packages/blueprints-integration/src/documents/rundown.ts @@ -22,12 +22,6 @@ export interface IBlueprintRundown): IB privateData: clone(rundown.privateData), publicData: clone(rundown.publicData), playlistExternalId: rundown.playlistExternalId, - endOfRundownIsShowBreak: rundown.endOfRundownIsShowBreak, _id: unprotectString(rundown._id), showStyleVariantId: unprotectString(rundown.showStyleVariantId), playlistId: unprotectString(rundown.playlistId), diff --git a/packages/meteor-lib/src/collections/RundownLayouts.ts b/packages/meteor-lib/src/collections/RundownLayouts.ts index 864155ed63b..f06dd353f39 100644 --- a/packages/meteor-lib/src/collections/RundownLayouts.ts +++ b/packages/meteor-lib/src/collections/RundownLayouts.ts @@ -44,7 +44,6 @@ export enum RundownLayoutElementType { NEXT_INFO = 'next_info', PLAYLIST_START_TIMER = 'playlist_start_timer', PLAYLIST_END_TIMER = 'playlist_end_timer', - NEXT_BREAK_TIMING = 'next_break_timing', SEGMENT_TIMING = 'segment_timing', PART_TIMING = 'part_timing', TEXT_LABEL = 'text_label', @@ -146,10 +145,6 @@ export interface RundownLayoutPlaylistEndTimer extends RundownLayoutElementBase hidePlannedEnd: boolean } -export interface RundownLayoutNextBreakTiming extends RundownLayoutElementBase { - type: RundownLayoutElementType.NEXT_BREAK_TIMING -} - export interface RundownLayoutSegmentTiming extends RundownLayoutElementBase, RequiresActiveLayers { type: RundownLayoutElementType.SEGMENT_TIMING timingType: 'count_down' | 'count_up' @@ -267,7 +262,6 @@ export type DashboardLayoutAdLibRegion = DashboardPanel export type DashboardLayoutNextInfo = DashboardPanel export type DashboardLayoutPlaylistStartTimer = DashboardPanel -export type DashboardLayoutNextBreakTiming = DashboardPanel export type DashboardLayoutPlaylistEndTimer = DashboardPanel export type DashboardLayoutSegmentCountDown = DashboardPanel export type DashboardLayoutPartCountDown = DashboardPanel @@ -331,8 +325,6 @@ export interface RundownViewLayout extends RundownLayoutBase { liveLineProps?: RequiresActiveLayers /** Hide the rundown divider header in playlists */ hideRundownDivider: boolean - /** Show breaks in segment timeline list */ - showBreaksAsSegments: boolean /** Only count down to the segment if it contains pieces on these layers */ countdownToSegmentRequireLayers: string[] /** Always show planned segment duration instead of counting up/down when the segment is live */ diff --git a/packages/openapi/api/definitions/ingest.yaml b/packages/openapi/api/definitions/ingest.yaml index fbc828f249b..30865c10cf7 100644 --- a/packages/openapi/api/definitions/ingest.yaml +++ b/packages/openapi/api/definitions/ingest.yaml @@ -1238,12 +1238,12 @@ components: timing: type: object properties: - expectedStart: - type: number - description: Epoch timestamp in milliseconds. - expectedEnd: + budgetDuration: type: number - description: Epoch timestamp in milliseconds. + description: Budget duration of this segment, in milliseconds + countdownType: + type: string + description: Defines the behavior of countdowns during this segment. additionalProperties: false required: - id diff --git a/packages/openapi/src/__tests__/ingest.spec.ts b/packages/openapi/src/__tests__/ingest.spec.ts index a674b114dbf..07b9270cf8a 100644 --- a/packages/openapi/src/__tests__/ingest.spec.ts +++ b/packages/openapi/src/__tests__/ingest.spec.ts @@ -198,8 +198,8 @@ describe('Ingest API', () => { expect(typeof segment.name).toBe('string') expect(typeof segment.rank).toBe('number') expect(typeof segment.timing).toBe('object') - expect(typeof segment.timing.expectedStart).toBe('number') - expect(typeof segment.timing.expectedEnd).toBe('number') + expect(['number', 'undefined']).toContain(typeof segment.timing?.budgetDuration) + expect(['string', 'undefined']).toContain(typeof segment.timing?.countdownType) segmentIds.push(segment.externalId) }) }) @@ -218,16 +218,14 @@ describe('Ingest API', () => { expect(segment).toHaveProperty('name') expect(segment).toHaveProperty('rank') expect(segment).toHaveProperty('timing') - expect(segment.timing).toHaveProperty('expectedStart') - expect(segment.timing).toHaveProperty('expectedEnd') expect(typeof segment.id).toBe('string') expect(typeof segment.externalId).toBe('string') expect(typeof segment.rundownId).toBe('string') expect(typeof segment.name).toBe('string') expect(typeof segment.rank).toBe('number') expect(typeof segment.timing).toBe('object') - expect(typeof segment.timing.expectedStart).toBe('number') - expect(typeof segment.timing.expectedEnd).toBe('number') + expect(['number', 'undefined']).toContain(typeof segment.timing?.budgetDuration) + expect(['string', 'undefined']).toContain(typeof segment.timing?.countdownType) }) const segment = { diff --git a/packages/openapi/src/generated/openapi.yaml b/packages/openapi/src/generated/openapi.yaml index aaf2806a2e6..3cb37499042 100644 --- a/packages/openapi/src/generated/openapi.yaml +++ b/packages/openapi/src/generated/openapi.yaml @@ -6725,12 +6725,12 @@ paths: timing: type: object properties: - expectedStart: - type: number - description: Epoch timestamp in milliseconds. - expectedEnd: + budgetDuration: type: number - description: Epoch timestamp in milliseconds. + description: Budget duration of this segment, in milliseconds + countdownType: + type: string + description: Defines the behavior of countdowns during this segment. additionalProperties: false required: - id @@ -7061,12 +7061,12 @@ paths: timing: type: object properties: - expectedStart: - type: number - description: Epoch timestamp in milliseconds. - expectedEnd: + budgetDuration: type: number - description: Epoch timestamp in milliseconds. + description: Budget duration of this segment, in milliseconds + countdownType: + type: string + description: Defines the behavior of countdowns during this segment. additionalProperties: false required: - id diff --git a/packages/webui/src/client/lib/__tests__/rundownTiming.test.ts b/packages/webui/src/client/lib/__tests__/rundownTiming.test.ts index 3dc640af210..c3bb75501b2 100644 --- a/packages/webui/src/client/lib/__tests__/rundownTiming.test.ts +++ b/packages/webui/src/client/lib/__tests__/rundownTiming.test.ts @@ -5,7 +5,7 @@ import { import { ForceQuickLoopAutoNext } from '@sofie-automation/shared-lib/dist/core/model/StudioSettings' import type { DBPart } from '@sofie-automation/corelib/dist/dataModel/Part' import type { DBSegment } from '@sofie-automation/corelib/dist/dataModel/Segment' -import type { DBRundown } from '@sofie-automation/corelib/dist/dataModel/Rundown' + import { literal } from '@sofie-automation/corelib/dist/lib' import { unprotectString, protectString } from '@sofie-automation/shared-lib/dist/lib/protectedString' import { RundownTimingCalculator, type RundownTimingContext, findPartInstancesInQuickLoop } from '../rundownTiming.js' @@ -71,30 +71,6 @@ function makeMockSegment(id: string, rank: number, rundownId: string, timing?: S }) } -function makeMockRundown(id: string, playlist: DBRundownPlaylist) { - playlist.rundownIdsInOrder.push(protectString(id)) - return literal({ - _id: protectString(id), - externalId: id, - timing: { - type: 'none' as any, - }, - studioId: protectString('studio0'), - showStyleBaseId: protectString(''), - showStyleVariantId: protectString('variant0'), - created: 0, - modified: 0, - importVersions: {} as any, - name: 'test', - source: { - type: 'nrcs', - peripheralDeviceId: protectString(''), - nrcsName: 'mockNRCS', - }, - playlistId: playlist._id, - }) -} - function convertPartsToPartInstances(parts: DBPart[]): PartInstance[] { return parts.map((part) => wrapPartToTemporaryInstance(protectString(''), part)) } @@ -122,19 +98,7 @@ describe('rundown Timing Calculator', () => { const playlist: DBRundownPlaylist = makeMockPlaylist() const partInstances: PartInstance[] = [] const segmentsMap: Map = new Map() - const partInstancesMap: Map = new Map() - const result = timing.updateDurations( - 0, - false, - playlist, - [], - undefined, - partInstances, - partInstancesMap, - segmentsMap, - DEFAULT_DURATION, - {} - ) + const result = timing.updateDurations(0, false, playlist, partInstances, segmentsMap, DEFAULT_DURATION, {}) expect(result).toEqual( literal({ currentPartInstanceId: null, @@ -155,9 +119,7 @@ describe('rundown Timing Calculator', () => { partsInQuickLoop: {}, remainingPlaylistDuration: 0, totalPlaylistDuration: 0, - breakIsLastRundown: undefined, remainingTimeOnCurrentPart: undefined, - rundownsBeforeNextBreak: undefined, }) ) }) @@ -167,7 +129,6 @@ describe('rundown Timing Calculator', () => { const playlist: DBRundownPlaylist = makeMockPlaylist() playlist.timing = { type: 'forward-time' as any, - expectedStart: 0, expectedDuration: 40000, } const rundownId = 'rundown1' @@ -182,21 +143,7 @@ describe('rundown Timing Calculator', () => { parts.push(makeMockPart('part3', 0, rundownId, segmentId2, { expectedDuration: 1000 })) parts.push(makeMockPart('part4', 0, rundownId, segmentId2, { expectedDuration: 1000 })) const partInstances = convertPartsToPartInstances(parts) - const partInstancesMap: Map = new Map() - const rundown = makeMockRundown(rundownId, playlist) - const rundowns = [rundown] - const result = timing.updateDurations( - 0, - false, - playlist, - rundowns, - undefined, - partInstances, - partInstancesMap, - segmentsMap, - DEFAULT_DURATION, - {} - ) + const result = timing.updateDurations(0, false, playlist, partInstances, segmentsMap, DEFAULT_DURATION, {}) expect(result).toEqual( literal({ currentPartInstanceId: null, @@ -256,9 +203,7 @@ describe('rundown Timing Calculator', () => { partsInQuickLoop: {}, remainingPlaylistDuration: 4000, totalPlaylistDuration: 4000, - breakIsLastRundown: undefined, remainingTimeOnCurrentPart: undefined, - rundownsBeforeNextBreak: undefined, }) ) }) @@ -268,7 +213,6 @@ describe('rundown Timing Calculator', () => { const playlist: DBRundownPlaylist = makeMockPlaylist() playlist.timing = { type: 'forward-time' as any, - expectedStart: 0, expectedDuration: 40000, } const rundownId = 'rundown1' @@ -283,21 +227,7 @@ describe('rundown Timing Calculator', () => { parts.push(makeMockPart('part3', 0, rundownId, segmentId2, { expectedDuration: 1000 })) parts.push(makeMockPart('part4', 0, rundownId, segmentId2, { expectedDuration: 1000 })) const partInstances = convertPartsToPartInstances(parts) - const partInstancesMap: Map = new Map() - const rundown = makeMockRundown(rundownId, playlist) - const rundowns = [rundown] - const result = timing.updateDurations( - 0, - false, - playlist, - rundowns, - undefined, - partInstances, - partInstancesMap, - segmentsMap, - DEFAULT_DURATION, - {} - ) + const result = timing.updateDurations(0, false, playlist, partInstances, segmentsMap, DEFAULT_DURATION, {}) expect(result).toEqual( literal({ currentPartInstanceId: null, @@ -357,9 +287,7 @@ describe('rundown Timing Calculator', () => { partsInQuickLoop: {}, remainingPlaylistDuration: 4000, totalPlaylistDuration: 4000, - breakIsLastRundown: undefined, remainingTimeOnCurrentPart: undefined, - rundownsBeforeNextBreak: undefined, }) ) }) @@ -369,7 +297,6 @@ describe('rundown Timing Calculator', () => { const playlist: DBRundownPlaylist = makeMockPlaylist() playlist.timing = { type: 'forward-time' as any, - expectedStart: 0, expectedDuration: 40000, } const rundownId1 = 'rundown1' @@ -385,22 +312,7 @@ describe('rundown Timing Calculator', () => { parts.push(makeMockPart('part3', 0, rundownId2, segmentId2, { expectedDuration: 1000 })) parts.push(makeMockPart('part4', 0, rundownId2, segmentId2, { expectedDuration: 1000 })) const partInstances = convertPartsToPartInstances(parts) - const partInstancesMap: Map = new Map() - const rundown1 = makeMockRundown(rundownId1, playlist) - const rundown2 = makeMockRundown(rundownId1, playlist) - const rundowns = [rundown1, rundown2] - const result = timing.updateDurations( - 0, - false, - playlist, - rundowns, - undefined, - partInstances, - partInstancesMap, - segmentsMap, - DEFAULT_DURATION, - {} - ) + const result = timing.updateDurations(0, false, playlist, partInstances, segmentsMap, DEFAULT_DURATION, {}) expect(result).toEqual( literal({ currentPartInstanceId: null, @@ -462,9 +374,7 @@ describe('rundown Timing Calculator', () => { partsInQuickLoop: {}, remainingPlaylistDuration: 4000, totalPlaylistDuration: 4000, - breakIsLastRundown: undefined, remainingTimeOnCurrentPart: undefined, - rundownsBeforeNextBreak: undefined, }) ) }) @@ -475,7 +385,6 @@ describe('rundown Timing Calculator', () => { const playlist: DBRundownPlaylist = makeMockPlaylist() playlist.timing = { type: 'forward-time' as any, - expectedStart: 0, expectedDuration: 40000, } const rundownId1 = 'rundown1' @@ -514,21 +423,7 @@ describe('rundown Timing Calculator', () => { }) ) const partInstances = convertPartsToPartInstances(parts) - const partInstancesMap: Map = new Map() - const rundown = makeMockRundown(rundownId1, playlist) - const rundowns = [rundown] - const result = timing.updateDurations( - 0, - false, - playlist, - rundowns, - undefined, - partInstances, - partInstancesMap, - segmentsMap, - DEFAULT_DURATION, - {} - ) + const result = timing.updateDurations(0, false, playlist, partInstances, segmentsMap, DEFAULT_DURATION, {}) expect(result).toEqual( literal({ currentPartInstanceId: null, @@ -588,9 +483,7 @@ describe('rundown Timing Calculator', () => { partsInQuickLoop: {}, remainingPlaylistDuration: 4000, totalPlaylistDuration: 4000, - breakIsLastRundown: undefined, remainingTimeOnCurrentPart: undefined, - rundownsBeforeNextBreak: undefined, }) ) }) @@ -600,7 +493,6 @@ describe('rundown Timing Calculator', () => { const playlist: DBRundownPlaylist = makeMockPlaylist() playlist.timing = { type: 'forward-time' as any, - expectedStart: 0, expectedDuration: 40000, } const rundownId1 = 'rundown1' @@ -669,16 +561,11 @@ describe('rundown Timing Calculator', () => { manuallySelected: false, consumesQueuedSegmentId: false, } - const rundown = makeMockRundown(rundownId1, playlist) - const rundowns = [rundown] const result = timing.updateDurations( 3500, false, playlist, - rundowns, - rundown, partInstances, - partInstancesMap, segmentsMap, DEFAULT_DURATION, {} @@ -743,10 +630,7 @@ describe('rundown Timing Calculator', () => { partsInQuickLoop: {}, remainingPlaylistDuration: 3500, totalPlaylistDuration: 7000, - breakIsLastRundown: false, remainingTimeOnCurrentPart: 2500, - rundownsBeforeNextBreak: [], - nextRundownAnchor: undefined, }) ) }) @@ -756,7 +640,6 @@ describe('rundown Timing Calculator', () => { const playlist: DBRundownPlaylist = makeMockPlaylist() playlist.timing = { type: 'forward-time' as any, - expectedStart: 0, expectedDuration: 40000, } const rundownId1 = 'rundown1' @@ -825,16 +708,12 @@ describe('rundown Timing Calculator', () => { manuallySelected: false, consumesQueuedSegmentId: false, } - const rundown = makeMockRundown(rundownId1, playlist) - const rundowns = [rundown] const result = timing.updateDurations( 10000, false, playlist, - rundowns, - rundown, partInstances, - partInstancesMap, + segmentsMap, DEFAULT_DURATION, {} @@ -899,10 +778,7 @@ describe('rundown Timing Calculator', () => { partsInQuickLoop: {}, remainingPlaylistDuration: 1000, totalPlaylistDuration: 7000, - breakIsLastRundown: false, remainingTimeOnCurrentPart: -4000, - rundownsBeforeNextBreak: [], - nextRundownAnchor: undefined, }) ) }) @@ -914,7 +790,6 @@ describe('rundown Timing Calculator', () => { const playlist: DBRundownPlaylist = makeMockPlaylist() playlist.timing = { type: 'forward-time' as any, - expectedStart: 0, expectedDuration: 40000, } const rundownId = 'rundown1' @@ -929,17 +804,12 @@ describe('rundown Timing Calculator', () => { parts.push(makeMockPart('part3', 0, rundownId, segmentId2, { expectedDuration: 1000 })) parts.push(makeMockPart('part4', 0, rundownId, segmentId2, { expectedDuration: 1000 })) const partInstances = convertPartsToPartInstances(parts) - const partInstancesMap: Map = new Map() - const rundown = makeMockRundown(rundownId, playlist) - const rundowns = [rundown] const result = timing.updateDurations( 0, false, playlist, - rundowns, - undefined, partInstances, - partInstancesMap, + segmentsMap, DEFAULT_NONZERO_DURATION, {} @@ -1003,9 +873,7 @@ describe('rundown Timing Calculator', () => { partsInQuickLoop: {}, remainingPlaylistDuration: 4000, totalPlaylistDuration: 4000, - breakIsLastRundown: undefined, remainingTimeOnCurrentPart: undefined, - rundownsBeforeNextBreak: undefined, }) ) }) @@ -1015,7 +883,6 @@ describe('rundown Timing Calculator', () => { const playlist: DBRundownPlaylist = makeMockPlaylist() playlist.timing = { type: 'forward-time' as any, - expectedStart: 0, expectedDuration: 40000, } const rundownId1 = 'rundown1' @@ -1059,17 +926,12 @@ describe('rundown Timing Calculator', () => { }) ) const partInstances = convertPartsToPartInstances(parts) - const partInstancesMap: Map = new Map() - const rundown = makeMockRundown(rundownId1, playlist) - const rundowns = [rundown] const result = timing.updateDurations( 0, false, playlist, - rundowns, - undefined, partInstances, - partInstancesMap, + segmentsMap, DEFAULT_NONZERO_DURATION, {} @@ -1140,9 +1002,7 @@ describe('rundown Timing Calculator', () => { partsInQuickLoop: {}, remainingPlaylistDuration: 5000, totalPlaylistDuration: 5000, - breakIsLastRundown: undefined, remainingTimeOnCurrentPart: undefined, - rundownsBeforeNextBreak: undefined, }) ) }) @@ -1153,7 +1013,6 @@ describe('rundown Timing Calculator', () => { const playlist: DBRundownPlaylist = makeMockPlaylist() playlist.timing = { type: 'forward-time' as any, - expectedStart: 0, expectedDuration: 40000, } const rundownId1 = 'rundown1' @@ -1186,17 +1045,12 @@ describe('rundown Timing Calculator', () => { ) parts.push(makeMockPart('part4', 0, rundownId1, segmentId2, { expectedDuration: 1000 })) const partInstances = convertPartsToPartInstances(parts) - const partInstancesMap: Map = new Map() - const rundown = makeMockRundown(rundownId1, playlist) - const rundowns = [rundown] const result = timing.updateDurations( 0, false, playlist, - rundowns, - undefined, partInstances, - partInstancesMap, + segmentsMap, DEFAULT_DURATION, {} @@ -1260,9 +1114,7 @@ describe('rundown Timing Calculator', () => { partsInQuickLoop: {}, remainingPlaylistDuration: 8000, totalPlaylistDuration: 8000, - breakIsLastRundown: undefined, remainingTimeOnCurrentPart: undefined, - rundownsBeforeNextBreak: undefined, }) ) }) @@ -1272,7 +1124,6 @@ describe('rundown Timing Calculator', () => { const playlist: DBRundownPlaylist = makeMockPlaylist() playlist.timing = { type: 'forward-time' as any, - expectedStart: 0, expectedDuration: 40000, } const rundownId1 = 'rundown1' @@ -1321,22 +1172,9 @@ describe('rundown Timing Calculator', () => { plannedStartedPlayback: 1000, // start after part1's expectedDuration } const partInstances = [partInstance1, partInstance2, ...convertPartsToPartInstances([parts[2], parts[3]])] - const partInstancesMap: Map = new Map() - const rundown = makeMockRundown(rundownId1, playlist) - const rundowns = [rundown] + // at t = 0 - const result = timing.updateDurations( - 0, - false, - playlist, - rundowns, - undefined, - partInstances, - partInstancesMap, - segmentsMap, - DEFAULT_DURATION, - {} - ) + const result = timing.updateDurations(0, false, playlist, partInstances, segmentsMap, DEFAULT_DURATION, {}) expect(result).toEqual( literal({ currentPartInstanceId: null, @@ -1396,9 +1234,7 @@ describe('rundown Timing Calculator', () => { }, remainingPlaylistDuration: 8000, totalPlaylistDuration: 8000, - breakIsLastRundown: undefined, remainingTimeOnCurrentPart: undefined, - rundownsBeforeNextBreak: undefined, }) ) }) @@ -1408,7 +1244,6 @@ describe('rundown Timing Calculator', () => { const playlist: DBRundownPlaylist = makeMockPlaylist() playlist.timing = { type: 'forward-time' as any, - expectedStart: 0, expectedDuration: 40000, } const rundownId1 = 'rundown1' @@ -1476,22 +1311,9 @@ describe('rundown Timing Calculator', () => { fromPartKeepalive: 0, } const partInstances = [partInstance1, partInstance2, ...convertPartsToPartInstances([parts[2], parts[3]])] - const partInstancesMap: Map = new Map() - const rundown = makeMockRundown(rundownId1, playlist) - const rundowns = [rundown] + // at t = 0 - const result = timing.updateDurations( - 3000, - false, - playlist, - rundowns, - undefined, - partInstances, - partInstancesMap, - segmentsMap, - DEFAULT_DURATION, - {} - ) + const result = timing.updateDurations(3000, false, playlist, partInstances, segmentsMap, DEFAULT_DURATION, {}) expect(result).toEqual( literal({ currentPartInstanceId: null, @@ -1551,945 +1373,32 @@ describe('rundown Timing Calculator', () => { }, remainingPlaylistDuration: 8000, totalPlaylistDuration: 8000, - breakIsLastRundown: undefined, remainingTimeOnCurrentPart: undefined, - rundownsBeforeNextBreak: undefined, }) ) }) - it('Back-time: Can find the next expectedStart rundown anchor when it is in a future segment', () => { + it('Passes partsInQuickLoop', () => { const timing = new RundownTimingCalculator() const playlist: DBRundownPlaylist = makeMockPlaylist() - playlist.timing = { - type: 'back-time' as any, - expectedDuration: 4000, - expectedEnd: 4000, - } - const rundownId1 = 'rundown1' + const rundownId = 'rundown1' const segmentId1 = 'segment1' const segmentId2 = 'segment2' const segmentsMap: Map = new Map() - segmentsMap.set( - protectString(segmentId1), - makeMockSegment(segmentId1, 0, rundownId1, { expectedStart: 0 }) - ) - segmentsMap.set( - protectString(segmentId2), - makeMockSegment(segmentId2, 0, rundownId1, { expectedStart: 2000, expectedEnd: 4000 }) - ) + segmentsMap.set(protectString(segmentId1), makeMockSegment(segmentId1, 0, rundownId)) + segmentsMap.set(protectString(segmentId2), makeMockSegment(segmentId2, 0, rundownId)) const parts: DBPart[] = [] - parts.push( - makeMockPart('part1', 0, rundownId1, segmentId1, { - expectedDuration: 1000, - }) - ) - parts.push( - makeMockPart('part2', 0, rundownId1, segmentId1, { - expectedDuration: 1000, - }) - ) - parts.push( - makeMockPart('part3', 0, rundownId1, segmentId2, { - expectedDuration: 1000, - }) - ) - parts.push(makeMockPart('part4', 0, rundownId1, segmentId2, { expectedDuration: 1000 })) - const partInstancesMap: Map = new Map( - parts.map((part) => { - return [part._id, wrapPartToTemporaryInstance(protectString('active'), part)] - }) - ) - const partInstances = Array.from(partInstancesMap.values()) - partInstancesMap.get(parts[0]._id)!.timings = { - duration: 1000, - take: 0, - plannedStartedPlayback: 0, - plannedStoppedPlayback: 1000, - } - partInstancesMap.get(parts[1]._id)!.timings = { - take: 1000, - plannedStartedPlayback: 1000, - } - const currentPartInstanceId = partInstancesMap.get(parts[1]._id)!._id - const nextPartInstanceId = partInstancesMap.get(parts[2]._id)!._id - playlist.currentPartInfo = { - partInstanceId: currentPartInstanceId, - rundownId: protectString(rundownId1), - manuallySelected: false, - consumesQueuedSegmentId: false, - } - playlist.nextPartInfo = { - partInstanceId: nextPartInstanceId, - rundownId: protectString(rundownId1), - manuallySelected: false, - consumesQueuedSegmentId: false, - } - const rundown = makeMockRundown(rundownId1, playlist) - const rundowns = [rundown] + parts.push(makeMockPart('part1', 0, rundownId, segmentId1, { expectedDuration: 1000 })) + parts.push(makeMockPart('part2', 0, rundownId, segmentId1, { expectedDuration: 1000 })) + parts.push(makeMockPart('part3', 0, rundownId, segmentId2, { expectedDuration: 1000 })) + parts.push(makeMockPart('part4', 0, rundownId, segmentId2, { expectedDuration: 1000 })) + const partInstances = convertPartsToPartInstances(parts) const result = timing.updateDurations( - 1500, + 0, false, playlist, - rundowns, - rundown, partInstances, - partInstancesMap, - segmentsMap, - DEFAULT_DURATION, - {} - ) - expect(result).toEqual( - literal({ - currentPartInstanceId, - isLowResolution: false, - asDisplayedPlaylistDuration: 4000, - asPlayedPlaylistDuration: 4000, - currentPartWillAutoNext: false, - currentSegmentId: protectString(segmentId1), - currentTime: 1500, - rundownExpectedDurations: { - [rundownId1]: 4000, - }, - rundownAsPlayedDurations: { - [rundownId1]: 4000, - }, - partCountdown: { - part1: null, - part2: null, - part3: 500, - part4: 1500, - }, - partDisplayDurations: { - part1: 1000, - part2: 1000, - part3: 1000, - part4: 1000, - }, - partDisplayStartsAt: { - part1: 0, - part2: 1000, - part3: 2000, - part4: 3000, - }, - partDurations: { - part1: 1000, - part2: 1000, - part3: 1000, - part4: 1000, - }, - partExpectedDurations: { - part1: 1000, - part2: 1000, - part3: 1000, - part4: 1000, - }, - partPlayed: { - part1: 1000, - part2: 500, - part3: 0, - part4: 0, - }, - partStartsAt: { - part1: 0, - part2: 1000, - part3: 2000, - part4: 3000, - }, - partsInQuickLoop: {}, - remainingPlaylistDuration: 2500, - totalPlaylistDuration: 4000, - breakIsLastRundown: false, - remainingTimeOnCurrentPart: 500, - rundownsBeforeNextBreak: [], - nextRundownAnchor: 2000, - }) - ) - }) - it('Back-time: Can find the next expectedEnd rundown anchor when it is a future segment', () => { - const timing = new RundownTimingCalculator() - const playlist: DBRundownPlaylist = makeMockPlaylist() - playlist.timing = { - type: 'back-time' as any, - expectedDuration: 4000, - expectedEnd: 4000, - } - const rundownId1 = 'rundown1' - const segmentId1 = 'segment1' - const segmentId2 = 'segment2' - const segmentsMap: Map = new Map() - segmentsMap.set( - protectString(segmentId1), - makeMockSegment(segmentId1, 0, rundownId1, { expectedStart: 0 }) - ) - segmentsMap.set( - protectString(segmentId2), - makeMockSegment(segmentId2, 0, rundownId1, { expectedStart: 2000, expectedEnd: 4000 }) - ) - const parts: DBPart[] = [] - parts.push( - makeMockPart('part1', 0, rundownId1, segmentId1, { - expectedDuration: 1000, - }) - ) - parts.push( - makeMockPart('part2', 0, rundownId1, segmentId1, { - expectedDuration: 1000, - }) - ) - parts.push( - makeMockPart('part3', 0, rundownId1, segmentId2, { - expectedDuration: 1000, - }) - ) - parts.push(makeMockPart('part4', 0, rundownId1, segmentId2, { expectedDuration: 1000 })) - const partInstancesMap: Map = new Map( - parts.map((part) => { - return [part._id, wrapPartToTemporaryInstance(protectString('active'), part)] - }) - ) - const partInstances = Array.from(partInstancesMap.values()) - partInstancesMap.get(parts[0]._id)!.timings = { - duration: 1000, - take: 0, - plannedStartedPlayback: 0, - plannedStoppedPlayback: 1000, - } - partInstancesMap.get(parts[1]._id)!.timings = { - take: 1000, - plannedStartedPlayback: 1000, - } - const currentPartInstanceId = partInstancesMap.get(parts[1]._id)!._id - const nextPartInstanceId = partInstancesMap.get(parts[2]._id)!._id - playlist.currentPartInfo = { - partInstanceId: currentPartInstanceId, - rundownId: protectString(rundownId1), - manuallySelected: false, - consumesQueuedSegmentId: false, - } - playlist.nextPartInfo = { - partInstanceId: nextPartInstanceId, - rundownId: protectString(rundownId1), - manuallySelected: false, - consumesQueuedSegmentId: false, - } - const rundown = makeMockRundown(rundownId1, playlist) - const rundowns = [rundown] - const result = timing.updateDurations( - 3500, - false, - playlist, - rundowns, - rundown, - partInstances, - partInstancesMap, - segmentsMap, - DEFAULT_DURATION, - {} - ) - expect(result).toEqual( - literal({ - currentPartInstanceId, - isLowResolution: false, - asDisplayedPlaylistDuration: 5500, - asPlayedPlaylistDuration: 5500, - currentPartWillAutoNext: false, - currentSegmentId: protectString(segmentId1), - currentTime: 3500, - rundownExpectedDurations: { - [rundownId1]: 4000, - }, - rundownAsPlayedDurations: { - [rundownId1]: 5500, - }, - partCountdown: { - part1: null, - part2: null, - part3: 0, - part4: 1000, - }, - partDisplayDurations: { - part1: 1000, - part2: 2500, - part3: 1000, - part4: 1000, - }, - partDisplayStartsAt: { - part1: 0, - part2: 1000, - part3: 3500, - part4: 4500, - }, - partDurations: { - part1: 1000, - part2: 2500, - part3: 1000, - part4: 1000, - }, - partExpectedDurations: { - part1: 1000, - part2: 1000, - part3: 1000, - part4: 1000, - }, - partPlayed: { - part1: 1000, - part2: 2500, - part3: 0, - part4: 0, - }, - partStartsAt: { - part1: 0, - part2: 1000, - part3: 3500, - part4: 4500, - }, - partsInQuickLoop: {}, - remainingPlaylistDuration: 2000, - totalPlaylistDuration: 4000, - breakIsLastRundown: false, - remainingTimeOnCurrentPart: -1500, - rundownsBeforeNextBreak: [], - nextRundownAnchor: 4000, - }) - ) - }) - - it('Back-time: Can find the next expectedEnd rundown anchor when it is the current segment', () => { - const timing = new RundownTimingCalculator() - const playlist: DBRundownPlaylist = makeMockPlaylist() - playlist.timing = { - type: 'back-time' as any, - expectedDuration: 4000, - expectedEnd: 4000, - } - const rundownId1 = 'rundown1' - const segmentId1 = 'segment1' - const segmentId2 = 'segment2' - const segmentsMap: Map = new Map() - segmentsMap.set( - protectString(segmentId1), - makeMockSegment(segmentId1, 0, rundownId1, { expectedStart: 0 }) - ) - segmentsMap.set( - protectString(segmentId2), - makeMockSegment(segmentId2, 0, rundownId1, { expectedStart: 2000, expectedEnd: 3000 }) - ) - const parts: DBPart[] = [] - parts.push( - makeMockPart('part1', 0, rundownId1, segmentId1, { - expectedDuration: 1000, - }) - ) - parts.push( - makeMockPart('part2', 0, rundownId1, segmentId1, { - expectedDuration: 1000, - }) - ) - parts.push( - makeMockPart('part3', 0, rundownId1, segmentId2, { - expectedDuration: 1000, - }) - ) - parts.push(makeMockPart('part4', 0, rundownId1, segmentId2, { expectedDuration: 1000 })) - const partInstancesMap: Map = new Map( - parts.map((part) => { - return [part._id, wrapPartToTemporaryInstance(protectString('active'), part)] - }) - ) - const partInstances = Array.from(partInstancesMap.values()) - partInstancesMap.get(parts[0]._id)!.timings = { - duration: 1000, - take: 0, - plannedStartedPlayback: 0, - plannedStoppedPlayback: 1000, - } - partInstancesMap.get(parts[1]._id)!.timings = { - duration: 1000, - take: 1000, - plannedStartedPlayback: 1000, - plannedStoppedPlayback: 2000, - } - partInstancesMap.get(parts[2]._id)!.timings = { - take: 2000, - plannedStartedPlayback: 2000, - } - const currentPartInstanceId = partInstancesMap.get(parts[2]._id)!._id - const nextPartInstanceId = partInstancesMap.get(parts[3]._id)!._id - playlist.currentPartInfo = { - partInstanceId: currentPartInstanceId, - rundownId: protectString(rundownId1), - manuallySelected: false, - consumesQueuedSegmentId: false, - } - playlist.nextPartInfo = { - partInstanceId: nextPartInstanceId, - rundownId: protectString(rundownId1), - manuallySelected: false, - consumesQueuedSegmentId: false, - } - const rundown = makeMockRundown(rundownId1, playlist) - const rundowns = [rundown] - const result = timing.updateDurations( - 2500, - false, - playlist, - rundowns, - rundown, - partInstances, - partInstancesMap, - segmentsMap, - DEFAULT_DURATION, - {} - ) - expect(result).toEqual( - literal({ - currentPartInstanceId, - isLowResolution: false, - asDisplayedPlaylistDuration: 4000, - asPlayedPlaylistDuration: 4000, - currentPartWillAutoNext: false, - currentSegmentId: protectString(segmentId2), - currentTime: 2500, - rundownExpectedDurations: { - [rundownId1]: 4000, - }, - rundownAsPlayedDurations: { - [rundownId1]: 4000, - }, - partCountdown: { - part1: null, - part2: null, - part3: null, - part4: 500, - }, - partDisplayDurations: { - part1: 1000, - part2: 1000, - part3: 1000, - part4: 1000, - }, - partDisplayStartsAt: { - part1: 0, - part2: 1000, - part3: 2000, - part4: 3000, - }, - partDurations: { - part1: 1000, - part2: 1000, - part3: 1000, - part4: 1000, - }, - partExpectedDurations: { - part1: 1000, - part2: 1000, - part3: 1000, - part4: 1000, - }, - partPlayed: { - part1: 1000, - part2: 1000, - part3: 500, - part4: 0, - }, - partStartsAt: { - part1: 0, - part2: 1000, - part3: 2000, - part4: 3000, - }, - partsInQuickLoop: {}, - remainingPlaylistDuration: 1500, - totalPlaylistDuration: 4000, - breakIsLastRundown: false, - remainingTimeOnCurrentPart: 500, - rundownsBeforeNextBreak: [], - nextRundownAnchor: 3000, - }) - ) - }) - - it('Forward-time: Can find the next expectedStart rundown anchor when it is in a future segment', () => { - const timing = new RundownTimingCalculator() - const playlist: DBRundownPlaylist = makeMockPlaylist() - playlist.timing = { - type: 'forward-time' as any, - expectedStart: 0, - expectedDuration: 4000, - } - const rundownId1 = 'rundown1' - const segmentId1 = 'segment1' - const segmentId2 = 'segment2' - const segmentsMap: Map = new Map() - segmentsMap.set( - protectString(segmentId1), - makeMockSegment(segmentId1, 0, rundownId1, { expectedStart: 0 }) - ) - segmentsMap.set( - protectString(segmentId2), - makeMockSegment(segmentId2, 0, rundownId1, { expectedStart: 2000, expectedEnd: 4000 }) - ) - const parts: DBPart[] = [] - parts.push( - makeMockPart('part1', 0, rundownId1, segmentId1, { - expectedDuration: 1000, - }) - ) - parts.push( - makeMockPart('part2', 0, rundownId1, segmentId1, { - expectedDuration: 1000, - }) - ) - parts.push( - makeMockPart('part3', 0, rundownId1, segmentId2, { - expectedDuration: 1000, - }) - ) - parts.push(makeMockPart('part4', 0, rundownId1, segmentId2, { expectedDuration: 1000 })) - const partInstancesMap: Map = new Map( - parts.map((part) => { - return [part._id, wrapPartToTemporaryInstance(protectString('active'), part)] - }) - ) - partInstancesMap.get(parts[0]._id)!.timings = { - duration: 1000, - take: 0, - plannedStartedPlayback: 0, - plannedStoppedPlayback: 1000, - } - partInstancesMap.get(parts[1]._id)!.timings = { - take: 1000, - plannedStartedPlayback: 1000, - } - const partInstances = Array.from(partInstancesMap.values()) - const currentPartInstanceId = partInstancesMap.get(parts[1]._id)!._id - const nextPartInstanceId = partInstancesMap.get(parts[2]._id)!._id - playlist.currentPartInfo = { - partInstanceId: currentPartInstanceId, - rundownId: protectString(rundownId1), - manuallySelected: false, - consumesQueuedSegmentId: false, - } - playlist.nextPartInfo = { - partInstanceId: nextPartInstanceId, - rundownId: protectString(rundownId1), - manuallySelected: false, - consumesQueuedSegmentId: false, - } - const rundown = makeMockRundown(rundownId1, playlist) - const rundowns = [rundown] - const result = timing.updateDurations( - 1500, - false, - playlist, - rundowns, - rundown, - partInstances, - partInstancesMap, - segmentsMap, - DEFAULT_DURATION, - {} - ) - expect(result).toEqual( - literal({ - currentPartInstanceId, - isLowResolution: false, - asDisplayedPlaylistDuration: 4000, - asPlayedPlaylistDuration: 4000, - currentPartWillAutoNext: false, - currentSegmentId: protectString(segmentId1), - currentTime: 1500, - rundownExpectedDurations: { - [rundownId1]: 4000, - }, - rundownAsPlayedDurations: { - [rundownId1]: 4000, - }, - partCountdown: { - part1: null, - part2: null, - part3: 500, - part4: 1500, - }, - partDisplayDurations: { - part1: 1000, - part2: 1000, - part3: 1000, - part4: 1000, - }, - partDisplayStartsAt: { - part1: 0, - part2: 1000, - part3: 2000, - part4: 3000, - }, - partDurations: { - part1: 1000, - part2: 1000, - part3: 1000, - part4: 1000, - }, - partExpectedDurations: { - part1: 1000, - part2: 1000, - part3: 1000, - part4: 1000, - }, - partPlayed: { - part1: 1000, - part2: 500, - part3: 0, - part4: 0, - }, - partStartsAt: { - part1: 0, - part2: 1000, - part3: 2000, - part4: 3000, - }, - partsInQuickLoop: {}, - remainingPlaylistDuration: 2500, - totalPlaylistDuration: 4000, - breakIsLastRundown: false, - remainingTimeOnCurrentPart: 500, - rundownsBeforeNextBreak: [], - nextRundownAnchor: 2000, - }) - ) - }) - - it('Forward-time: Can find the next expectedEnd rundown anchor when it is a future segment', () => { - const timing = new RundownTimingCalculator() - const playlist: DBRundownPlaylist = makeMockPlaylist() - playlist.timing = { - type: 'forward-time' as any, - expectedStart: 0, - expectedDuration: 4000, - } - const rundownId1 = 'rundown1' - const segmentId1 = 'segment1' - const segmentId2 = 'segment2' - const segmentsMap: Map = new Map() - segmentsMap.set( - protectString(segmentId1), - makeMockSegment(segmentId1, 0, rundownId1, { expectedStart: 0 }) - ) - segmentsMap.set( - protectString(segmentId2), - makeMockSegment(segmentId2, 0, rundownId1, { expectedStart: 2000, expectedEnd: 4000 }) - ) - const parts: DBPart[] = [] - parts.push( - makeMockPart('part1', 0, rundownId1, segmentId1, { - expectedDuration: 1000, - }) - ) - parts.push( - makeMockPart('part2', 0, rundownId1, segmentId1, { - expectedDuration: 1000, - }) - ) - parts.push( - makeMockPart('part3', 0, rundownId1, segmentId2, { - expectedDuration: 1000, - }) - ) - parts.push(makeMockPart('part4', 0, rundownId1, segmentId2, { expectedDuration: 1000 })) - const partInstancesMap: Map = new Map( - parts.map((part) => { - return [part._id, wrapPartToTemporaryInstance(protectString('active'), part)] - }) - ) - const partInstances = Array.from(partInstancesMap.values()) - partInstancesMap.get(parts[0]._id)!.timings = { - duration: 1000, - take: 0, - plannedStartedPlayback: 0, - plannedStoppedPlayback: 1000, - } - partInstancesMap.get(parts[1]._id)!.timings = { - take: 1000, - plannedStartedPlayback: 1000, - } - const currentPartInstanceId = partInstancesMap.get(parts[1]._id)!._id - const nextPartInstanceId = partInstancesMap.get(parts[2]._id)!._id - playlist.currentPartInfo = { - partInstanceId: currentPartInstanceId, - rundownId: protectString(rundownId1), - manuallySelected: false, - consumesQueuedSegmentId: false, - } - playlist.nextPartInfo = { - partInstanceId: nextPartInstanceId, - rundownId: protectString(rundownId1), - manuallySelected: false, - consumesQueuedSegmentId: false, - } - const rundown = makeMockRundown(rundownId1, playlist) - const rundowns = [rundown] - const result = timing.updateDurations( - 3500, - false, - playlist, - rundowns, - rundown, - partInstances, - partInstancesMap, - segmentsMap, - DEFAULT_DURATION, - {} - ) - expect(result).toEqual( - literal({ - currentPartInstanceId, - isLowResolution: false, - asDisplayedPlaylistDuration: 5500, - asPlayedPlaylistDuration: 5500, - currentPartWillAutoNext: false, - currentSegmentId: protectString(segmentId1), - currentTime: 3500, - rundownExpectedDurations: { - [rundownId1]: 4000, - }, - rundownAsPlayedDurations: { - [rundownId1]: 5500, - }, - partCountdown: { - part1: null, - part2: null, - part3: 0, - part4: 1000, - }, - partDisplayDurations: { - part1: 1000, - part2: 2500, - part3: 1000, - part4: 1000, - }, - partDisplayStartsAt: { - part1: 0, - part2: 1000, - part3: 3500, - part4: 4500, - }, - partDurations: { - part1: 1000, - part2: 2500, - part3: 1000, - part4: 1000, - }, - partExpectedDurations: { - part1: 1000, - part2: 1000, - part3: 1000, - part4: 1000, - }, - partPlayed: { - part1: 1000, - part2: 2500, - part3: 0, - part4: 0, - }, - partStartsAt: { - part1: 0, - part2: 1000, - part3: 3500, - part4: 4500, - }, - partsInQuickLoop: {}, - remainingPlaylistDuration: 2000, - totalPlaylistDuration: 4000, - breakIsLastRundown: false, - remainingTimeOnCurrentPart: -1500, - rundownsBeforeNextBreak: [], - nextRundownAnchor: 4000, - }) - ) - }) - - it('Forward-time: Can find the next expectedEnd rundown anchor when it is the current segment', () => { - const timing = new RundownTimingCalculator() - const playlist: DBRundownPlaylist = makeMockPlaylist() - playlist.timing = { - type: 'forward-time' as any, - expectedStart: 0, - expectedEnd: 4000, - } - const rundownId1 = 'rundown1' - const segmentId1 = 'segment1' - const segmentId2 = 'segment2' - const segmentsMap: Map = new Map() - segmentsMap.set( - protectString(segmentId1), - makeMockSegment(segmentId1, 0, rundownId1, { expectedStart: 0 }) - ) - segmentsMap.set( - protectString(segmentId2), - makeMockSegment(segmentId2, 0, rundownId1, { expectedStart: 2000, expectedEnd: 3000 }) - ) - const parts: DBPart[] = [] - parts.push( - makeMockPart('part1', 0, rundownId1, segmentId1, { - expectedDuration: 1000, - }) - ) - parts.push( - makeMockPart('part2', 0, rundownId1, segmentId1, { - expectedDuration: 1000, - }) - ) - parts.push( - makeMockPart('part3', 0, rundownId1, segmentId2, { - expectedDuration: 1000, - }) - ) - parts.push(makeMockPart('part4', 0, rundownId1, segmentId2, { expectedDuration: 1000 })) - const partInstancesMap: Map = new Map( - parts.map((part) => { - return [part._id, wrapPartToTemporaryInstance(protectString('active'), part)] - }) - ) - partInstancesMap.get(parts[0]._id)!.timings = { - duration: 1000, - take: 0, - plannedStartedPlayback: 0, - plannedStoppedPlayback: 1000, - } - partInstancesMap.get(parts[1]._id)!.timings = { - duration: 1000, - take: 1000, - plannedStartedPlayback: 1000, - plannedStoppedPlayback: 2000, - } - partInstancesMap.get(parts[2]._id)!.timings = { - take: 2000, - plannedStartedPlayback: 2000, - } - const partInstances = Array.from(partInstancesMap.values()) - const currentPartInstanceId = partInstancesMap.get(parts[2]._id)!._id - const nextPartInstanceId = partInstancesMap.get(parts[3]._id)!._id - playlist.currentPartInfo = { - partInstanceId: currentPartInstanceId, - rundownId: protectString(rundownId1), - manuallySelected: false, - consumesQueuedSegmentId: false, - } - playlist.nextPartInfo = { - partInstanceId: nextPartInstanceId, - rundownId: protectString(rundownId1), - manuallySelected: false, - consumesQueuedSegmentId: false, - } - const rundown = makeMockRundown(rundownId1, playlist) - const rundowns = [rundown] - const result = timing.updateDurations( - 2500, - false, - playlist, - rundowns, - rundown, - partInstances, - partInstancesMap, - segmentsMap, - DEFAULT_DURATION, - {} - ) - expect(result).toEqual( - literal({ - currentPartInstanceId, - isLowResolution: false, - asDisplayedPlaylistDuration: 4000, - asPlayedPlaylistDuration: 4000, - currentPartWillAutoNext: false, - currentSegmentId: protectString(segmentId2), - currentTime: 2500, - rundownExpectedDurations: { - [rundownId1]: 4000, - }, - rundownAsPlayedDurations: { - [rundownId1]: 4000, - }, - partCountdown: { - part1: null, - part2: null, - part3: null, - part4: 500, - }, - partDisplayDurations: { - part1: 1000, - part2: 1000, - part3: 1000, - part4: 1000, - }, - partDisplayStartsAt: { - part1: 0, - part2: 1000, - part3: 2000, - part4: 3000, - }, - partDurations: { - part1: 1000, - part2: 1000, - part3: 1000, - part4: 1000, - }, - partExpectedDurations: { - part1: 1000, - part2: 1000, - part3: 1000, - part4: 1000, - }, - partPlayed: { - part1: 1000, - part2: 1000, - part3: 500, - part4: 0, - }, - partStartsAt: { - part1: 0, - part2: 1000, - part3: 2000, - part4: 3000, - }, - partsInQuickLoop: {}, - remainingPlaylistDuration: 1500, - totalPlaylistDuration: 4000, - breakIsLastRundown: false, - remainingTimeOnCurrentPart: 500, - rundownsBeforeNextBreak: [], - nextRundownAnchor: 3000, - }) - ) - }) - - it('Passes partsInQuickLoop', () => { - const timing = new RundownTimingCalculator() - const playlist: DBRundownPlaylist = makeMockPlaylist() - const rundownId = 'rundown1' - const segmentId1 = 'segment1' - const segmentId2 = 'segment2' - const segmentsMap: Map = new Map() - segmentsMap.set(protectString(segmentId1), makeMockSegment(segmentId1, 0, rundownId)) - segmentsMap.set(protectString(segmentId2), makeMockSegment(segmentId2, 0, rundownId)) - const parts: DBPart[] = [] - parts.push(makeMockPart('part1', 0, rundownId, segmentId1, { expectedDuration: 1000 })) - parts.push(makeMockPart('part2', 0, rundownId, segmentId1, { expectedDuration: 1000 })) - parts.push(makeMockPart('part3', 0, rundownId, segmentId2, { expectedDuration: 1000 })) - parts.push(makeMockPart('part4', 0, rundownId, segmentId2, { expectedDuration: 1000 })) - const partInstances = convertPartsToPartInstances(parts) - const partInstancesMap: Map = new Map() - const rundown = makeMockRundown(rundownId, playlist) - const rundowns = [rundown] - const result = timing.updateDurations( - 0, - false, - playlist, - rundowns, - undefined, - partInstances, - partInstancesMap, segmentsMap, DEFAULT_DURATION, { diff --git a/packages/webui/src/client/lib/rundownLayouts.ts b/packages/webui/src/client/lib/rundownLayouts.ts index 590c2c21c17..9783a322f84 100644 --- a/packages/webui/src/client/lib/rundownLayouts.ts +++ b/packages/webui/src/client/lib/rundownLayouts.ts @@ -24,7 +24,6 @@ import { type RundownLayoutExternalFrame, type RundownLayoutFilterBase, type RundownLayoutMiniRundown, - type RundownLayoutNextBreakTiming, type RundownLayoutNextInfo, type RundownLayoutPartName, type RundownLayoutPartTiming, @@ -319,7 +318,6 @@ export namespace RundownLayoutsAPI { RundownLayoutElementType.TEXT_LABEL, RundownLayoutElementType.SEGMENT_TIMING, RundownLayoutElementType.PLAYLIST_END_TIMER, - RundownLayoutElementType.NEXT_BREAK_TIMING, RundownLayoutElementType.TIME_OF_DAY, RundownLayoutElementType.PLAYLIST_NAME, RundownLayoutElementType.STUDIO_NAME, @@ -409,10 +407,6 @@ export namespace RundownLayoutsAPI { return element.type === RundownLayoutElementType.PLAYLIST_END_TIMER } - export function isNextBreakTiming(element: RundownLayoutElementBase): element is RundownLayoutNextBreakTiming { - return element.type === RundownLayoutElementType.NEXT_BREAK_TIMING - } - export function isSegmentTiming(element: RundownLayoutElementBase): element is RundownLayoutSegmentTiming { return element.type === RundownLayoutElementType.SEGMENT_TIMING } diff --git a/packages/webui/src/client/lib/rundownPlaylistUtil.ts b/packages/webui/src/client/lib/rundownPlaylistUtil.ts index 5a91dce5d43..e0898a16165 100644 --- a/packages/webui/src/client/lib/rundownPlaylistUtil.ts +++ b/packages/webui/src/client/lib/rundownPlaylistUtil.ts @@ -25,16 +25,7 @@ export class RundownPlaylistClientUtil { selector?: MongoQuery, options?: FindOptions ): Array<{ - rundown: Pick< - Rundown, - | '_id' - | 'name' - | 'playlistId' - | 'timing' - | 'showStyleBaseId' - | 'showStyleVariantId' - | 'endOfRundownIsShowBreak' - > + rundown: Pick segments: DBSegment[] }> { const rundowns = RundownPlaylistCollectionUtil.getRundownsOrdered(playlist, undefined, { @@ -44,7 +35,6 @@ export class RundownPlaylistClientUtil { timing: 1, showStyleBaseId: 1, showStyleVariantId: 1, - endOfRundownIsShowBreak: 1, }, }) const segments = Segments.find( diff --git a/packages/webui/src/client/lib/rundownTiming.ts b/packages/webui/src/client/lib/rundownTiming.ts index e8a5be4fd8f..ac476e075c7 100644 --- a/packages/webui/src/client/lib/rundownTiming.ts +++ b/packages/webui/src/client/lib/rundownTiming.ts @@ -24,7 +24,7 @@ import { import { objectFromEntries } from '@sofie-automation/shared-lib/dist/lib/lib' import { getCurrentTime } from './systemTime.js' import { Settings } from '../lib/Settings.js' -import type { Rundown } from '@sofie-automation/corelib/dist/dataModel/Rundown' + import type { DBSegment } from '@sofie-automation/corelib/dist/dataModel/Segment' import { CountdownType } from '@sofie-automation/blueprints-integration' import { RundownUtils } from './rundown.js' @@ -38,11 +38,6 @@ import { // Minimum duration that a part can be assigned. Used by gap parts to allow them to "compress" to indicate time running out. const MINIMAL_NONZERO_DURATION = 1 -interface BreakProps { - rundownsBeforeNextBreak: Rundown[] - breakIsLastRundown: boolean -} - type CalculateTimingsPartInstance = Pick< PartInstance, '_id' | 'isTemporary' | 'segmentId' | 'segmentPlayoutId' | 'orphaned' | 'timings' | 'part' @@ -75,10 +70,7 @@ export class RundownTimingCalculator { private partDisplayDurationsNoPlayback: Record = {} private displayDurationGroups: Record = {} private segmentAsPlayedDurations: Record = {} - private breakProps: { - props: BreakProps | undefined - state: string | undefined - } = { props: undefined, state: undefined } + /** * Segment is untimed if all of it's Parts are set to `untimed` */ @@ -90,10 +82,8 @@ export class RundownTimingCalculator { * @param {number} now * @param {boolean} isLowResolution * @param {(DBRundownPlaylist | undefined)} playlist - * @param {Rundown[]} rundowns - * @param {(Rundown | undefined)} currentRundown * @param {CalculateTimingsPartInstance[]} partInstances - * @param {Map} partInstancesMap + * @param {Map} segmentsMap * @param {number} [defaultDuration] * @return {*} {RundownTimingContext} * @memberof RundownTimingCalculator @@ -102,10 +92,7 @@ export class RundownTimingCalculator { now: number, isLowResolution: boolean, playlist: DBRundownPlaylist | undefined, - rundowns: Rundown[], - currentRundown: Rundown | undefined, partInstances: CalculateTimingsPartInstance[], - partInstancesMap: Map, segmentsMap: Map, /** Fallback duration for Parts that have no as-played duration of their own. */ defaultDuration: number = Settings.defaultDisplayDuration, @@ -128,8 +115,6 @@ export class RundownTimingCalculator { const rundownExpectedDurations: Record = {} const rundownAsPlayedDurations: Record = {} - let rundownsBeforeNextBreak: Rundown[] | undefined - let breakIsLastRundown: boolean | undefined let liveSegmentIds: { segmentId: SegmentId; segmentPlayoutId: SegmentPlayoutId } | undefined Object.keys(this.displayDurationGroups).forEach((key) => delete this.displayDurationGroups[key]) @@ -141,18 +126,10 @@ export class RundownTimingCalculator { let currentAIndex = -1 let lastSegmentIds: { segmentId: SegmentId; segmentPlayoutId: SegmentPlayoutId } | undefined = undefined - let nextRundownAnchor: number | undefined = undefined const entirePlaylistIsLooping = isEntirePlaylistLooping(playlist) if (playlist) { - const breakProps = currentRundown ? this.getRundownsBeforeNextBreak(rundowns, currentRundown) : undefined - - if (breakProps) { - rundownsBeforeNextBreak = breakProps.rundownsBeforeNextBreak - breakIsLastRundown = breakProps.breakIsLastRundown - } - if (!playlist.nextPartInfo) { this.nextSegmentId = undefined } @@ -171,7 +148,9 @@ export class RundownTimingCalculator { : undefined if (!lastSegmentIds || partInstance.segmentId !== lastSegmentIds.segmentId) { + // untimed segment: pattern is to add all segments as candidates to untimed here, then remove them once we see any timed part within it, later this.untimedSegments.add(partInstance.segmentId) + if (liveSegmentIds && lastSegmentIds && lastSegmentIds.segmentId === liveSegmentIds.segmentId) { const liveSegment = segmentsMap.get(liveSegmentIds.segmentId) @@ -223,6 +202,7 @@ export class RundownTimingCalculator { const partIsUntimed = partInstance.part.untimed || false + // untimed segment algorithm: we have considered all segments as candidates to untimed segments, and now we remove the ones that aren't (the ones that contain a timed part) if (!partIsUntimed) { this.untimedSegments.delete(partInstance.segmentId) } @@ -517,27 +497,10 @@ export class RundownTimingCalculator { if (!partsInQuickLoop[unprotectString(this.linearParts[i][0])] && !entirePlaylistIsLooping) { this.linearParts[i][1] = null // we use null to express 'will not probably be played out, if played in order' } - } else if (i === currentAIndex) { - if (nextRundownAnchor === undefined) { - nextRundownAnchor = getSegmentRundownAnchorFromPart( - this.linearParts[i][0], - partInstancesMap, - segmentsMap, - now - ) - } } else if (i === nextAIndex) { // this is a calculation for the next line, which is basically how much there is left of the current line localAccum = this.linearParts[i][1] || 0 // if there is no current line, rebase following lines to the next line this.linearParts[i][1] = currentRemaining - if (nextRundownAnchor === undefined) { - nextRundownAnchor = getSegmentRundownAnchorFromPart( - this.linearParts[i][0], - partInstancesMap, - segmentsMap, - now - ) - } } else { // these are lines after next line // we take whatever value this line has, subtract the value as set on the Next Part @@ -549,15 +512,6 @@ export class RundownTimingCalculator { if (!partsInQuickLoop[unprotectString(this.linearParts[i][0])] && !entirePlaylistIsLooping) { timeTillEndLoop = timeTillEndLoop ?? this.linearParts[i][1] ?? undefined } - - if (nextRundownAnchor === undefined) { - nextRundownAnchor = getSegmentRundownAnchorFromPart( - this.linearParts[i][0], - partInstancesMap, - segmentsMap, - now - ) - } } } // at this point the localAccumulator should be the sum of waits before the next line @@ -575,15 +529,6 @@ export class RundownTimingCalculator { // add the wait from this part to the waitInLoop (the lookup here should still work by the definition of a "wait") waitInLoop += waitPerPart[unprotectString(this.linearParts[i][0])] ?? 0 - - if (nextRundownAnchor === undefined) { - nextRundownAnchor = getSegmentRundownAnchorFromPart( - this.linearParts[i][0], - partInstancesMap, - segmentsMap, - now - ) - } } } @@ -682,53 +627,10 @@ export class RundownTimingCalculator { remainingTimeOnCurrentPart, remainingBudgetOnCurrentSegment, currentPartWillAutoNext, - rundownsBeforeNextBreak, - breakIsLastRundown, isLowResolution, - nextRundownAnchor, partsInQuickLoop, }) } - - private getRundownsBeforeNextBreak( - orderedRundowns: Rundown[], - currentRundown: Rundown | undefined - ): BreakProps | undefined { - const currentState = orderedRundowns.map((r) => r.endOfRundownIsShowBreak ?? '_').join('') - if (this.breakProps.state !== currentState) { - this.recalculateBreaks(orderedRundowns, currentRundown) - } - - this.breakProps.state = currentState - return this.breakProps.props - } - - private recalculateBreaks(orderedRundowns: Rundown[], currentRundown: Rundown | undefined) { - if (!currentRundown) { - this.breakProps.props = undefined - return - } - - const currentRundownIndex = orderedRundowns.findIndex((r) => r._id === currentRundown._id) - - if (currentRundownIndex === -1) { - this.breakProps.props = undefined - return - } - - const nextBreakIndex = orderedRundowns.findIndex((rundown, index) => { - if (index < currentRundownIndex) { - return false - } - - return rundown.endOfRundownIsShowBreak === true - }) - - this.breakProps.props = { - rundownsBeforeNextBreak: orderedRundowns.slice(currentRundownIndex, nextBreakIndex + 1), - breakIsLastRundown: nextBreakIndex === orderedRundowns.length - 1, - } - } } export interface RundownTimingContext { @@ -780,14 +682,8 @@ export interface RundownTimingContext { currentPartWillAutoNext?: boolean /** Current time of this calculation */ currentTime?: number - /** Rundowns between current rundown and rundown with next break (inclusive of both). Undefined if there's no break in the future. */ - rundownsBeforeNextBreak?: Rundown[] - /** Whether the next break is also the last */ - breakIsLastRundown?: boolean /** Was this time context calculated during a high-resolution tick */ isLowResolution: boolean - /** The next (absolute) anchor time in the rundown, if any. */ - nextRundownAnchor?: number } /** @@ -847,14 +743,13 @@ export function getPlaylistTimingDiff( let frontAnchor: number = currentTime let backAnchor: number = currentTime if (PlaylistTiming.isPlaylistTimingForwardTime(timing)) { - const backAnchorTimeWithoutBreaks = + backAnchor = timing.expectedEnd ?? (startedPlayback ?? Math.max(timing.expectedStart, currentTime)) + (timing.expectedDuration ?? timingContext.totalPlaylistDuration ?? 0) - backAnchor = timingContext.nextRundownAnchor ?? backAnchorTimeWithoutBreaks frontAnchor = Math.max(currentTime, playlist.startedPlayback ?? Math.max(timing.expectedStart, currentTime)) } else if (PlaylistTiming.isPlaylistTimingBackTime(timing)) { - backAnchor = timingContext.nextRundownAnchor ?? timing.expectedEnd + backAnchor = timing.expectedEnd } let diff = 0 @@ -911,38 +806,6 @@ function ensureMinimumDefaultDurationIfNotAuto( return Math.max(incomingDuration, defaultDuration) } -/** - * Gets the next soonest valid rundown anchor from a Part's Segment. - * - * Specifically, it returns the start anchor if present and if the start anchor's time has not already passed. - * Else, it returns the end anchor if present. - * Else, returns undefined. - */ -function getSegmentRundownAnchorFromPart( - partId: PartId, - partInstancesMap: Map, - segmentsMap: Map, - now: number -): number | undefined { - let nextRundownAnchor: number | undefined = undefined - - const part = partInstancesMap.get(partId) - const segment = part?.segmentId ? segmentsMap.get(part.segmentId) : null - if (!segment) return nextRundownAnchor - - const startTime = segment.segmentTiming?.expectedStart ?? null - if (startTime && startTime > now) { - nextRundownAnchor = startTime - } else { - const endTime = segment.segmentTiming?.expectedEnd ?? null - if (endTime) { - nextRundownAnchor = endTime - } - } - - return nextRundownAnchor -} - export type MinimalPartInstance = Pick< PartInstance, | '_id' diff --git a/packages/webui/src/client/ui/RundownView.tsx b/packages/webui/src/client/ui/RundownView.tsx index f84ed7f11dd..9e014ee6f11 100644 --- a/packages/webui/src/client/ui/RundownView.tsx +++ b/packages/webui/src/client/ui/RundownView.tsx @@ -65,8 +65,6 @@ import { RundownDividerHeader } from './RundownView/RundownDividerHeader.js' import { PlaylistLoopingHeader } from './RundownView/PlaylistLoopingHeader.js' import RundownViewEventBus, { RundownViewEvents } from '@sofie-automation/meteor-lib/dist/triggers/RundownViewEventBus' import { RundownLayoutsAPI } from '../lib/rundownLayouts.js' -import { PlaylistTiming } from '@sofie-automation/corelib/dist/playout/rundownTiming' -import { BreakSegment } from './SegmentTimeline/BreakSegment.js' import type { DBShowStyleVariant } from '@sofie-automation/corelib/dist/dataModel/ShowStyleVariant.js' import { SegmentStoryboardContainer } from './SegmentStoryboard/SegmentStoryboardContainer.js' import { SegmentViewMode } from './SegmentContainer/SegmentViewModes.js' @@ -154,7 +152,7 @@ interface IState { segmentViewModes: Record } -export type MinimalRundown = Pick +export type MinimalRundown = Pick type MatchedSegment = { rundown: MinimalRundown @@ -1072,10 +1070,6 @@ const RundownViewContent = translateWithTracker - )} ) }) diff --git a/packages/webui/src/client/ui/RundownView/RundownTiming/NextBreakTiming.tsx b/packages/webui/src/client/ui/RundownView/RundownTiming/NextBreakTiming.tsx deleted file mode 100644 index ecd5eeb325b..00000000000 --- a/packages/webui/src/client/ui/RundownView/RundownTiming/NextBreakTiming.tsx +++ /dev/null @@ -1,35 +0,0 @@ -import { useTranslation } from 'react-i18next' -import Moment from 'react-moment' -import type { Rundown } from '@sofie-automation/corelib/dist/dataModel/Rundown' -import { useTiming } from './withTiming.js' -import ClassNames from 'classnames' -import { PlaylistTiming } from '@sofie-automation/corelib/dist/playout/rundownTiming' - -interface INextBreakTimingProps { - loop?: boolean - rundownsBeforeBreak?: Rundown[] - breakText?: string - lastChild?: boolean -} - -export function NextBreakTiming(props: Readonly): JSX.Element | null { - const { t } = useTranslation() - - const timingDurations = useTiming() - - const rundownsBeforeBreak = props.rundownsBeforeBreak || timingDurations.rundownsBeforeNextBreak || [] - const breakRundown = rundownsBeforeBreak.length ? rundownsBeforeBreak[rundownsBeforeBreak.length - 1] : undefined - - if (!breakRundown) { - return null - } - - const expectedEnd = PlaylistTiming.getExpectedEnd(breakRundown.timing) - - return ( - - {t(props.breakText || 'Next Break')} - - - ) -} diff --git a/packages/webui/src/client/ui/RundownView/RundownTiming/RundownTimingProvider.tsx b/packages/webui/src/client/ui/RundownView/RundownTiming/RundownTimingProvider.tsx index 970b33298b1..4d6e565ecda 100644 --- a/packages/webui/src/client/ui/RundownView/RundownTiming/RundownTimingProvider.tsx +++ b/packages/webui/src/client/ui/RundownView/RundownTiming/RundownTimingProvider.tsx @@ -4,7 +4,6 @@ import { withTracker } from '../../../lib/ReactMeteorData/react-meteor-data.js' import { protectString } from '@sofie-automation/shared-lib/dist/lib/protectedString' import type { DBRundownPlaylist } from '@sofie-automation/corelib/dist/dataModel/RundownPlaylist/RundownPlaylist' import { RundownTiming, type TimeEventArgs } from './RundownTiming.js' -import type { Rundown } from '@sofie-automation/corelib/dist/dataModel/Rundown' import type { DBSegment } from '@sofie-automation/corelib/dist/dataModel/Segment' import { type MinimalPartInstance, @@ -14,7 +13,7 @@ import { findPartInstancesInQuickLoop, } from '../../../lib/rundownTiming.js' import type { PartId, PartInstanceId, SegmentId } from '@sofie-automation/corelib/dist/dataModel/Ids' -import { RundownPlaylistCollectionUtil } from '../../../collections/rundownPlaylistUtil.js' + import { sortPartInstancesInSortedSegments } from '@sofie-automation/corelib/dist/playout/playlist' import { RundownPlaylistClientUtil } from '../../../lib/rundownPlaylistUtil.js' import { getCurrentTime } from '../../../lib/systemTime.js' @@ -50,10 +49,7 @@ interface IRundownTimingProviderProps { interface IRundownTimingProviderState {} interface IRundownTimingProviderTrackedProps { - rundowns: Array - currentRundown: Rundown | undefined partInstances: Array - partInstancesMap: Map segments: DBSegment[] segmentsMap: Map partsInQuickLoop: Record @@ -72,19 +68,13 @@ export const RundownTimingProvider = withTracker< >(({ playlist }) => { if (!playlist) { return { - rundowns: [], - currentRundown: undefined, partInstances: [], - partInstancesMap: new Map(), segments: [], segmentsMap: new Map(), partsInQuickLoop: {}, } } - const partInstancesMap = new Map() - - const rundowns = RundownPlaylistCollectionUtil.getRundownsOrdered(playlist) const segments = RundownPlaylistClientUtil.getSegments(playlist) const segmentsMap = new Map(segments.map((segment) => [segment._id, segment])) const unorderedParts = RundownPlaylistClientUtil.getUnorderedParts(playlist) @@ -121,10 +111,6 @@ export const RundownTimingProvider = withTracker< playlist.previousPartInfo?.partInstanceId ) - const currentRundown = currentPartInstance - ? rundowns.find((r) => r._id === currentPartInstance.rundownId) - : rundowns[0] - let partInstances: MinimalPartInstance[] = [] const allPartIds: Set = new Set() @@ -147,10 +133,7 @@ export const RundownTimingProvider = withTracker< const partsInQuickLoop = findPartInstancesInQuickLoop(playlist, partInstances) return { - rundowns, - currentRundown, partInstances, - partInstancesMap, segments, segmentsMap, partsInQuickLoop, @@ -277,16 +260,13 @@ export const RundownTimingProvider = withTracker< } private updateDurations(now: number, isSynced: boolean) { - const { playlist, rundowns, currentRundown, partInstances, partInstancesMap, segmentsMap } = this.props + const { playlist, partInstances, segmentsMap } = this.props const updatedDurations = this.timingCalculator.updateDurations( now, isSynced, playlist, - rundowns, - currentRundown, partInstances, - partInstancesMap, segmentsMap, this.props.defaultDuration, this.props.partsInQuickLoop diff --git a/packages/webui/src/client/ui/RundownView/RundownTiming/SegmentTimeAnchorTime.tsx b/packages/webui/src/client/ui/RundownView/RundownTiming/SegmentTimeAnchorTime.tsx deleted file mode 100644 index 5a3608261d0..00000000000 --- a/packages/webui/src/client/ui/RundownView/RundownTiming/SegmentTimeAnchorTime.tsx +++ /dev/null @@ -1,46 +0,0 @@ -import classNames from 'classnames' -import type { SegmentUi } from '../../SegmentTimeline/SegmentTimelineContainer.js' -import { useTranslation } from 'react-i18next' -import { useCurrentTime } from '../../../lib/lib.js' -import Moment from 'react-moment' - -interface ISegmentTimeAnchorTimeProps { - segment: SegmentUi - className?: string - labelClassName?: string - isLiveSegment: boolean -} - -/** - * A presentational component that will render a counter that will show the wall time that a break starts at. - * (Or ends at, if there's no start time but an end time is provided.) - * @function SegmentTimeAnchorTime - * @extends React.Component - */ -export const SegmentTimeAnchorTime = function SegmentTimeAnchorTime( - props: ISegmentTimeAnchorTimeProps -): JSX.Element | null { - const { t } = useTranslation() - const currentTime = useCurrentTime() - const passedExpectedStart = - props.segment.segmentTiming?.expectedStart && currentTime > props.segment.segmentTiming?.expectedStart - let value = props.segment.segmentTiming?.expectedStart - let usingEnd = false - if (props.isLiveSegment || passedExpectedStart) { - usingEnd = true - value = props.segment.segmentTiming?.expectedEnd - } - - if (value === null || value === undefined) { - return null - } - - return ( - <> - {t(usingEnd ? 'Planned End' : 'Planned Start')} - - - - - ) -} diff --git a/packages/webui/src/client/ui/SegmentContainer/withResolvedSegment.ts b/packages/webui/src/client/ui/SegmentContainer/withResolvedSegment.ts index 1032c1bec2e..ff0e1b4f2da 100644 --- a/packages/webui/src/client/ui/SegmentContainer/withResolvedSegment.ts +++ b/packages/webui/src/client/ui/SegmentContainer/withResolvedSegment.ts @@ -56,7 +56,7 @@ export interface IOutputLayerUi extends IOutputLayerExtended { } export type ISourceLayerUi = ISourceLayerExtended -export type MinimalRundown = Pick +export type MinimalRundown = Pick export const FREEZE_FRAME_FLASH = 5000 diff --git a/packages/webui/src/client/ui/SegmentList/SegmentListHeader.tsx b/packages/webui/src/client/ui/SegmentList/SegmentListHeader.tsx index 29138fdf60b..df9d9a5f183 100644 --- a/packages/webui/src/client/ui/SegmentList/SegmentListHeader.tsx +++ b/packages/webui/src/client/ui/SegmentList/SegmentListHeader.tsx @@ -14,7 +14,6 @@ import type { DBRundownPlaylist } from '@sofie-automation/corelib/dist/dataModel import type { IContextMenuContext } from '../RundownView.js' import { NoteSeverity } from '@sofie-automation/blueprints-integration' import { CriticalIconSmall, WarningIconSmall } from '../../lib/ui/icons/notifications.js' -import { SegmentTimeAnchorTime } from '../RundownView/RundownTiming/SegmentTimeAnchorTime.js' export function SegmentListHeader({ isDetached, @@ -116,38 +115,28 @@ export function SegmentListHeader({ {segment.name}
- {segment.segmentTiming?.expectedStart || segment.segmentTiming?.expectedEnd ? ( -
- + {playlist && parts && parts.length > 0 && showCountdownToSegment && ( + {t('On Air At')} + ) : ( + {t('On Air In')} + ) + } /> -
- ) : ( -
- {playlist && parts && parts.length > 0 && showCountdownToSegment && ( - {t('On Air At')} - ) : ( - {t('On Air In')} - ) - } - /> - )} -
- )} + )} +
{(criticalNotes > 0 || warningNotes > 0) && (
diff --git a/packages/webui/src/client/ui/SegmentStoryboard/SegmentStoryboard.tsx b/packages/webui/src/client/ui/SegmentStoryboard/SegmentStoryboard.tsx index 99815b1ac2b..22e56c93a67 100644 --- a/packages/webui/src/client/ui/SegmentStoryboard/SegmentStoryboard.tsx +++ b/packages/webui/src/client/ui/SegmentStoryboard/SegmentStoryboard.tsx @@ -38,7 +38,6 @@ import { SegmentViewMode } from '../SegmentContainer/SegmentViewModes.js' import { ErrorBoundary } from '../../lib/ErrorBoundary.js' import { SwitchViewModeButton } from '../SegmentContainer/SwitchViewModeButton.js' import type { PartId, SegmentId } from '@sofie-automation/corelib/dist/dataModel/Ids' -import { SegmentTimeAnchorTime } from '../RundownView/RundownTiming/SegmentTimeAnchorTime.js' import { logger } from '../../lib/logging.js' import type { UIStudio } from '@sofie-automation/corelib/src/dataModel/Studio.js' import type { PieceUi } from '@sofie-automation/corelib/src/dataModel/Piece.js' @@ -631,33 +630,23 @@ export const SegmentStoryboard = React.memo( /> )}
- {props.segment.segmentTiming?.expectedStart || props.segment.segmentTiming?.expectedEnd ? ( -
- + {props.playlist && props.parts && props.parts.length > 0 && props.showCountdownToSegment && ( + {t('On Air At')} + ) : ( + {t('On Air In')} + ) + } /> -
- ) : ( -
- {props.playlist && props.parts && props.parts.length > 0 && props.showCountdownToSegment && ( - {t('On Air At')} - ) : ( - {t('On Air In')} - ) - } - /> - )} -
- )} + )} +
{props.segment.externalId}
diff --git a/packages/webui/src/client/ui/SegmentTimeline/SegmentTimeline.tsx b/packages/webui/src/client/ui/SegmentTimeline/SegmentTimeline.tsx index 3a9ab3fca40..1e073b5c747 100644 --- a/packages/webui/src/client/ui/SegmentTimeline/SegmentTimeline.tsx +++ b/packages/webui/src/client/ui/SegmentTimeline/SegmentTimeline.tsx @@ -56,7 +56,6 @@ import { TimingDataResolution, type WithTiming, } from '../RundownView/RundownTiming/withTiming.js' -import { SegmentTimeAnchorTime } from '../RundownView/RundownTiming/SegmentTimeAnchorTime.js' import { logger } from '../../lib/logging.js' import type { DBSegment } from '@sofie-automation/corelib/dist/dataModel/Segment' import { SelectedElementsContext } from '../RundownView/SelectedElementsContext.js' @@ -1123,36 +1122,26 @@ export class SegmentTimelineClass extends React.Component - {this.props.segment.segmentTiming?.expectedStart || this.props.segment.segmentTiming?.expectedEnd ? ( -
- -
- ) : ( -
- {this.props.playlist && - this.props.parts && - this.props.parts.length > 0 && - this.props.showCountdownToSegment && ( - {t('On Air At')} - ) : ( - {t('On Air In')} - ) - } - /> - )} -
- )} +
+ {this.props.playlist && + this.props.parts && + this.props.parts.length > 0 && + this.props.showCountdownToSegment && ( + {t('On Air At')} + ) : ( + {t('On Air In')} + ) + } + /> + )} +
{this.props.segment.externalId}
diff --git a/packages/webui/src/client/ui/Settings/components/FilterEditor.tsx b/packages/webui/src/client/ui/Settings/components/FilterEditor.tsx index 91a19d5b121..3686b200111 100644 --- a/packages/webui/src/client/ui/Settings/components/FilterEditor.tsx +++ b/packages/webui/src/client/ui/Settings/components/FilterEditor.tsx @@ -1202,19 +1202,6 @@ export const FilterEditor: React.ComponentType = withTranslation()( ) } - renderNextBreakTiming(item: RundownLayoutBase, index: number, isDashboardLayout: boolean) { - const { t } = this.props - return ( - - - - {isDashboardLayout && this.renderDashboardLayoutSettings(item, index)} - - ) - } renderMiniRundown(item: RundownLayoutBase, index: number, isDashboardLayout: boolean) { const { t } = this.props return ( diff --git a/packages/webui/src/client/ui/Settings/components/rundownLayouts/RundownViewLayoutSettings.tsx b/packages/webui/src/client/ui/Settings/components/rundownLayouts/RundownViewLayoutSettings.tsx index 083954fa69d..bc79e486086 100644 --- a/packages/webui/src/client/ui/Settings/components/rundownLayouts/RundownViewLayoutSettings.tsx +++ b/packages/webui/src/client/ui/Settings/components/rundownLayouts/RundownViewLayoutSettings.tsx @@ -142,16 +142,6 @@ export default function RundownViewLayoutSettings({ sourceLayers, item, layouts {t('Hide rundown divider between rundowns in a playlist')} - -