7
* @flow
8
*/
9
import 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';
14
import type Store from '../../store';
15
16
import * as React from 'react';
28
lineage: $ReadOnlyArray<SuspenseNode['id']> | null,
29
roots: $ReadOnlyArray<SuspenseNode['id']>,
30
selectedSuspenseID: SuspenseNode['id'] | null,
28
- timeline: $ReadOnlyArray<SuspenseNode['id']>,
31
+ timeline: $ReadOnlyArray<SuspenseTimelineStep>,
32
timelineIndex: number | -1,
33
hoveredTimelineIndex: number | -1,
34
uniqueSuspendersOnly: boolean,
52
type ACTION_SET_SUSPENSE_TIMELINE = {
53
type: 'SET_SUSPENSE_TIMELINE',
54
payload: [
52
- $ReadOnlyArray<SuspenseNode['id']>,
55
+ $ReadOnlyArray<SuspenseTimelineStep>,
56
// The next Suspense ID to select in the timeline
57
SuspenseNode['id'] | null,
58
// Whether this timeline includes only unique suspenders
114
store.getSuspendableDocumentOrderSuspense(uniqueSuspendersOnly);
115
const timelineIndex = timeline.length - 1;
116
const selectedSuspenseID =
114
- timelineIndex === -1 ? null : timeline[timelineIndex];
117
+ timelineIndex === -1 ? null : timeline[timelineIndex].id;
118
const lineage =
119
selectedSuspenseID !== null
120
? store.getSuspenseLineage(selectedSuspenseID)
167
selectedSuspenseID = null;
168
}
169
167
- let selectedTimelineID =
168
- state.timeline === null
170
+ const selectedTimelineStep =
171
+ state.timeline === null || state.timelineIndex === -1
172
? null
173
: 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
+ }
182
}
183
184
// TODO: Handle different timeline modes (e.g. random order)
186
state.uniqueSuspendersOnly,
187
);
188
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
+ }
198
if (
199
nextTimeline.length > 0 &&
200
(nextTimelineIndex === -1 || state.autoSelect)
201
) {
202
nextTimelineIndex = nextTimeline.length - 1;
193
- selectedSuspenseID = nextTimeline[nextTimelineIndex];
203
+ selectedSuspenseID = nextTimeline[nextTimelineIndex].id;
204
}
205
206
if (selectedSuspenseID === null && nextTimeline.length > 0) {
197
- selectedSuspenseID = nextTimeline[nextTimeline.length - 1];
207
+ selectedSuspenseID = nextTimeline[nextTimeline.length - 1].id;
208
}
209
210
const nextLineage =
266
nextMilestoneIndex = nextTimeline.indexOf(previousMilestoneID);
267
if (nextMilestoneIndex === -1 && nextTimeline.length > 0) {
268
nextMilestoneIndex = nextTimeline.length - 1;
259
- nextSelectedSuspenseID = nextTimeline[nextMilestoneIndex];
269
+ nextSelectedSuspenseID = nextTimeline[nextMilestoneIndex].id;
270
nextLineage = store.getSuspenseLineage(nextSelectedSuspenseID);
271
}
272
} else if (nextRootID !== null) {
273
nextMilestoneIndex = nextTimeline.length - 1;
264
- nextSelectedSuspenseID = nextTimeline[nextMilestoneIndex];
274
+ nextSelectedSuspenseID = nextTimeline[nextMilestoneIndex].id;
275
nextLineage = store.getSuspenseLineage(nextSelectedSuspenseID);
276
}
277
286
}
287
case 'SUSPENSE_SET_TIMELINE_INDEX': {
288
const nextTimelineIndex = action.payload;
279
- const nextSelectedSuspenseID = state.timeline[nextTimelineIndex];
289
+ const nextSelectedSuspenseID = state.timeline[nextTimelineIndex].id;
290
const nextLineage = store.getSuspenseLineage(
291
nextSelectedSuspenseID,
292
);
311
) {
312
return state;
313
}
304
- const nextSelectedSuspenseID = state.timeline[nextTimelineIndex];
314
+ const nextSelectedSuspenseID = state.timeline[nextTimelineIndex].id;
315
const nextLineage = store.getSuspenseLineage(
316
nextSelectedSuspenseID,
317
);
339
) {
340
// If we're restarting at the end. Then loop around and start again from the beginning.
341
nextTimelineIndex = 0;
332
- nextSelectedSuspenseID = state.timeline[nextTimelineIndex];
342
+ nextSelectedSuspenseID = state.timeline[nextTimelineIndex].id;
343
nextLineage = store.getSuspenseLineage(nextSelectedSuspenseID);
344
}
345
362
if (nextTimelineIndex > state.timeline.length - 1) {
363
return state;
364
}
355
- const nextSelectedSuspenseID = state.timeline[nextTimelineIndex];
365
+ const nextSelectedSuspenseID = state.timeline[nextTimelineIndex].id;
366
const nextLineage = store.getSuspenseLineage(
367
nextSelectedSuspenseID,
368
);
379
}
380
case 'TOGGLE_TIMELINE_FOR_ID': {
381
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
+ }
390
if (timelineIndexForSuspenseID === -1) {
391
// This boundary is no longer in the timeline.
392
return state;
403
timelineIndexForSuspenseID
404
: // Otherwise, if we're currently showing it, jump to right before to hide it.
405
timelineIndexForSuspenseID - 1;
390
- const nextSelectedSuspenseID = state.timeline[nextTimelineIndex];
406
+ const nextSelectedSuspenseID = state.timeline[nextTimelineIndex].id;
407
const nextLineage = store.getSuspenseLineage(
408
nextSelectedSuspenseID,
409
);
419
}
420
case 'HOVER_TIMELINE_FOR_ID': {
421
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
+ }
429
return {
430
...state,
431
hoveredTimelineIndex: timelineIndexForSuspenseID,