1- import * as React from 'react'
1+ import React , { useState , useRef , useEffect } from 'react'
22import { WithTranslation , withTranslation } from 'react-i18next'
33
44import ClassNames from 'classnames'
@@ -36,7 +36,7 @@ import { wrapPartToTemporaryInstance } from '@sofie-automation/meteor-lib/dist/c
3636
3737import { SegmentTimelineSmallPartFlag } from './SmallParts/SegmentTimelineSmallPartFlag.js'
3838import { UIStateStorage } from '../../lib/UIStateStorage.js'
39- import { getPartInstanceTimingId , RundownTimingContext } from '../../lib/rundownTiming.js'
39+ import { computeSegmentDuration , getPartInstanceTimingId , RundownTimingContext } from '../../lib/rundownTiming.js'
4040import { IOutputLayer , ISourceLayer , NoteSeverity , UserEditingType } from '@sofie-automation/blueprints-integration'
4141import { SegmentTimelineZoomButtons } from './SegmentTimelineZoomButtons.js'
4242import { SegmentViewMode } from '../SegmentContainer/SegmentViewModes.js'
@@ -51,7 +51,6 @@ import {
5151 TimingTickResolution ,
5252 TimingDataResolution ,
5353 WithTiming ,
54- RundownTimingProviderContext ,
5554} from '../RundownView/RundownTiming/withTiming.js'
5655import { SegmentTimeAnchorTime } from '../RundownView/RundownTiming/SegmentTimeAnchorTime.js'
5756import { logger } from '../../lib/logging.js'
@@ -121,100 +120,61 @@ interface IStateHeader {
121120 // isSelected: boolean
122121}
123122
124- interface IZoomPropsHeader {
123+ interface SegmentTimelineZoomProps extends IProps {
125124 onZoomDblClick : ( e : React . MouseEvent ) => void
126125 timelineWidth : number
126+ timingDurations : RundownTimingContext
127127}
128- interface IZoomStateHeader {
129- totalSegmentDuration : number
128+
129+ function computeSegmentDurationFromProps ( props : SegmentTimelineZoomProps ) : number {
130+ return computeSegmentDuration ( props . timingDurations , props . parts , true )
130131}
131132
132- const SegmentTimelineZoom = class SegmentTimelineZoom extends React . Component <
133- IProps & IZoomPropsHeader ,
134- IZoomStateHeader
135- > {
136- static contextType = RundownTimingProviderContext
137- declare context : React . ContextType < typeof RundownTimingProviderContext >
133+ function SegmentTimelineZoom ( props : SegmentTimelineZoomProps ) : JSX . Element {
134+ const [ totalSegmentDuration , setTotalSegmentDuration ] = useState ( ( ) => computeSegmentDurationFromProps ( props ) )
138135
139- constructor ( props : IProps & IZoomPropsHeader , context : any ) {
140- super ( props , context )
141- this . state = {
142- totalSegmentDuration : 10 ,
143- }
144- }
136+ // Store the props into a ref so that the checkTimingChange can access the latest props without needing to be re-created on every render
137+ const propsRef = useRef ( props )
138+ propsRef . current = props
145139
146- componentDidMount ( ) : void {
147- this . checkTimingChange ( )
148- window . addEventListener ( RundownTiming . Events . timeupdateHighResolution , this . onTimeupdate )
149- }
150-
151- componentWillUnmount ( ) : void {
152- window . removeEventListener ( RundownTiming . Events . timeupdateHighResolution , this . onTimeupdate )
153- }
154-
155- onTimeupdate = ( ) => {
156- if ( ! this . props . isLiveSegment ) {
157- this . checkTimingChange ( )
158- }
159- }
160-
161- checkTimingChange = ( ) => {
162- const total = this . calculateSegmentDuration ( )
163- if ( total !== this . state . totalSegmentDuration ) {
164- this . setState ( {
165- totalSegmentDuration : total ,
166- } )
140+ useEffect ( ( ) => {
141+ const onTimeupdate = ( ) => {
142+ if ( ! propsRef . current . isLiveSegment ) {
143+ setTotalSegmentDuration ( computeSegmentDurationFromProps ( propsRef . current ) )
144+ }
167145 }
168- }
169146
170- calculateSegmentDuration ( ) : number {
171- let total = 0
172- if ( this . context ?. durations ) {
173- const durations = this . context . durations
174- this . props . parts . forEach ( ( partExtended ) => {
175- // total += durations.partDurations ? durations.partDurations[item._id] : (item.duration || item.renderedDuration || 1)
176- const partInstanceTimingId = getPartInstanceTimingId ( partExtended . instance )
177- const duration = Math . max (
178- partExtended . instance . timings ?. duration || partExtended . renderedDuration || 0 ,
179- durations . partDisplayDurations ?. [ partInstanceTimingId ] || Settings . defaultDisplayDuration
180- )
181- total += duration
182- } )
183- } else {
184- total = RundownUtils . getSegmentDuration ( this . props . parts , true )
147+ window . addEventListener ( RundownTiming . Events . timeupdateHighResolution , onTimeupdate )
148+ return ( ) => {
149+ window . removeEventListener ( RundownTiming . Events . timeupdateHighResolution , onTimeupdate )
185150 }
186- return total
187- }
151+ } , [ ] )
188152
189- getSegmentDuration ( ) : number {
190- return this . props . isLiveSegment ? this . calculateSegmentDuration ( ) : this . state . totalSegmentDuration
191- }
153+ const segmentDuration = props . isLiveSegment ? computeSegmentDurationFromProps ( props ) : totalSegmentDuration
192154
193- render ( ) : JSX . Element {
194- return (
195- < div
196- className = { ClassNames ( 'segment-timeline__zoom-area-container' , {
197- hidden :
198- this . props . scrollLeft === 0 &&
199- ( this . props . showingAllSegment || this . props . timeScale === this . props . maxTimeScale ) &&
200- ! this . props . isLiveSegment ,
201- } ) }
202- >
203- < div className = "segment-timeline__zoom-area" onDoubleClick = { ( e ) => this . props . onZoomDblClick ( e ) } >
204- < SegmentTimelineZoomControls
205- scrollLeft = { this . props . scrollLeft }
206- scrollWidth = { this . props . timelineWidth / this . props . timeScale }
207- onScroll = { this . props . onScroll }
208- segmentDuration = { this . getSegmentDuration ( ) }
209- liveLineHistorySize = { this . props . liveLineHistorySize }
210- timeScale = { this . props . timeScale }
211- maxTimeScale = { this . props . maxTimeScale }
212- onZoomChange = { this . props . onZoomChange }
213- />
214- </ div >
155+ return (
156+ < div
157+ className = { ClassNames ( 'segment-timeline__zoom-area-container' , {
158+ hidden :
159+ props . scrollLeft === 0 &&
160+ ( props . showingAllSegment || props . timeScale === props . maxTimeScale ) &&
161+ ! props . isLiveSegment ,
162+ } ) }
163+ >
164+ < div className = "segment-timeline__zoom-area" onDoubleClick = { props . onZoomDblClick } >
165+ < SegmentTimelineZoomControls
166+ scrollLeft = { props . scrollLeft }
167+ scrollWidth = { props . timelineWidth / props . timeScale }
168+ onScroll = { props . onScroll }
169+ segmentDuration = { segmentDuration }
170+ liveLineHistorySize = { props . liveLineHistorySize }
171+ timeScale = { props . timeScale }
172+ maxTimeScale = { props . maxTimeScale }
173+ onZoomChange = { props . onZoomChange }
174+ />
215175 </ div >
216- )
217- }
176+ </ div >
177+ )
218178}
219179
220180export const SEGMENT_TIMELINE_ELEMENT_ID = 'rundown__segment__'
0 commit comments