diff --git a/Libraries/Inspector/NetworkOverlay.js b/Libraries/Inspector/NetworkOverlay.js index 90f143b45669be..86fe8da1ac829a 100644 --- a/Libraries/Inspector/NetworkOverlay.js +++ b/Libraries/Inspector/NetworkOverlay.js @@ -88,6 +88,16 @@ class NetworkOverlay extends React.Component { _requestsListView: ?React.ElementRef; _detailScrollView: ?React.ElementRef; + // Metrics are used to decide when if the request list should be sticky, and + // scroll to the bottom as new network requests come in, or if the user has + // intentionally scrolled away from the bottom - to instead flash the scroll bar + // and keep the current position + _requestsListViewScrollMetrics = { + offset: 0, + visibleLength: 0, + contentLength: 0, + }; + // Map of `socketId` -> `index in `this.state.requests`. _socketIdMap = {}; // Map of `xhr._index` -> `index in `this.state.requests`. @@ -121,7 +131,7 @@ class NetworkOverlay extends React.Component { { requests: this.state.requests.concat(_xhr), }, - this._scrollRequestsToBottom, + this._indicateAdditionalRequests, ); }); @@ -214,7 +224,7 @@ class NetworkOverlay extends React.Component { { requests: this.state.requests.concat(_webSocket), }, - this._scrollRequestsToBottom, + this._indicateAdditionalRequests, ); }, ); @@ -383,11 +393,35 @@ class NetworkOverlay extends React.Component { ); } - _scrollRequestsToBottom(): void { + _indicateAdditionalRequests = (): void => { if (this._requestsListView) { - this._requestsListView.scrollToEnd(); + const distanceFromEndThreshold = LISTVIEW_CELL_HEIGHT * 2; + const { + offset, + visibleLength, + contentLength, + } = this._requestsListViewScrollMetrics; + const distanceFromEnd = contentLength - visibleLength - offset; + const isCloseToEnd = distanceFromEnd <= distanceFromEndThreshold; + if (isCloseToEnd) { + this._requestsListView.scrollToEnd(); + } else { + this._requestsListView.flashScrollIndicators(); + } } - } + }; + + _captureRequestsListView = (listRef: ?FlatList): void => { + this._requestsListView = listRef; + }; + + _requestsListViewOnScroll = (e: Object): void => { + this._requestsListViewScrollMetrics.offset = e.nativeEvent.contentOffset.y; + this._requestsListViewScrollMetrics.visibleLength = + e.nativeEvent.layoutMeasurement.height; + this._requestsListViewScrollMetrics.contentLength = + e.nativeEvent.contentSize.height; + }; /** * Popup a scrollView to dynamically show detailed information of @@ -446,7 +480,8 @@ class NetworkOverlay extends React.Component { (this._requestsListView = listRef)} + ref={this._captureRequestsListView} + onScroll={this._requestsListViewOnScroll} style={styles.listView} data={requests} renderItem={this._renderItem}