mirror of
https://github.com/react/react-native-devtools-frontend.git
synced 2026-10-06 12:01:40 +08:00
This is a reland of cef170cfe5
The change accidentally deleted a line that allowed for the overview timeline
highlighting of the currently selected node. This has been fixed.
Original change's description:
> Network A11y: Improve keyboarding experience of Network tool Datagrid
>
> This changes builds off of
> https://chromium-review.googlesource.com/c/devtools/devtools-frontend/+/1881219
> in order to improve the keyboard accessibility
> of the Network tool Datagrid.
>
> Previously, the network tool ties selection of a node in the grid
> directly to opening the request sidepane. This makes it challenging for
> keyboard only users to view and navigate the network tool datagrid
> columns.
>
> This change separates selection from opening the sidepane, and fixes
> styling issues that affect the columns that were previously hidden
> behind the sidepane when a node is selected. Selected nodes are
> highlighted in the grid, and are "activated" using the enter key
> or a click in the primary column to open the sidepane.
>
> Before: https://imgur.com/U1PG6Hr
>
> After: https://imgur.com/eXgDE9D
>
> Bug: 963183
>
> Change-Id: I2c2629670624e807adb4cd9e9e9b75cdafbae7a5
> Reviewed-on: https://chromium-review.googlesource.com/c/devtools/devtools-frontend/+/1881592
> Commit-Queue: Brandon Goddard <brgoddar@microsoft.com>
> Reviewed-by: Lorne Mitchell <lomitch@microsoft.com>
> Reviewed-by: Jan Scheffler <janscheffler@chromium.org>
Bug: 963183
Change-Id: I4dfd0a67cd1fce6e6dd8066ceb84841d21191ef3
Reviewed-on: https://chromium-review.googlesource.com/c/devtools/devtools-frontend/+/1896256
Reviewed-by: Lorne Mitchell <lomitch@microsoft.com>
Commit-Queue: Brandon Goddard <brgoddar@microsoft.com>
346 lines
11 KiB
JavaScript
346 lines
11 KiB
JavaScript
// Copyright 2015 The Chromium Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
/**
|
|
* @unrestricted
|
|
*/
|
|
Network.NetworkOverview = class extends PerfUI.TimelineOverviewBase {
|
|
constructor() {
|
|
super();
|
|
this._selectedFilmStripTime = -1;
|
|
this.element.classList.add('network-overview');
|
|
|
|
/** @type {number} */
|
|
this._numBands = 1;
|
|
/** @type {boolean} */
|
|
this._updateScheduled = false;
|
|
this._highlightedRequest = null;
|
|
|
|
SDK.targetManager.addModelListener(
|
|
SDK.ResourceTreeModel, SDK.ResourceTreeModel.Events.Load, this._loadEventFired, this);
|
|
SDK.targetManager.addModelListener(
|
|
SDK.ResourceTreeModel, SDK.ResourceTreeModel.Events.DOMContentLoaded, this._domContentLoadedEventFired, this);
|
|
|
|
this.reset();
|
|
}
|
|
|
|
setHighlightedRequest(request) {
|
|
this._highlightedRequest = request;
|
|
this.scheduleUpdate();
|
|
}
|
|
|
|
/**
|
|
* @param {?SDK.FilmStripModel} filmStripModel
|
|
*/
|
|
setFilmStripModel(filmStripModel) {
|
|
this._filmStripModel = filmStripModel;
|
|
this.scheduleUpdate();
|
|
}
|
|
|
|
/**
|
|
* @param {number} time
|
|
*/
|
|
selectFilmStripFrame(time) {
|
|
this._selectedFilmStripTime = time;
|
|
this.scheduleUpdate();
|
|
}
|
|
|
|
clearFilmStripFrame() {
|
|
this._selectedFilmStripTime = -1;
|
|
this.scheduleUpdate();
|
|
}
|
|
|
|
/**
|
|
* @param {!Common.Event} event
|
|
*/
|
|
_loadEventFired(event) {
|
|
const time = /** @type {number} */ (event.data.loadTime);
|
|
if (time) {
|
|
this._loadEvents.push(time * 1000);
|
|
}
|
|
this.scheduleUpdate();
|
|
}
|
|
|
|
/**
|
|
* @param {!Common.Event} event
|
|
*/
|
|
_domContentLoadedEventFired(event) {
|
|
const data = /** @type {number} */ (event.data);
|
|
if (data) {
|
|
this._domContentLoadedEvents.push(data * 1000);
|
|
}
|
|
this.scheduleUpdate();
|
|
}
|
|
|
|
/**
|
|
* @param {string} connectionId
|
|
* @return {number}
|
|
*/
|
|
_bandId(connectionId) {
|
|
if (!connectionId || connectionId === '0') {
|
|
return -1;
|
|
}
|
|
if (this._bandMap.has(connectionId)) {
|
|
return /** @type {number} */ (this._bandMap.get(connectionId));
|
|
}
|
|
const result = this._nextBand++;
|
|
this._bandMap.set(connectionId, result);
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* @param {!SDK.NetworkRequest} request
|
|
*/
|
|
updateRequest(request) {
|
|
if (!this._requestsSet.has(request)) {
|
|
this._requestsSet.add(request);
|
|
this._requestsList.push(request);
|
|
}
|
|
this.scheduleUpdate();
|
|
}
|
|
|
|
/**
|
|
* @override
|
|
*/
|
|
wasShown() {
|
|
this.onResize();
|
|
}
|
|
|
|
/**
|
|
* @override
|
|
*/
|
|
onResize() {
|
|
const width = this.element.offsetWidth;
|
|
const height = this.element.offsetHeight;
|
|
this.calculator().setDisplayWidth(width);
|
|
this.resetCanvas();
|
|
const numBands = (((height - Network.NetworkOverview._padding - 1) / Network.NetworkOverview._bandHeight) - 1) | 0;
|
|
this._numBands = (numBands > 0) ? numBands : 1;
|
|
this.scheduleUpdate();
|
|
}
|
|
|
|
/**
|
|
* @override
|
|
*/
|
|
reset() {
|
|
/** @type {?SDK.FilmStripModel} */
|
|
this._filmStripModel = null;
|
|
|
|
/** @type {number} */
|
|
this._span = 1;
|
|
/** @type {?Network.NetworkTimeBoundary} */
|
|
this._lastBoundary = null;
|
|
/** @type {number} */
|
|
this._nextBand = 0;
|
|
/** @type {!Map.<string, number>} */
|
|
this._bandMap = new Map();
|
|
/** @type {!Array.<!SDK.NetworkRequest>} */
|
|
this._requestsList = [];
|
|
/** @type {!Set.<!SDK.NetworkRequest>} */
|
|
this._requestsSet = new Set();
|
|
/** @type {!Array.<number>} */
|
|
this._loadEvents = [];
|
|
/** @type {!Array.<number>} */
|
|
this._domContentLoadedEvents = [];
|
|
|
|
// Clear screen.
|
|
this.resetCanvas();
|
|
}
|
|
|
|
/**
|
|
* @protected
|
|
*/
|
|
scheduleUpdate() {
|
|
if (this._updateScheduled || !this.isShowing()) {
|
|
return;
|
|
}
|
|
this._updateScheduled = true;
|
|
this.element.window().requestAnimationFrame(this.update.bind(this));
|
|
}
|
|
|
|
/**
|
|
* @override
|
|
*/
|
|
update() {
|
|
this._updateScheduled = false;
|
|
|
|
const calculator = this.calculator();
|
|
|
|
const newBoundary = new Network.NetworkTimeBoundary(calculator.minimumBoundary(), calculator.maximumBoundary());
|
|
if (!this._lastBoundary || !newBoundary.equals(this._lastBoundary)) {
|
|
const span = calculator.boundarySpan();
|
|
while (this._span < span) {
|
|
this._span *= 1.25;
|
|
}
|
|
|
|
calculator.setBounds(calculator.minimumBoundary(), calculator.minimumBoundary() + this._span);
|
|
this._lastBoundary = new Network.NetworkTimeBoundary(calculator.minimumBoundary(), calculator.maximumBoundary());
|
|
}
|
|
|
|
const context = this.context();
|
|
const linesByType = {};
|
|
const paddingTop = Network.NetworkOverview._padding;
|
|
|
|
/**
|
|
* @param {string} type
|
|
*/
|
|
function drawLines(type) {
|
|
const lines = linesByType[type];
|
|
if (!lines) {
|
|
return;
|
|
}
|
|
const n = lines.length;
|
|
context.beginPath();
|
|
context.strokeStyle = Network.NetworkOverview.RequestTimeRangeNameToColor[type];
|
|
for (let i = 0; i < n;) {
|
|
const y = lines[i++] * Network.NetworkOverview._bandHeight + paddingTop;
|
|
const startTime = lines[i++];
|
|
let endTime = lines[i++];
|
|
if (endTime === Number.MAX_VALUE) {
|
|
endTime = calculator.maximumBoundary();
|
|
}
|
|
context.moveTo(calculator.computePosition(startTime), y);
|
|
context.lineTo(calculator.computePosition(endTime) + 1, y);
|
|
}
|
|
context.stroke();
|
|
}
|
|
|
|
/**
|
|
* @param {string} type
|
|
* @param {number} y
|
|
* @param {number} start
|
|
* @param {number} end
|
|
*/
|
|
function addLine(type, y, start, end) {
|
|
let lines = linesByType[type];
|
|
if (!lines) {
|
|
lines = [];
|
|
linesByType[type] = lines;
|
|
}
|
|
lines.push(y, start, end);
|
|
}
|
|
|
|
const requests = this._requestsList;
|
|
const n = requests.length;
|
|
for (let i = 0; i < n; ++i) {
|
|
const request = requests[i];
|
|
const band = this._bandId(request.connectionId);
|
|
const y = (band === -1) ? 0 : (band % this._numBands + 1);
|
|
const timeRanges =
|
|
Network.RequestTimingView.calculateRequestTimeRanges(request, this.calculator().minimumBoundary());
|
|
for (let j = 0; j < timeRanges.length; ++j) {
|
|
const type = timeRanges[j].name;
|
|
if (band !== -1 || type === Network.RequestTimeRangeNames.Total) {
|
|
addLine(type, y, timeRanges[j].start * 1000, timeRanges[j].end * 1000);
|
|
}
|
|
}
|
|
}
|
|
|
|
context.clearRect(0, 0, this.width(), this.height());
|
|
context.save();
|
|
context.scale(window.devicePixelRatio, window.devicePixelRatio);
|
|
context.lineWidth = 2;
|
|
drawLines(Network.RequestTimeRangeNames.Total);
|
|
drawLines(Network.RequestTimeRangeNames.Blocking);
|
|
drawLines(Network.RequestTimeRangeNames.Connecting);
|
|
drawLines(Network.RequestTimeRangeNames.ServiceWorker);
|
|
drawLines(Network.RequestTimeRangeNames.ServiceWorkerPreparation);
|
|
drawLines(Network.RequestTimeRangeNames.Push);
|
|
drawLines(Network.RequestTimeRangeNames.Proxy);
|
|
drawLines(Network.RequestTimeRangeNames.DNS);
|
|
drawLines(Network.RequestTimeRangeNames.SSL);
|
|
drawLines(Network.RequestTimeRangeNames.Sending);
|
|
drawLines(Network.RequestTimeRangeNames.Waiting);
|
|
drawLines(Network.RequestTimeRangeNames.Receiving);
|
|
|
|
if (this._highlightedRequest) {
|
|
const size = 5;
|
|
const borderSize = 2;
|
|
|
|
const request = this._highlightedRequest;
|
|
const band = this._bandId(request.connectionId);
|
|
const y = ((band === -1) ? 0 : (band % this._numBands + 1)) * Network.NetworkOverview._bandHeight + paddingTop;
|
|
const timeRanges =
|
|
Network.RequestTimingView.calculateRequestTimeRanges(request, this.calculator().minimumBoundary());
|
|
|
|
// This is the value of var(--selection-bg-color)
|
|
// to match the selection color used in the performance panel
|
|
context.fillStyle = '#1a73e8';
|
|
|
|
const start = timeRanges[0].start * 1000;
|
|
const end = timeRanges[0].end * 1000;
|
|
context.fillRect(
|
|
calculator.computePosition(start) - borderSize, y - size / 2 - borderSize,
|
|
calculator.computePosition(end) - calculator.computePosition(start) + 1 + 2 * borderSize, size * borderSize);
|
|
|
|
for (let j = 0; j < timeRanges.length; ++j) {
|
|
const type = timeRanges[j].name;
|
|
if (band !== -1 || type === Network.RequestTimeRangeNames.Total) {
|
|
context.beginPath();
|
|
context.strokeStyle = Network.NetworkOverview.RequestTimeRangeNameToColor[type];
|
|
context.lineWidth = size;
|
|
|
|
const start = timeRanges[j].start * 1000;
|
|
const end = timeRanges[j].end * 1000;
|
|
context.moveTo(calculator.computePosition(start) - 0, y);
|
|
context.lineTo(calculator.computePosition(end) + 1, y);
|
|
context.stroke();
|
|
}
|
|
}
|
|
}
|
|
|
|
const height = this.element.offsetHeight;
|
|
context.lineWidth = 1;
|
|
context.beginPath();
|
|
context.strokeStyle = Network.NetworkLogView.getDCLEventColor();
|
|
for (let i = this._domContentLoadedEvents.length - 1; i >= 0; --i) {
|
|
const x = Math.round(calculator.computePosition(this._domContentLoadedEvents[i])) + 0.5;
|
|
context.moveTo(x, 0);
|
|
context.lineTo(x, height);
|
|
}
|
|
context.stroke();
|
|
|
|
context.beginPath();
|
|
context.strokeStyle = Network.NetworkLogView.getLoadEventColor();
|
|
for (let i = this._loadEvents.length - 1; i >= 0; --i) {
|
|
const x = Math.round(calculator.computePosition(this._loadEvents[i])) + 0.5;
|
|
context.moveTo(x, 0);
|
|
context.lineTo(x, height);
|
|
}
|
|
context.stroke();
|
|
|
|
if (this._selectedFilmStripTime !== -1) {
|
|
context.lineWidth = 2;
|
|
context.beginPath();
|
|
context.strokeStyle = '#FCCC49'; // Keep in sync with .network-frame-divider CSS rule.
|
|
const x = Math.round(calculator.computePosition(this._selectedFilmStripTime));
|
|
context.moveTo(x, 0);
|
|
context.lineTo(x, height);
|
|
context.stroke();
|
|
}
|
|
context.restore();
|
|
}
|
|
};
|
|
|
|
Network.NetworkOverview.RequestTimeRangeNameToColor = {
|
|
[Network.RequestTimeRangeNames.Total]: '#CCCCCC',
|
|
[Network.RequestTimeRangeNames.Blocking]: '#AAAAAA',
|
|
[Network.RequestTimeRangeNames.Connecting]: '#FF9800',
|
|
[Network.RequestTimeRangeNames.ServiceWorker]: '#FF9800',
|
|
[Network.RequestTimeRangeNames.ServiceWorkerPreparation]: '#FF9800',
|
|
[Network.RequestTimeRangeNames.Push]: '#8CDBff',
|
|
[Network.RequestTimeRangeNames.Proxy]: '#A1887F',
|
|
[Network.RequestTimeRangeNames.DNS]: '#009688',
|
|
[Network.RequestTimeRangeNames.SSL]: '#9C27B0',
|
|
[Network.RequestTimeRangeNames.Sending]: '#B0BEC5',
|
|
[Network.RequestTimeRangeNames.Waiting]: '#00C853',
|
|
[Network.RequestTimeRangeNames.Receiving]: '#03A9F4',
|
|
};
|
|
|
|
/** @type {number} */
|
|
Network.NetworkOverview._bandHeight = 3;
|
|
Network.NetworkOverview._padding = 5;
|
|
|
|
/** @typedef {{start: number, end: number}} */
|
|
Network.NetworkOverview.Window;
|