Skip to content

Commit f2ff58b

Browse files
paulirishDevtools-frontend LUCI CQ
authored andcommitted
ViewportDataGrid: Add enableAutoScrollToBottom preference
Bug:377763109 Change-Id: Iec8b46cc65b4026c5220c539ed2e96db6e6efa88 Reviewed-on: https://chromium-review.googlesource.com/c/devtools/devtools-frontend/+/6001603 Commit-Queue: Paul Irish <[email protected]> Reviewed-by: Adam Raine <[email protected]>
1 parent 1d0c2db commit f2ff58b

File tree

4 files changed

+23
-15
lines changed

4 files changed

+23
-15
lines changed

front_end/panels/network/EventSourceMessagesView.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ export class EventSourceMessagesView extends UI.Widget.VBox {
100100
refreshCallback: undefined,
101101
});
102102
this.dataGrid.setStriped(true);
103-
this.dataGrid.setStickToBottom(true);
103+
this.dataGrid.setEnableAutoScrollToBottom(true);
104104
this.dataGrid.setRowContextMenuCallback(this.onRowContextMenu.bind(this));
105105
this.dataGrid.markColumnAsSortedBy('time', DataGrid.DataGrid.Order.Ascending);
106106
this.sortItems();

front_end/panels/network/NetworkLogView.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1144,7 +1144,7 @@ export class NetworkLogView extends Common.ObjectWrapper.eventMixin<EventTypes,
11441144
this.handleContextMenuForRequest(contextMenu, request);
11451145
}
11461146
});
1147-
this.dataGrid.setStickToBottom(true);
1147+
this.dataGrid.setEnableAutoScrollToBottom(true);
11481148
this.dataGrid.setName('network-log');
11491149
this.dataGrid.setResizeMethod(DataGrid.DataGrid.ResizeMethod.LAST);
11501150
this.dataGrid.element.classList.add('network-log-grid');
@@ -1595,7 +1595,6 @@ export class NetworkLogView extends Common.ObjectWrapper.eventMixin<EventTypes,
15951595

15961596
this.dataGrid.rootNode().removeChildren();
15971597
this.updateSummaryBar();
1598-
this.dataGrid.setStickToBottom(true);
15991598
this.scheduleRefresh();
16001599
}
16011600

front_end/panels/network/ResourceWebSocketFrameView.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,7 @@ export class ResourceWebSocketFrameView extends UI.Widget.VBox {
190190
refreshCallback: undefined,
191191
});
192192
this.dataGrid.setRowContextMenuCallback(onRowContextMenu.bind(this));
193-
this.dataGrid.setStickToBottom(true);
193+
this.dataGrid.setEnableAutoScrollToBottom(true);
194194
this.dataGrid.setCellClass('websocket-frame-view-td');
195195
this.timeComparator =
196196
(resourceWebSocketFrameNodeTimeComparator as

front_end/ui/legacy/components/data_grid/ViewportDataGrid.ts

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,15 @@ export class ViewportDataGrid<T> extends Common.ObjectWrapper.eventMixin<EventTy
1414
DataGridImpl)<ViewportDataGridNode<T>> {
1515
private readonly onScrollBound: (event: Event|null) => void;
1616
private visibleNodes: ViewportDataGridNode<T>[];
17-
stickToBottom: boolean;
17+
/** A datagrid preference to express that the grid represents an updating log of rows (eg Network panel request log, websocket messages).
18+
* If `true`, the datagrid will mostly keep the scroll at the bottom, so new items are visible.
19+
* If the data is sorted descending (eg Performance Call Tree, heap snapshot), keep the default of `false`.
20+
*/
21+
enableAutoScrollToBottom: boolean = false;
22+
/** When true, the datagrid will manipulate the scrollTop to focus on the bottom, mostly so new additions are visible.
23+
* Some actions will unset this, like revealing or expanding a particular node.
24+
* Only matters if enableAutoScrollToBottom is true. */
25+
keepScrollingToBottom: boolean = false;
1826
private updateIsFromUser: boolean;
1927
private lastScrollTop: number;
2028
private firstVisibleIsStriped: boolean;
@@ -29,7 +37,6 @@ export class ViewportDataGrid<T> extends Common.ObjectWrapper.eventMixin<EventTy
2937
this.visibleNodes = [];
3038
this.inline = false;
3139

32-
this.stickToBottom = false;
3340
this.updateIsFromUser = false;
3441
this.lastScrollTop = 0;
3542
this.firstVisibleIsStriped = false;
@@ -60,15 +67,15 @@ export class ViewportDataGrid<T> extends Common.ObjectWrapper.eventMixin<EventTy
6067
}
6168

