@@ -68,12 +68,7 @@ export async function scrollToPartInstance(
6868 quitFocusOnPart ( )
6969 const partInstance = UIPartInstances . findOne ( partInstanceId )
7070 if ( partInstance ) {
71- console . log ( 'scrollToPartInstance - Emitting GO_TO_PART_INSTANCE' , partInstance . segmentId , partInstanceId )
72- // RundownViewEventBus.emit(RundownViewEvents.GO_TO_PART_INSTANCE, {
73- // segmentId: partInstance.segmentId,
74- // partInstanceId: partInstanceId,
75- // })
76- return scrollToSegment ( partInstance . segmentId , forceScroll , noAnimation , partInstanceId )
71+ return scrollToSegment ( partInstance . segmentId , forceScroll , noAnimation )
7772 }
7873 throw new Error ( 'Could not find PartInstance' )
7974}
@@ -120,39 +115,10 @@ let currentScrollingElement: HTMLElement | undefined
120115export async function scrollToSegment (
121116 elementToScrollToOrSegmentId : HTMLElement | SegmentId ,
122117 forceScroll ?: boolean ,
123- noAnimation ?: boolean ,
124- partInstanceId ?: PartInstanceId | undefined
118+ noAnimation ?: boolean
125119) : Promise < boolean > {
126- const getElementToScrollTo = ( showHistory : boolean ) : HTMLElement | null => {
127- if ( isProtectedString ( elementToScrollToOrSegmentId ) ) {
128- let targetElement = document . querySelector < HTMLElement > (
129- `#${ SEGMENT_TIMELINE_ELEMENT_ID } ${ elementToScrollToOrSegmentId } `
130- )
131-
132- if ( showHistory && Settings . followOnAirSegmentsHistory && targetElement ) {
133- let i = Settings . followOnAirSegmentsHistory
134- while ( i > 0 ) {
135- // Segment timeline is wrapped by <div><div>...</div></div> when rendered
136- const next : any = targetElement ?. parentElement ?. parentElement ?. previousElementSibling ?. children
137- . item ( 0 )
138- ?. children . item ( 0 )
139- if ( next ) {
140- targetElement = next
141- i --
142- } else {
143- i = 0
144- }
145- }
146- }
147-
148- return targetElement
149- }
150-
151- return elementToScrollToOrSegmentId
152- }
153-
154- const elementToScrollTo : HTMLElement | null = getElementToScrollTo ( false )
155- const historyTarget : HTMLElement | null = getElementToScrollTo ( true )
120+ const elementToScrollTo : HTMLElement | null = getElementToScrollTo ( elementToScrollToOrSegmentId , false )
121+ const historyTarget : HTMLElement | null = getElementToScrollTo ( elementToScrollToOrSegmentId , true )
156122
157123 // historyTarget will be === to elementToScrollTo if history is not used / not found
158124 if ( ! elementToScrollTo || ! historyTarget ) {
@@ -163,24 +129,66 @@ export async function scrollToSegment(
163129 historyTarget ,
164130 forceScroll || ! regionInViewport ( historyTarget , elementToScrollTo ) ,
165131 noAnimation ,
166- false ,
167- partInstanceId
132+ false
168133 )
169134}
170135
136+ function getElementToScrollTo (
137+ elementToScrollToOrSegmentId : HTMLElement | SegmentId ,
138+ showHistory : boolean
139+ ) : HTMLElement | null {
140+ if ( isProtectedString ( elementToScrollToOrSegmentId ) ) {
141+ // Get the current segment element
142+ let targetElement = document . querySelector < HTMLElement > (
143+ `#${ SEGMENT_TIMELINE_ELEMENT_ID } ${ elementToScrollToOrSegmentId } `
144+ )
145+ if ( showHistory && Settings . followOnAirSegmentsHistory && targetElement ) {
146+ let i = Settings . followOnAirSegmentsHistory
147+
148+ // Find previous segments
149+ while ( i > 0 && targetElement ) {
150+ const currentSegmentId = targetElement . id
151+ const allSegments = Array . from ( document . querySelectorAll ( `[id^="${ SEGMENT_TIMELINE_ELEMENT_ID } "]` ) )
152+
153+ // Find current segment's index in the array of all segments
154+ const currentIndex = allSegments . findIndex ( ( el ) => el . id === currentSegmentId )
155+
156+ // Find the previous segment
157+ if ( currentIndex > 0 ) {
158+ targetElement = allSegments [ currentIndex - 1 ] as HTMLElement
159+ i --
160+ } else {
161+ // No more previous segments
162+ break
163+ }
164+ }
165+ }
166+
167+ return targetElement
168+ }
169+
170+ return elementToScrollToOrSegmentId
171+ }
172+
171173async function innerScrollToSegment (
172174 elementToScrollTo : HTMLElement ,
173175 forceScroll ?: boolean ,
174176 noAnimation ?: boolean ,
175- secondStage ?: boolean ,
176- partInstanceId ?: PartInstanceId | undefined
177+ secondStage ?: boolean
177178) : Promise < boolean > {
178179 if ( ! secondStage ) {
179180 currentScrollingElement = elementToScrollTo
180181 } else if ( secondStage && elementToScrollTo !== currentScrollingElement ) {
181182 throw new Error ( 'Scroll overriden by another scroll' )
182183 }
183184
185+ // Ensure that the element is ready to be scrolled:
186+ if ( ! secondStage ) {
187+ await new Promise ( ( resolve ) => setTimeout ( resolve , 250 ) )
188+ }
189+ console . log ( 'innerScrollToSegment' , elementToScrollTo )
190+ await new Promise ( ( resolve ) => requestAnimationFrame ( resolve ) )
191+
184192 let { top, bottom } = elementToScrollTo . getBoundingClientRect ( )
185193 top = Math . floor ( top )
186194 bottom = Math . floor ( bottom )
@@ -193,36 +201,24 @@ async function innerScrollToSegment(
193201
194202 return scrollToPosition ( top + window . scrollY , noAnimation ) . then (
195203 async ( ) => {
196- // retry scroll in case we have to load some data
197- if ( pendingSecondStageScroll ) window . cancelIdleCallback ( pendingSecondStageScroll )
198204 return new Promise < boolean > ( ( resolve , reject ) => {
199- // scrollToPosition will resolve after some time, at which point a new pendingSecondStageScroll may have been created
200-
201- pendingSecondStageScroll = window . requestIdleCallback (
202- ( ) => {
203- if ( ! secondStage ) {
204- let { top, bottom } = elementToScrollTo . getBoundingClientRect ( )
205- top = Math . floor ( top )
206- bottom = Math . floor ( bottom )
207-
208- if ( bottom > Math . floor ( window . innerHeight ) || top < headerHeight ) {
209- innerScrollToSegment (
210- elementToScrollTo ,
211- forceScroll ,
212- true ,
213- true ,
214- partInstanceId
215- ) . then ( resolve , reject )
216- } else {
217- resolve ( true )
218- }
205+ if ( ! secondStage ) {
206+ // Wait to settle 1 atemt to scroll
207+ setTimeout ( ( ) => {
208+ let { top, bottom } = elementToScrollTo . getBoundingClientRect ( )
209+ top = Math . floor ( top )
210+ bottom = Math . floor ( bottom )
211+ if ( bottom > Math . floor ( window . innerHeight ) || top < headerHeight ) {
212+ // If not in place atempt to scroll again
213+ innerScrollToSegment ( elementToScrollTo , forceScroll , true , true ) . then ( resolve , reject )
219214 } else {
220- currentScrollingElement = undefined
221215 resolve ( true )
222216 }
223- } ,
224- { timeout : 250 }
225- )
217+ } , 600 )
218+ } else {
219+ currentScrollingElement = undefined
220+ resolve ( true )
221+ }
226222 } )
227223 } ,
228224 ( error ) => {
@@ -252,9 +248,6 @@ function getRegionPosition(topElement: HTMLElement, bottomElement: HTMLElement):
252248 return { top, bottom }
253249}
254250
255- let scrollToPositionRequest : number | undefined
256- let scrollToPositionRequestReject : ( ( reason ?: any ) => void ) | undefined
257-
258251export async function scrollToPosition ( scrollPosition : number , noAnimation ?: boolean ) : Promise < void > {
259252 // Calculate the exact position
260253 const headerOffset = getHeaderHeight ( ) + HEADER_MARGIN
@@ -264,66 +257,15 @@ export async function scrollToPosition(scrollPosition: number, noAnimation?: boo
264257 window . scroll ( {
265258 top : targetTop ,
266259 left : 0 ,
260+ behavior : 'instant' ,
267261 } )
262+ console . log ( `scrollToPosition: immediate scroll complete, position=${ window . scrollY } ` )
268263 return Promise . resolve ( )
269264 } else {
270- return new Promise ( ( resolve , reject ) => {
271- if ( scrollToPositionRequest !== undefined ) window . cancelIdleCallback ( scrollToPositionRequest )
272- if ( scrollToPositionRequestReject !== undefined )
273- scrollToPositionRequestReject ( 'Prevented by another scroll' )
274-
275- scrollToPositionRequestReject = reject
276-
277- scrollToPositionRequest = window . requestIdleCallback (
278- ( ) => {
279- window . scroll ( {
280- top : targetTop ,
281- left : 0 ,
282- behavior : 'smooth' ,
283- } )
284-
285- const checkScrollPosition = ( ) => {
286- const currentPosition = window . scrollY
287- // Check if target position is reached
288- if (
289- Math . abs ( currentPosition - targetTop ) < 2 ||
290- Math . abs ( currentPosition - lastCheckedPosition ) < 1
291- ) {
292- // Fine adjust the position
293- if ( Math . abs ( currentPosition - targetTop ) > 2 ) {
294- window . scroll ( {
295- top : targetTop ,
296- left : 0 ,
297- } )
298- }
299-
300- // Clean up and resolve
301- clearInterval ( checkInterval )
302- clearTimeout ( timeoutTimer )
303- resolve ( )
304- scrollToPositionRequestReject = undefined
305- return
306- }
307-
308- lastCheckedPosition = currentPosition
309- }
310-
311- // Keep track of the last position to detect when scrolling stops
312- let lastCheckedPosition = window . scrollY
313-
314- // Check every 100ms
315- const checkInterval = setInterval ( checkScrollPosition , 100 )
316-
317- // Fallback timeout - resolve after a reasonable time even if not at target
318- const timeoutTimer = setTimeout ( ( ) => {
319- clearInterval ( checkInterval )
320- resolve ( )
321- scrollToPositionRequestReject = undefined
322- } , 1500 )
323- } ,
324- // Make sure we wait to ensure the scroll is started
325- { timeout : 250 }
326- )
265+ window . scroll ( {
266+ top : targetTop ,
267+ left : 0 ,
268+ behavior : 'smooth' ,
327269 } )
328270 }
329271}
0 commit comments