@samitouri / QOS-React / commits / f89ed71ddf

[DevTools] Track whether to auto select when new timeline entries come on (#34698)

This auto updates to select the last entry in the timeline until we make the first selection. That way when new content loads in, we show the last timeline of what is visible.

Sebastian Markbåge committed Oct 2, 2025 at 17:06 UTC f89ed71ddf5f8cab28b202cfdc04927c683ad3cc
1 file changed +12 -1
packages/react-devtools-shared/src/devtools/views/SuspenseTab/SuspenseTreeContext.js
+12 -1
@@ -30,6 +30,7 @@ export type SuspenseTreeState = {
30 hoveredTimelineIndex: number | -1,
31 uniqueSuspendersOnly: boolean,
32 playing: boolean,
33 + autoSelect: boolean,
34 };
35
36 type ACTION_SUSPENSE_TREE_MUTATION = {
@@ -123,6 +124,7 @@ function getInitialState(store: Store): SuspenseTreeState {
124 hoveredTimelineIndex: -1,
125 uniqueSuspendersOnly,
126 playing: false,
127 + autoSelect: true,
128 };
129
130 return initialState;
@@ -181,7 +183,10 @@ function SuspenseTreeContextController({children}: Props): React.Node {
183 selectedTimelineID === null || nextTimeline.length === 0
184 ? -1
185 : nextTimeline.indexOf(selectedTimelineID);
184 - if (nextTimeline.length > 0 && nextTimelineIndex === -1) {
186 + if (
187 + nextTimeline.length > 0 &&
188 + (nextTimelineIndex === -1 || state.autoSelect)
189 + ) {
190 nextTimelineIndex = nextTimeline.length - 1;
191 selectedSuspenseID = nextTimeline[nextTimelineIndex];
192 }
@@ -212,6 +217,7 @@ function SuspenseTreeContextController({children}: Props): React.Node {
217 ...state,
218 selectedSuspenseID,
219 playing: false, // pause
220 + autoSelect: false,
221 };
222 }
223 case 'SET_SUSPENSE_LINEAGE': {
@@ -223,6 +229,7 @@ function SuspenseTreeContextController({children}: Props): React.Node {
229 lineage,
230 selectedSuspenseID: suspenseID,
231 playing: false, // pause
232 + autoSelect: false,
233 };
234 }
235 case 'SET_SUSPENSE_TIMELINE': {
@@ -277,6 +284,7 @@ function SuspenseTreeContextController({children}: Props): React.Node {
284 selectedSuspenseID: nextSelectedSuspenseID,
285 timelineIndex: nextTimelineIndex,
286 playing: false, // pause
287 + autoSelect: false,
288 };
289 }
290 case 'SUSPENSE_SKIP_TIMELINE_INDEX': {
@@ -299,6 +307,7 @@ function SuspenseTreeContextController({children}: Props): React.Node {
307 selectedSuspenseID: nextSelectedSuspenseID,
308 timelineIndex: nextTimelineIndex,
309 playing: false, // pause
310 + autoSelect: false,
311 };
312 }
313 case 'SUSPENSE_PLAY_PAUSE': {
@@ -325,6 +334,7 @@ function SuspenseTreeContextController({children}: Props): React.Node {
334 selectedSuspenseID: nextSelectedSuspenseID,
335 timelineIndex: nextTimelineIndex,
336 playing: mode === 'toggle' ? !state.playing : mode === 'play',
337 + autoSelect: false,
338 };
339 }
340 case 'SUSPENSE_PLAY_TICK': {
@@ -381,6 +391,7 @@ function SuspenseTreeContextController({children}: Props): React.Node {
391 selectedSuspenseID: nextSelectedSuspenseID,
392 timelineIndex: nextTimelineIndex,
393 playing: false, // pause
394 + autoSelect: false,
395 };
396 }
397 case 'HOVER_TIMELINE_FOR_ID': {