6269
override onResize(): void {
63-
if (this.stickToBottom) {
70+
if (this.keepScrollingToBottom) {
6471
this.scrollContainer.scrollTop = this.scrollContainer.scrollHeight - this.scrollContainer.clientHeight;
6572
}
6673
this.scheduleUpdate();
6774
super.onResize();
6875
}
6976

70-
setStickToBottom(stick: boolean): void {
71-
this.stickToBottom = stick;
77+
setEnableAutoScrollToBottom(stick: boolean): void {
78+
this.keepScrollingToBottom = this.enableAutoScrollToBottom = stick;
7279
}
7380

7481
private onScroll(_event: Event|null): void {
@@ -131,8 +138,10 @@ export class ViewportDataGrid<T> extends Common.ObjectWrapper.eventMixin<EventTy
131138
bottomPadding += nodes[i].nodeSelfHeight();
132139
}
133140

134-
// enable stick-to-bottom if the last item is visible
135-
this.stickToBottom = end === nodes.length;
141+
if (this.enableAutoScrollToBottom) {
142+
// If we're scrolled to the very end, keep the scroll viewport focused to the end (as new items arrive)
143+
this.keepScrollingToBottom = end === nodes.length;
144+
}
136145

137146
return {
138147
topPadding,
@@ -157,7 +166,7 @@ export class ViewportDataGrid<T> extends Common.ObjectWrapper.eventMixin<EventTy
157166
let scrollTop: number = this.scrollContainer.scrollTop;
158167
const currentScrollTop = scrollTop;
159168
const maxScrollTop = Math.max(0, this.contentHeight() - clientHeight);
160-
if (!this.updateIsFromUser && this.stickToBottom) {
169+
if (!this.updateIsFromUser && this.keepScrollingToBottom) {
161170
scrollTop = maxScrollTop;
162171
}
163172
this.updateIsFromUser = false;
@@ -185,7 +194,7 @@ export class ViewportDataGrid<T> extends Common.ObjectWrapper.eventMixin<EventTy
185194
const nodes = (this.rootNode() as ViewportDataGridNode<T>).flatChildren();
186195
const index = nodes.indexOf(visibleNodes[0]);
187196
this.updateStripesClass(Boolean(index % 2));
188-
if (this.stickToBottom && index !== -1 && Boolean(index % 2) !== this.firstVisibleIsStriped) {
197+
if (this.keepScrollingToBottom && index !== -1 && Boolean(index % 2) !== this.firstVisibleIsStriped) {
189198
offset += 1;
190199
}
191200
}
@@ -233,7 +242,7 @@ export class ViewportDataGrid<T> extends Common.ObjectWrapper.eventMixin<EventTy
233242
const visibleHeight = this.scrollContainer.offsetHeight - this.headerHeightInScroller();
234243
if (scrollTop > fromY) {
235244
scrollTop = fromY;
236-
this.stickToBottom = false;
245+
this.keepScrollingToBottom = false;
237246
} else if (scrollTop + visibleHeight < toY) {
238247
scrollTop = toY - visibleHeight;
239248
}
@@ -410,7 +419,7 @@ export class ViewportDataGridNode<T> extends DataGridNode<ViewportDataGridNode<T
410419
if (this.expanded) {
411420
return;
412421
}
413-
(this.dataGrid as ViewportDataGrid<T>).stickToBottom = false;
422+
(this.dataGrid as ViewportDataGrid<T>).keepScrollingToBottom = false;
414423
this.clearFlatNodes();
415424
super.expand();
416425
(this.dataGrid as ViewportDataGrid<T>).scheduleUpdateStructure();

0 commit comments

Comments
 (0)