11import React , { type PropsWithChildren } from 'react'
22import { Meteor } from 'meteor/meteor'
33import { withTracker } from '../../../lib/ReactMeteorData/react-meteor-data.js'
4+ import _ from 'underscore'
45import { protectString } from '@sofie-automation/shared-lib/dist/lib/protectedString'
56import type { DBRundownPlaylist } from '@sofie-automation/corelib/dist/dataModel/RundownPlaylist/RundownPlaylist'
67import { RundownTiming , type TimeEventArgs } from './RundownTiming.js'
@@ -59,6 +60,31 @@ interface IRundownTimingProviderTrackedProps {
5960 partsInQuickLoop : Record < TimingId , boolean >
6061}
6162
63+ function getPlaylistRenderSelector ( playlist : DBRundownPlaylist | undefined ) {
64+ if ( ! playlist ) return undefined
65+
66+ const quickLoopStartId =
67+ playlist . quickLoop ?. start && 'id' in playlist . quickLoop . start ? playlist . quickLoop . start . id : undefined
68+ const quickLoopEndId =
69+ playlist . quickLoop ?. end && 'id' in playlist . quickLoop . end ? playlist . quickLoop . end . id : undefined
70+
71+ return {
72+ id : playlist . _id ,
73+ activationId : playlist . activationId ,
74+ rundownIdsInOrder : playlist . rundownIdsInOrder ,
75+ currentPartInstanceId : playlist . currentPartInfo ?. partInstanceId ,
76+ nextPartInstanceId : playlist . nextPartInfo ?. partInstanceId ,
77+ previousPartInstanceId : playlist . previousPartInfo ?. partInstanceId ,
78+ outOfOrderTiming : playlist . outOfOrderTiming ,
79+ segmentsStartedPlayback : playlist . segmentsStartedPlayback ,
80+ quickLoopRunning : playlist . quickLoop ?. running ,
81+ quickLoopStartType : playlist . quickLoop ?. start ?. type ,
82+ quickLoopStartId,
83+ quickLoopEndType : playlist . quickLoop ?. end ?. type ,
84+ quickLoopEndId,
85+ }
86+ }
87+
6288/**
6389 * RundownTimingProvider is a container component that provides a timing context to all child elements.
6490 * It allows calculating a single
@@ -69,93 +95,101 @@ export const RundownTimingProvider = withTracker<
6995 PropsWithChildren < IRundownTimingProviderProps > ,
7096 IRundownTimingProviderState ,
7197 IRundownTimingProviderTrackedProps
72- > ( ( { playlist } ) => {
73- if ( ! playlist ) {
74- return {
75- rundowns : [ ] ,
76- currentRundown : undefined ,
77- partInstances : [ ] ,
78- partInstancesMap : new Map ( ) ,
79- segments : [ ] ,
80- segmentsMap : new Map ( ) ,
81- partsInQuickLoop : { } ,
98+ > (
99+ ( { playlist } ) => {
100+ if ( ! playlist ) {
101+ return {
102+ rundowns : [ ] ,
103+ currentRundown : undefined ,
104+ partInstances : [ ] ,
105+ partInstancesMap : new Map ( ) ,
106+ segments : [ ] ,
107+ segmentsMap : new Map ( ) ,
108+ partsInQuickLoop : { } ,
109+ }
82110 }
83- }
84111
85- const partInstancesMap = new Map < PartId , MinimalPartInstance > ( )
86-
87- const rundowns = RundownPlaylistCollectionUtil . getRundownsOrdered ( playlist )
88- const segments = RundownPlaylistClientUtil . getSegments ( playlist )
89- const segmentsMap = new Map < SegmentId , DBSegment > ( segments . map ( ( segment ) => [ segment . _id , segment ] ) )
90- const unorderedParts = RundownPlaylistClientUtil . getUnorderedParts ( playlist )
91- const activePartInstances = RundownPlaylistClientUtil . getActivePartInstances ( playlist , undefined , {
92- projection : {
93- _id : 1 ,
94- rundownId : 1 ,
95- segmentId : 1 ,
96- isTemporary : 1 ,
97- segmentPlayoutId : 1 ,
98- takeCount : 1 ,
99- part : 1 ,
100- timings : 1 ,
101- orphaned : 1 ,
102- } ,
103- } ) as Array <
104- Pick <
105- PartInstance ,
106- | '_id'
107- | 'rundownId'
108- | 'segmentId'
109- | 'isTemporary'
110- | 'segmentPlayoutId'
111- | 'takeCount'
112- | 'part'
113- | 'timings'
114- | 'orphaned'
112+ const partInstancesMap = new Map < PartId , MinimalPartInstance > ( )
113+
114+ const rundowns = RundownPlaylistCollectionUtil . getRundownsOrdered ( playlist )
115+ const segments = RundownPlaylistClientUtil . getSegments ( playlist )
116+ const segmentsMap = new Map < SegmentId , DBSegment > ( segments . map ( ( segment ) => [ segment . _id , segment ] ) )
117+ const unorderedParts = RundownPlaylistClientUtil . getUnorderedParts ( playlist )
118+ const activePartInstances = RundownPlaylistClientUtil . getActivePartInstances ( playlist , undefined , {
119+ projection : {
120+ _id : 1 ,
121+ rundownId : 1 ,
122+ segmentId : 1 ,
123+ isTemporary : 1 ,
124+ segmentPlayoutId : 1 ,
125+ takeCount : 1 ,
126+ part : 1 ,
127+ timings : 1 ,
128+ orphaned : 1 ,
129+ } ,
130+ } ) as Array <
131+ Pick <
132+ PartInstance ,
133+ | '_id'
134+ | 'rundownId'
135+ | 'segmentId'
136+ | 'isTemporary'
137+ | 'segmentPlayoutId'
138+ | 'takeCount'
139+ | 'part'
140+ | 'timings'
141+ | 'orphaned'
142+ >
115143 >
116- >
117144
118- const { currentPartInstance } = findCurrentAndPreviousPartInstance (
119- activePartInstances ,
120- playlist . currentPartInfo ?. partInstanceId ,
121- playlist . previousPartInfo ?. partInstanceId
122- )
145+ const { currentPartInstance } = findCurrentAndPreviousPartInstance (
146+ activePartInstances ,
147+ playlist . currentPartInfo ?. partInstanceId ,
148+ playlist . previousPartInfo ?. partInstanceId
149+ )
123150
124- const currentRundown = currentPartInstance
125- ? rundowns . find ( ( r ) => r . _id === currentPartInstance . rundownId )
126- : rundowns [ 0 ]
151+ const currentRundown = currentPartInstance
152+ ? rundowns . find ( ( r ) => r . _id === currentPartInstance . rundownId )
153+ : rundowns [ 0 ]
127154
128- let partInstances : MinimalPartInstance [ ] = [ ]
155+ let partInstances : MinimalPartInstance [ ] = [ ]
129156
130- const allPartIds : Set < PartId > = new Set ( )
157+ const allPartIds : Set < PartId > = new Set ( )
131158
132- for ( const partInstance of activePartInstances ) {
133- allPartIds . add ( partInstance . part . _id )
134- }
159+ for ( const partInstance of activePartInstances ) {
160+ allPartIds . add ( partInstance . part . _id )
161+ }
135162
136- partInstances = activePartInstances
163+ partInstances = activePartInstances
137164
138- for ( const part of unorderedParts ) {
139- if ( allPartIds . has ( part . _id ) ) continue
140- partInstances . push ( wrapPartToTemporaryInstance ( playlist . activationId ?? protectString ( '' ) , part ) )
141- }
165+ for ( const part of unorderedParts ) {
166+ if ( allPartIds . has ( part . _id ) ) continue
167+ partInstances . push ( wrapPartToTemporaryInstance ( playlist . activationId ?? protectString ( '' ) , part ) )
168+ }
142169
143- partInstances = sortPartInstancesInSortedSegments ( partInstances , segments )
170+ partInstances = sortPartInstancesInSortedSegments ( partInstances , segments )
144171
145- partInstances = deduplicatePartInstancesForQuickLoop ( playlist , partInstances , currentPartInstance )
172+ partInstances = deduplicatePartInstancesForQuickLoop ( playlist , partInstances , currentPartInstance )
146173
147- const partsInQuickLoop = findPartInstancesInQuickLoop ( playlist , partInstances )
174+ const partsInQuickLoop = findPartInstancesInQuickLoop ( playlist , partInstances )
148175
149- return {
150- rundowns,
151- currentRundown,
152- partInstances,
153- partInstancesMap,
154- segments,
155- segmentsMap,
156- partsInQuickLoop,
176+ return {
177+ rundowns,
178+ currentRundown,
179+ partInstances,
180+ partInstancesMap,
181+ segments,
182+ segmentsMap,
183+ partsInQuickLoop,
184+ }
185+ } ,
186+ ( _data , props , nextProps ) => {
187+ if ( props . refreshInterval !== nextProps . refreshInterval ) return true
188+ if ( props . defaultDuration !== nextProps . defaultDuration ) return true
189+
190+ return ! _ . isEqual ( getPlaylistRenderSelector ( props . playlist ) , getPlaylistRenderSelector ( nextProps . playlist ) )
157191 }
158- } ) (
192+ ) (
159193 class RundownTimingProvider extends React . Component <
160194 PropsWithChildren < IRundownTimingProviderProps > & IRundownTimingProviderTrackedProps ,
161195 IRundownTimingProviderState
0 commit comments