Diff
Modified: trunk/Source/WebInspectorUI/ChangeLog (267037 => 267038)
--- trunk/Source/WebInspectorUI/ChangeLog 2020-09-14 20:48:38 UTC (rev 267037)
+++ trunk/Source/WebInspectorUI/ChangeLog 2020-09-14 20:51:40 UTC (rev 267038)
@@ -1,3 +1,51 @@
+2020-09-14 Patrick Angle <[email protected]>
+
+ Web Inspector: Stop Recording in Timelines tab doesn't work reliably
+ https://bugs.webkit.org/show_bug.cgi?id=216416
+
+ Reviewed by Devin Rousso.
+
+ Improved UX surrounding stopping recordings. In the Frames view, the interface now shows a "Stopping Recording
+ Timeline Data" message and disables the Stop Recording button as soon as the user has pressed the button to stop
+ recording. For all timeline views, the Record/Continue/Stop buttons in the top-right are replaced with an
+ indeterminate progress spinner while recording is being stopped to better indicate that all work has not
+ completed yet. Lastly, the recording head now stops at the moment recording was stopped. After we have finished
+ stopping the recording, the timeline is updated one more time to account for any records we receive after the
+ moment the user requested recording to stop, instead of continously updating during the stopping phase, which
+ made it appear that recording was instead continuing.
+
+ * Localizations/en.lproj/localizedStrings.js:
+ * UserInterface/Main.html: Added `IndeterminateProgressSpinnerNavigationItem.css` and
+ `IndeterminateProgressSpinnerNavigationItem.js`.
+ * UserInterface/Views/ButtonNavigationItem.css:
+ (.navigation-bar .item.button.image-only):
+ * UserInterface/Views/IndeterminateProgressSpinnerNavigationItem.css: Added.
+ (.navigation-bar .item.indeterminate-progress-spinner):
+ (.navigation-bar .item.indeterminate-progress-spinner-item .indeterminate-progress-spinner):
+ * UserInterface/Views/IndeterminateProgressSpinnerNavigationItem.js: Added.
+ (WI.IndeterminateProgressSpinnerNavigationItem):
+ * UserInterface/Views/TextNavigationItem.js: Drive-by fix for misplaced `assert`.
+ (WI.TextNavigationItem):
+ * UserInterface/Views/TimelineRecordingContentView.js: Don't advanced the recording head after the user requests
+ recording to stop.
+ (WI.TimelineRecordingContentView.prototype._updateTimes):
+ (WI.TimelineRecordingContentView.prototype._updateTimelineViewTimes):
+ * UserInterface/Views/TimelineRecordingProgressView.js: Listen to the TimelineManager to show different messages
+ for Recording and Stopping, as well as disabling the Stop Recording button.
+ (WI.TimelineRecordingProgressView):
+ (WI.TimelineRecordingProgressView.prototype.set visible):
+ (WI.TimelineRecordingProgressView.prototype._updateState):
+ (WI.TimelineRecordingProgressView.prototype._handleTimelineCapturingStateChanged):
+ * UserInterface/Views/TimelineTabContentView.js: Show a progress spinner while stopping recording.
+ (WI.TimelineTabContentView):
+ (WI.TimelineTabContentView.prototype._showRecordButton):
+ (WI.TimelineTabContentView.prototype._showRecordStoppingSpinner):
+ (WI.TimelineTabContentView.prototype._showContinueButton):
+ (WI.TimelineTabContentView.prototype._updateNavigationBarButtons):
+ (WI.TimelineTabContentView.prototype._handleTimelineCapturingStateChanged):
+ * UserInterface/Views/Variables.css: New variable for navigation items with only an icon.
+ (:root):
+
2020-09-14 Devin Rousso <[email protected]>
Web Inspector: docking buttons don't work when already docked if window is too small
Modified: trunk/Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js (267037 => 267038)
--- trunk/Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js 2020-09-14 20:48:38 UTC (rev 267037)
+++ trunk/Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js 2020-09-14 20:51:40 UTC (rev 267038)
@@ -1010,7 +1010,8 @@
localizedStrings["Recording"] = "Recording";
localizedStrings["Recording %d"] = "Recording %d";
localizedStrings["Recording Error: %s"] = "Recording Error: %s";
-localizedStrings["Recording Timeline Data"] = "Recording Timeline Data";
+/* Message for progress of a timeline recording. */
+localizedStrings["Recording Timeline Data @ Timeline Recording Progress"] = "Recording Timeline Data";
/* A type of canvas recording in the Graphics Tab */
localizedStrings["Recording Type Canvas Bitmap Renderer"] = "Bitmap Renderer";
localizedStrings["Recording Warning: %s"] = "Recording Warning: %s";
@@ -1253,6 +1254,9 @@
localizedStrings["Stop recording (%s)"] = "Stop recording (%s)";
localizedStrings["Stop recording canvas actions"] = "Stop recording canvas actions";
localizedStrings["Stop recording once page loads"] = "Stop recording once page loads";
+/* Message for progress of stopping a timeline recording. */
+localizedStrings["Stopping Timeline Recording @ Timeline Recording Progress"] = "Stopping Timeline Recording";
+localizedStrings["Stopping recording"] = "Stopping recording";
localizedStrings["Stopping the \u201C%s\u201D audit"] = "Stopping the \u201C%s\u201D audit";
localizedStrings["Storage"] = "Storage";
/* Name of Storage Tab */
Modified: trunk/Source/WebInspectorUI/UserInterface/Main.html (267037 => 267038)
--- trunk/Source/WebInspectorUI/UserInterface/Main.html 2020-09-14 20:48:38 UTC (rev 267037)
+++ trunk/Source/WebInspectorUI/UserInterface/Main.html 2020-09-14 20:51:40 UTC (rev 267038)
@@ -123,6 +123,7 @@
<link rel="stylesheet" href=""
<link rel="stylesheet" href=""
<link rel="stylesheet" href=""
+ <link rel="stylesheet" href=""
<link rel="stylesheet" href=""
<link rel="stylesheet" href=""
<link rel="stylesheet" href=""
@@ -711,6 +712,7 @@
<script src=""
<script src=""
<script src=""
+ <script src=""
<script src=""
<script src=""
<script src=""
Modified: trunk/Source/WebInspectorUI/UserInterface/Views/ButtonNavigationItem.css (267037 => 267038)
--- trunk/Source/WebInspectorUI/UserInterface/Views/ButtonNavigationItem.css 2020-09-14 20:48:38 UTC (rev 267037)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/ButtonNavigationItem.css 2020-09-14 20:51:40 UTC (rev 267038)
@@ -38,7 +38,7 @@
}
.navigation-bar .item.button.image-only {
- width: 26px;
+ width: var(--image-button-navigation-item-width);
}
.navigation-bar .item.button.image-and-text {
Copied: trunk/Source/WebInspectorUI/UserInterface/Views/IndeterminateProgressSpinnerNavigationItem.css (from rev 267037, trunk/Source/WebInspectorUI/UserInterface/Views/TextNavigationItem.js) (0 => 267038)
--- trunk/Source/WebInspectorUI/UserInterface/Views/IndeterminateProgressSpinnerNavigationItem.css (rev 0)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/IndeterminateProgressSpinnerNavigationItem.css 2020-09-14 20:51:40 UTC (rev 267038)
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2020 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+.navigation-bar .item.indeterminate-progress-spinner-item {
+ width: var(--image-button-navigation-item-width);
+ padding: 1px 4px;
+}
+
+.navigation-bar .item.indeterminate-progress-spinner-item .indeterminate-progress-spinner {
+ margin: auto;
+}
Copied: trunk/Source/WebInspectorUI/UserInterface/Views/IndeterminateProgressSpinnerNavigationItem.js (from rev 267037, trunk/Source/WebInspectorUI/UserInterface/Views/TextNavigationItem.js) (0 => 267038)
--- trunk/Source/WebInspectorUI/UserInterface/Views/IndeterminateProgressSpinnerNavigationItem.js (rev 0)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/IndeterminateProgressSpinnerNavigationItem.js 2020-09-14 20:51:40 UTC (rev 267038)
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2020 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WI.IndeterminateProgressSpinnerNavigationItem = class IndeterminateProgressSpinnerNavigationItem extends WI.NavigationItem
+{
+ constructor(identifier, tooltip)
+ {
+ console.assert(identifier);
+
+ super(identifier);
+
+ this.element.classList.add("indeterminate-progress-spinner-item");
+
+ this._spinner = new WI.IndeterminateProgressSpinner;
+ this.element.appendChild(this._spinner.element);
+
+ this.tooltip = tooltip ?? "";
+ }
+};
Modified: trunk/Source/WebInspectorUI/UserInterface/Views/TextNavigationItem.js (267037 => 267038)
--- trunk/Source/WebInspectorUI/UserInterface/Views/TextNavigationItem.js 2020-09-14 20:48:38 UTC (rev 267037)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/TextNavigationItem.js 2020-09-14 20:51:40 UTC (rev 267038)
@@ -27,10 +27,10 @@
{
constructor(identifier, label)
{
+ console.assert(identifier);
+
super(identifier);
- console.assert(identifier);
-
this._element.classList.add("text");
this._element.textContent = label || "";
}
Modified: trunk/Source/WebInspectorUI/UserInterface/Views/TimelineRecordingContentView.js (267037 => 267038)
--- trunk/Source/WebInspectorUI/UserInterface/Views/TimelineRecordingContentView.js 2020-09-14 20:48:38 UTC (rev 267037)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/TimelineRecordingContentView.js 2020-09-14 20:51:40 UTC (rev 267038)
@@ -463,10 +463,16 @@
this._startTimeNeedsReset = false;
}
- this._timelineOverview.endTime = Math.max(endTime, currentTime);
+ if (WI.timelineManager.capturingState !== WI.TimelineManager.CapturingState.Stopping) {
+ // Only update end time while not stopping, otherwise the interface contues scrolling.
+ this._timelineOverview.endTime = Math.max(endTime, currentTime);
- this._currentTime = currentTime;
- this._timelineOverview.currentTime = currentTime;
+ if (WI.timelineManager.capturingState !== WI.TimelineManager.CapturingState.Inactive) {
+ // Only update current time while active/starting or else the interface continues scrolling.
+ this._currentTime = currentTime;
+ this._timelineOverview.currentTime = currentTime;
+ }
+ }
if (this.currentTimelineView)
this._updateTimelineViewTimes(this.currentTimelineView);
@@ -849,8 +855,16 @@
}
timelineView.startTime = this._timelineOverview.selectionStartTime;
- timelineView.currentTime = this._currentTime;
- timelineView.endTime = endTime;
+
+ if (WI.timelineManager.capturingState !== WI.TimelineManager.CapturingState.Stopping) {
+ // Only update end time while not stopping, otherwise the interface contues scrolling.
+ timelineView.endTime = endTime;
+
+ if (WI.timelineManager.capturingState !== WI.TimelineManager.CapturingState.Inactive) {
+ // Only update current time while active/starting or else the interface continues scrolling.
+ timelineView.currentTime = this._currentTime;
+ }
+ }
}
_editingInstrumentsDidChange(event)
Modified: trunk/Source/WebInspectorUI/UserInterface/Views/TimelineRecordingProgressView.js (267037 => 267038)
--- trunk/Source/WebInspectorUI/UserInterface/Views/TimelineRecordingProgressView.js 2020-09-14 20:48:38 UTC (rev 267037)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/TimelineRecordingProgressView.js 2020-09-14 20:51:40 UTC (rev 267038)
@@ -31,18 +31,18 @@
this.element.classList.add("recording-progress");
- let statusElement = document.createElement("div");
- statusElement.classList.add("status");
- statusElement.textContent = WI.UIString("Recording Timeline Data");
- this.element.append(statusElement);
+ let statusGroup = this.element.appendChild(document.createElement("div"));
+ statusGroup.className = "status";
+ this._statusElement = statusGroup.appendChild(document.createElement("span"));
+
let spinner = new WI.IndeterminateProgressSpinner;
- statusElement.append(spinner.element);
+ statusGroup.appendChild(spinner.element);
this._stopRecordingButtonElement = document.createElement("button");
this._stopRecordingButtonElement.textContent = WI.UIString("Stop Recording");
this._stopRecordingButtonElement.addEventListener("click", () => WI.timelineManager.stopCapturing());
- this.element.append(this._stopRecordingButtonElement);
+ this.element.appendChild(this._stopRecordingButtonElement);
}
// Public
@@ -60,5 +60,37 @@
// FIXME: remove once <https://webkit.org/b/150741> is fixed.
this._visible = x;
this.element.classList.toggle("hidden", !this._visible);
+
+ if (this._visible) {
+ WI.timelineManager.addEventListener(WI.TimelineManager.Event.CapturingStateChanged, this._handleTimelineCapturingStateChanged, this);
+ this._updateState();
+ } else
+ WI.timelineManager.removeEventListener(WI.TimelineManager.Event.CapturingStateChanged, this._handleTimelineCapturingStateChanged, this);
}
+
+ // Private
+
+ _updateState() {
+ switch (WI.timelineManager.capturingState) {
+ case WI.TimelineManager.CapturingState.Starting:
+ case WI.TimelineManager.CapturingState.Active:
+ this._statusElement.textContent = WI.UIString("Recording Timeline Data", "Recording Timeline Data @ Timeline Recording Progress", "Message for progress of a timeline recording.");
+ this._stopRecordingButtonElement.disabled = false;
+ break;
+ case WI.TimelineManager.CapturingState.Stopping:
+ this._statusElement.textContent = WI.UIString("Stopping Timeline Recording", "Stopping Timeline Recording @ Timeline Recording Progress", "Message for progress of stopping a timeline recording.");
+ this._stopRecordingButtonElement.disabled = true;
+ break;
+ case WI.TimelineManager.CapturingState.Inactive:
+ // When inactive this view should be hidden by its parent, so keep the state the same to avoid possibly
+ // flickering to a different state just before the parent hides us.
+ break;
+ }
+ }
+
+ _handleTimelineCapturingStateChanged(event)
+ {
+ this._updateState();
+ }
+
};
Modified: trunk/Source/WebInspectorUI/UserInterface/Views/TimelineTabContentView.js (267037 => 267038)
--- trunk/Source/WebInspectorUI/UserInterface/Views/TimelineTabContentView.js 2020-09-14 20:48:38 UTC (rev 267037)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/TimelineTabContentView.js 2020-09-14 20:51:40 UTC (rev 267038)
@@ -49,6 +49,10 @@
this._recordButton.visibilityPriority = WI.NavigationItem.VisibilityPriority.High;
this._recordButton.addEventListener(WI.ButtonNavigationItem.Event.Clicked, this._recordButtonClicked, this);
+ this._recordStoppingSpinner = new WI.IndeterminateProgressSpinnerNavigationItem("record-stopping", WI.UIString("Stopping recording"));
+ this._recordStoppingSpinner.visibilityPriority = WI.NavigationItem.VisibilityPriority.High;
+ this._recordStoppingSpinner.hidden = true;
+
this._continueButton = new WI.ButtonNavigationItem("record-continue", WI.UIString("Continue without automatically stopping"), "Images/Resume.svg", 13, 13);
this._continueButton.visibilityPriority = WI.NavigationItem.VisibilityPriority.High;
this._continueButton.addEventListener(WI.ButtonNavigationItem.Event.Clicked, this._continueButtonClicked, this);
@@ -55,7 +59,8 @@
this._continueButton.hidden = true;
this.contentBrowser.navigationBar.insertNavigationItem(this._recordButton, 0);
- this.contentBrowser.navigationBar.insertNavigationItem(this._continueButton, 1);
+ this.contentBrowser.navigationBar.insertNavigationItem(this._recordStoppingSpinner, 1);
+ this.contentBrowser.navigationBar.insertNavigationItem(this._continueButton, 2);
if (WI.sharedApp.isWebDebuggable()) {
let timelinesNavigationItem = new WI.RadioButtonNavigationItem(WI.TimelineOverview.ViewMode.Timelines, WI.UIString("Events"));
@@ -64,7 +69,7 @@
let viewModeGroup = new WI.GroupNavigationItem([timelinesNavigationItem, renderingFramesNavigationItem]);
viewModeGroup.visibilityPriority = WI.NavigationItem.VisibilityPriority.High;
- this.contentBrowser.navigationBar.insertNavigationItem(viewModeGroup, 2);
+ this.contentBrowser.navigationBar.insertNavigationItem(viewModeGroup, 3);
this.contentBrowser.navigationBar.addEventListener(WI.NavigationBar.Event.NavigationItemSelected, this._viewModeSelected, this);
}
@@ -452,18 +457,29 @@
_showRecordButton()
{
this._recordButton.hidden = false;
+ this._recordStoppingSpinner.hidden = true;
this._continueButton.hidden = true;
}
+ _showRecordStoppingSpinner()
+ {
+ this._recordButton.hidden = true;
+ this._recordStoppingSpinner.hidden = false;
+ this._continueButton.hidden = true;
+ }
+
_showContinueButton()
{
this._recordButton.hidden = true;
+ this._recordStoppingSpinner.hidden = true;
this._continueButton.hidden = false;
}
_updateNavigationBarButtons()
{
- if (!WI.modifierKeys.altKey || !WI.timelineManager.willAutoStop())
+ if (WI.timelineManager.capturingState === WI.TimelineManager.CapturingState.Stopping)
+ this._showRecordStoppingSpinner();
+ else if (!WI.modifierKeys.altKey || !WI.timelineManager.willAutoStop())
this._showRecordButton();
else
this._showContinueButton();
@@ -472,9 +488,10 @@
_handleTimelineCapturingStateChanged(event)
{
let enabled = WI.timelineManager.capturingState === WI.TimelineManager.CapturingState.Active || WI.timelineManager.capturingState === WI.TimelineManager.CapturingState.Inactive;
+ let stopping = WI.timelineManager.capturingState === WI.TimelineManager.CapturingState.Stopping;
- this._toggleRecordingShortcut.disabled = !enabled;
- this._toggleNewRecordingShortcut.disabled = !enabled;
+ this._toggleRecordingShortcut.disabled = !enabled || stopping;
+ this._toggleNewRecordingShortcut.disabled = !enabled || stopping;
this._recordButton.toggled = WI.timelineManager.isCapturing();
this._recordButton.enabled = enabled;
Modified: trunk/Source/WebInspectorUI/UserInterface/Views/Variables.css (267037 => 267038)
--- trunk/Source/WebInspectorUI/UserInterface/Views/Variables.css 2020-09-14 20:48:38 UTC (rev 267037)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/Variables.css 2020-09-14 20:51:40 UTC (rev 267038)
@@ -213,6 +213,8 @@
--sorted-header-font-weight: 500;
--reference-page-link-size: 20px;
+
+ --image-button-navigation-item-width: 26px;
}
body.window-inactive {