77 * @flow
88 */
99import type { ReactContext } from 'shared/ReactTypes' ;
10- import type { SuspenseNode } from 'react-devtools-shared/src/frontend/types' ;
10+ import type {
11+ SuspenseNode ,
12+ SuspenseTimelineStep ,
13+ } from 'react-devtools-shared/src/frontend/types' ;
1114import type Store from '../../store' ;
1215
1316import * as React from 'react' ;
@@ -25,7 +28,7 @@ export type SuspenseTreeState = {
2528 lineage : $ReadOnlyArray < SuspenseNode [ 'id' ] > | null ,
2629 roots : $ReadOnlyArray < SuspenseNode [ 'id' ] > ,
2730 selectedSuspenseID : SuspenseNode [ 'id' ] | null ,
28- timeline : $ReadOnlyArray < SuspenseNode [ 'id' ] > ,
31+ timeline : $ReadOnlyArray < SuspenseTimelineStep > ,
2932 timelineIndex : number | - 1 ,
3033 hoveredTimelineIndex : number | - 1 ,
3134 uniqueSuspendersOnly : boolean ,
@@ -49,7 +52,7 @@ type ACTION_SELECT_SUSPENSE_BY_ID = {
4952type ACTION_SET_SUSPENSE_TIMELINE = {
5053 type : 'SET_SUSPENSE_TIMELINE' ,
5154 payload : [
52- $ReadOnlyArray < SuspenseNode [ 'id' ] > ,
55+ $ReadOnlyArray < SuspenseTimelineStep > ,
5356 // The next Suspense ID to select in the timeline
5457 SuspenseNode [ 'id' ] | null ,
5558 // Whether this timeline includes only unique suspenders
@@ -111,7 +114,7 @@ function getInitialState(store: Store): SuspenseTreeState {
111114 store . getSuspendableDocumentOrderSuspense ( uniqueSuspendersOnly ) ;
112115 const timelineIndex = timeline . length - 1 ;
113116 const selectedSuspenseID =
114- timelineIndex === - 1 ? null : timeline [ timelineIndex ] ;
117+ timelineIndex === - 1 ? null : timeline [ timelineIndex ] . id ;
115118 const lineage =
116119 selectedSuspenseID !== null
117120 ? store . getSuspenseLineage ( selectedSuspenseID )
@@ -164,37 +167,44 @@ function SuspenseTreeContextController({children}: Props): React.Node {
164167 selectedSuspenseID = null ;
165168 }
166169
167- let selectedTimelineID =
168- state . timeline === null
170+ const selectedTimelineStep =
171+ state . timeline === null || state . timelineIndex === - 1
169172 ? null
170173 : state . timeline [ state . timelineIndex ] ;
171- while (
172- selectedTimelineID !== null &&
173- removedIDs . has ( selectedTimelineID )
174- ) {
175- // $FlowExpectedError[incompatible-type]
176- selectedTimelineID = removedIDs . get ( selectedTimelineID ) ;
174+ let selectedTimelineID : null | number = null ;
175+ if ( selectedTimelineStep !== null ) {
176+ selectedTimelineID = selectedTimelineStep . id ;
177+ // $FlowFixMe
178+ while ( removedIDs . has ( selectedTimelineID ) ) {
179+ // $FlowFixMe
180+ selectedTimelineID = removedIDs . get ( selectedTimelineID ) ;
181+ }
177182 }
178183
179184 // TODO: Handle different timeline modes (e.g. random order)
180185 const nextTimeline = store . getSuspendableDocumentOrderSuspense (
181186 state . uniqueSuspendersOnly ,
182187 ) ;
183188
184- let nextTimelineIndex =
185- selectedTimelineID === null || nextTimeline . length === 0
186- ? - 1
187- : nextTimeline . indexOf ( selectedTimelineID ) ;
189+ let nextTimelineIndex = - 1 ;
190+ if ( selectedTimelineID !== null && nextTimeline . length !== 0 ) {
191+ for ( let i = 0 ; i < nextTimeline . length ; i ++ ) {
192+ if ( nextTimeline [ i ] . id === selectedTimelineID ) {
193+ nextTimelineIndex = i ;
194+ break ;
195+ }
196+ }
197+ }
188198 if (
189199 nextTimeline . length > 0 &&
190200 ( nextTimelineIndex === - 1 || state . autoSelect )
191201 ) {
192202 nextTimelineIndex = nextTimeline . length - 1 ;
193- selectedSuspenseID = nextTimeline [ nextTimelineIndex ] ;
203+ selectedSuspenseID = nextTimeline [ nextTimelineIndex ] . id ;
194204 }
195205
196206 if ( selectedSuspenseID === null && nextTimeline . length > 0 ) {
197- selectedSuspenseID = nextTimeline [ nextTimeline . length - 1 ] ;
207+ selectedSuspenseID = nextTimeline [ nextTimeline . length - 1 ] . id ;
198208 }
199209
200210 const nextLineage =
@@ -256,12 +266,12 @@ function SuspenseTreeContextController({children}: Props): React.Node {
256266 nextMilestoneIndex = nextTimeline . indexOf ( previousMilestoneID ) ;
257267 if ( nextMilestoneIndex === - 1 && nextTimeline . length > 0 ) {
258268 nextMilestoneIndex = nextTimeline . length - 1 ;
259- nextSelectedSuspenseID = nextTimeline [ nextMilestoneIndex ] ;
269+ nextSelectedSuspenseID = nextTimeline [ nextMilestoneIndex ] . id ;
260270 nextLineage = store . getSuspenseLineage ( nextSelectedSuspenseID ) ;
261271 }
262272 } else if ( nextRootID !== null ) {
263273 nextMilestoneIndex = nextTimeline . length - 1 ;
264- nextSelectedSuspenseID = nextTimeline [ nextMilestoneIndex ] ;
274+ nextSelectedSuspenseID = nextTimeline [ nextMilestoneIndex ] . id ;
265275 nextLineage = store . getSuspenseLineage ( nextSelectedSuspenseID ) ;
266276 }
267277
@@ -276,7 +286,7 @@ function SuspenseTreeContextController({children}: Props): React.Node {
276286 }
277287 case 'SUSPENSE_SET_TIMELINE_INDEX' : {
278288 const nextTimelineIndex = action . payload ;
279- const nextSelectedSuspenseID = state . timeline [ nextTimelineIndex ] ;
289+ const nextSelectedSuspenseID = state . timeline [ nextTimelineIndex ] . id ;
280290 const nextLineage = store . getSuspenseLineage (
281291 nextSelectedSuspenseID ,
282292 ) ;
@@ -301,7 +311,7 @@ function SuspenseTreeContextController({children}: Props): React.Node {
301311 ) {
302312 return state ;
303313 }
304- const nextSelectedSuspenseID = state . timeline [ nextTimelineIndex ] ;
314+ const nextSelectedSuspenseID = state . timeline [ nextTimelineIndex ] . id ;
305315 const nextLineage = store . getSuspenseLineage (
306316 nextSelectedSuspenseID ,
307317 ) ;
@@ -329,7 +339,7 @@ function SuspenseTreeContextController({children}: Props): React.Node {
329339 ) {
330340 // If we're restarting at the end. Then loop around and start again from the beginning.
331341 nextTimelineIndex = 0 ;
332- nextSelectedSuspenseID = state . timeline [ nextTimelineIndex ] ;
342+ nextSelectedSuspenseID = state . timeline [ nextTimelineIndex ] . id ;
333343 nextLineage = store . getSuspenseLineage ( nextSelectedSuspenseID ) ;
334344 }
335345
@@ -352,7 +362,7 @@ function SuspenseTreeContextController({children}: Props): React.Node {
352362 if ( nextTimelineIndex > state . timeline . length - 1 ) {
353363 return state ;
354364 }
355- const nextSelectedSuspenseID = state . timeline [ nextTimelineIndex ] ;
365+ const nextSelectedSuspenseID = state . timeline [ nextTimelineIndex ] . id ;
356366 const nextLineage = store . getSuspenseLineage (
357367 nextSelectedSuspenseID ,
358368 ) ;
@@ -369,8 +379,14 @@ function SuspenseTreeContextController({children}: Props): React.Node {
369379 }
370380 case 'TOGGLE_TIMELINE_FOR_ID' : {
371381 const suspenseID = action . payload ;
372- const timelineIndexForSuspenseID =
373- state . timeline . indexOf ( suspenseID ) ;
382+
383+ let timelineIndexForSuspenseID = - 1 ;
384+ for ( let i = 0 ; i < state . timeline . length ; i ++ ) {
385+ if ( state . timeline [ i ] . id === suspenseID ) {
386+ timelineIndexForSuspenseID = i ;
387+ break ;
388+ }
389+ }
374390 if ( timelineIndexForSuspenseID === - 1 ) {
375391 // This boundary is no longer in the timeline.
376392 return state ;
@@ -387,7 +403,7 @@ function SuspenseTreeContextController({children}: Props): React.Node {
387403 timelineIndexForSuspenseID
388404 : // Otherwise, if we're currently showing it, jump to right before to hide it.
389405 timelineIndexForSuspenseID - 1 ;
390- const nextSelectedSuspenseID = state . timeline [ nextTimelineIndex ] ;
406+ const nextSelectedSuspenseID = state . timeline [ nextTimelineIndex ] . id ;
391407 const nextLineage = store . getSuspenseLineage (
392408 nextSelectedSuspenseID ,
393409 ) ;
@@ -403,8 +419,13 @@ function SuspenseTreeContextController({children}: Props): React.Node {
403419 }
404420 case 'HOVER_TIMELINE_FOR_ID' : {
405421 const suspenseID = action . payload ;
406- const timelineIndexForSuspenseID =
407- state . timeline . indexOf ( suspenseID ) ;
422+ let timelineIndexForSuspenseID = - 1 ;
423+ for ( let i = 0 ; i < state . timeline . length ; i ++ ) {
424+ if ( state . timeline [ i ] . id === suspenseID ) {
425+ timelineIndexForSuspenseID = i ;
426+ break ;
427+ }
428+ }
408429 return {
409430 ...state ,
410431 hoveredTimelineIndex : timelineIndexForSuspenseID ,
0 commit comments