[DevTools] Add more descriptive UI for state transitions.
This CL incorporates some of the changes discussed in the latest UX meeting:
- Reorder the columns and toolbar buttons
- Display the metadata in a manner to a similar to the Network panel
- Add instructions for the inital landing page and other UI states
Bug: 942174
Change-Id: I7bd451377b241ec70d49c6d0b443522b43e5bcfe
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1578554
Commit-Queue: Rayan Kanso <[email protected]>
Reviewed-by: Dmitry Gozman <[email protected]>
Cr-Original-Commit-Position: refs/heads/master@{#653543}
Cr-Mirrored-From: https://chromium.googlesource.com/chromium/src
Cr-Mirrored-Commit: 7150235b5070ebb8d03e4b6f4dd4ae3650cab283
diff --git a/front_end/resources/BackgroundServiceView.js b/front_end/resources/BackgroundServiceView.js
index 4021f43..bfd5c8e 100644
--- a/front_end/resources/BackgroundServiceView.js
+++ b/front_end/resources/BackgroundServiceView.js
@@ -4,6 +4,21 @@
Resources.BackgroundServiceView = class extends UI.VBox {
/**
+ * @param {string} serviceName The name of the background service.
+ * @return {string} The UI String to display.
+ */
+ static getUIString(serviceName) {
+ switch (serviceName) {
+ case Protocol.BackgroundService.ServiceName.BackgroundFetch:
+ return ls`Background Fetch`;
+ case Protocol.BackgroundService.ServiceName.BackgroundSync:
+ return ls`Background Sync`;
+ default:
+ return '';
+ }
+ }
+
+ /**
* @param {!Protocol.BackgroundService.ServiceName} serviceName
* @param {!Resources.BackgroundServiceModel} model
*/
@@ -57,6 +72,9 @@
/** @const {!UI.VBox} */
this._previewPanel = new UI.VBox();
+ /** @type {?Resources.BackgroundServiceView.EventDataNode} */
+ this._selectedEventNode = null;
+
/** @type {?UI.Widget} */
this._preview = null;
@@ -82,16 +100,16 @@
this._toolbar.appendSeparator();
- this._originCheckbox =
- new UI.ToolbarCheckbox(ls`Show events from other domains`, undefined, () => this._refreshView());
- this._toolbar.appendToolbarItem(this._originCheckbox);
-
- this._toolbar.appendSeparator();
-
this._saveButton = new UI.ToolbarButton(ls`Save events`, 'largeicon-download');
this._saveButton.addEventListener(UI.ToolbarButton.Events.Click, () => this._saveToFile());
this._saveButton.setEnabled(false);
this._toolbar.appendToolbarItem(this._saveButton);
+
+ this._toolbar.appendSeparator();
+
+ this._originCheckbox =
+ new UI.ToolbarCheckbox(ls`Show events from other domains`, undefined, () => this._refreshView());
+ this._toolbar.appendToolbarItem(this._originCheckbox);
}
/**
@@ -108,9 +126,10 @@
* Clears the grid and panel.
*/
_clearView() {
+ this._selectedEventNode = null;
this._dataGrid.rootNode().removeChildren();
- this._showPreview(null);
this._saveButton.setEnabled(false);
+ this._showPreview(null);
}
/**
@@ -135,7 +154,12 @@
const state = /** @type {!Resources.BackgroundServiceModel.RecordingState} */ (event.data);
if (state.serviceName !== this._serviceName)
return;
+
+ if (state.isRecording === this._recordButton.toggled())
+ return;
+
this._recordButton.setToggled(state.isRecording);
+ this._showPreview(this._selectedEventNode);
}
/**
@@ -163,8 +187,10 @@
const dataNode = new Resources.BackgroundServiceView.EventDataNode(data, serviceEvent.eventMetadata);
this._dataGrid.rootNode().appendChild(dataNode);
- // There's at least one event. So we can allow saving the events.
- this._saveButton.setEnabled(true);
+ if (this._dataGrid.rootNode().children.length === 1) {
+ this._saveButton.setEnabled(true);
+ this._showPreview(this._selectedEventNode);
+ }
}
/**
@@ -174,9 +200,9 @@
const columns = /** @type {!Array<!DataGrid.DataGrid.ColumnDescriptor>} */ ([
{id: 'id', title: ls`#`, weight: 1},
{id: 'timestamp', title: ls`Timestamp`, weight: 8},
+ {id: 'eventName', title: ls`Event`, weight: 10},
{id: 'origin', title: ls`Origin`, weight: 10},
{id: 'swSource', title: ls`SW Source`, weight: 4},
- {id: 'eventName', title: ls`Event`, weight: 10},
{id: 'instanceId', title: ls`Instance ID`, weight: 10},
]);
const dataGrid = new DataGrid.DataGrid(columns);
@@ -238,13 +264,36 @@
* @param {?Resources.BackgroundServiceView.EventDataNode} dataNode
*/
_showPreview(dataNode) {
+ if (this._selectedEventNode && this._selectedEventNode === dataNode)
+ return;
+
+ this._selectedEventNode = dataNode;
+
if (this._preview)
this._preview.detach();
- if (dataNode)
- this._preview = dataNode.createPreview();
- else
- this._preview = new UI.EmptyWidget(ls`Select a value to preview`);
+ if (this._selectedEventNode) {
+ this._preview = this._selectedEventNode.createPreview();
+ } else if (this._dataGrid.rootNode().children.length) {
+ // Inform users that grid entries are clickable.
+ this._preview = new UI.EmptyWidget(ls`Select an entry to view metadata`);
+ } else if (this._recordButton.toggled()) {
+ // Inform users that we are recording/waiting for events.
+ this._preview = new UI.EmptyWidget(
+ ls`Recording ${Resources.BackgroundServiceView.getUIString(this._serviceName)} activity...`);
+ } else {
+ this._preview = new UI.VBox();
+ this._preview.contentElement.classList.add('background-service-landing-page');
+ const centered = this._preview.contentElement.createChild('div');
+
+ const landingRecordButton =
+ new UI.ToolbarToggle(ls`Toggle Record`, 'largeicon-start-recording', 'largeicon-stop-recording');
+ landingRecordButton.addEventListener(UI.ToolbarButton.Events.Click, () => this._toggleRecording());
+
+ // TODO(rayankans): Add a keyboard shortcut.
+ centered.createChild('p').appendChild(UI.formatLocalized(
+ 'Click the record button %s to start recording.', [UI.createInlineButton(landingRecordButton)]));
+ }
this._preview.show(this._previewPanel.contentElement);
}
@@ -291,12 +340,25 @@
}
/**
- * @return {!UI.SearchableView}
+ * @return {!UI.VBox}
*/
createPreview() {
- const metadata = {};
- for (const entry of this._eventMetadata)
- metadata[entry.key] = entry.value;
- return SourceFrame.JSONView.createViewSync(metadata);
+ const preview = new UI.VBox();
+ preview.element.classList.add('background-service-metadata');
+
+ for (const entry of this._eventMetadata) {
+ const div = createElementWithClass('div', 'background-service-metadata-entry');
+ div.createChild('div', 'background-service-metadata-name').textContent = entry.key + ': ';
+ div.createChild('div', 'background-service-metadata-value source-code').textContent = entry.value;
+ preview.element.appendChild(div);
+ }
+
+ if (!preview.element.children.length) {
+ const div = createElementWithClass('div', 'background-service-metadata-entry');
+ div.createChild('div', 'background-service-metadata-name').textContent = ls`No metadata for this event`;
+ preview.element.appendChild(div);
+ }
+
+ return preview;
}
};