- Revision
- 223322
- Author
- [email protected]
- Date
- 2017-10-14 12:05:16 -0700 (Sat, 14 Oct 2017)
Log Message
Web Inspector: Canvas tab: recordings should have a unique name
https://bugs.webkit.org/show_bug.cgi?id=178188
<rdar://problem/34943364>
Reviewed by Devin Rousso.
* Localizations/en.lproj/localizedStrings.js:
New format string "Recording %d".
* UserInterface/Base/FileUtilities.js:
(WI.loadDataFromFile):
Pass chosen filename to callback.
* UserInterface/Controllers/CanvasManager.js:
(WI.CanvasManager.prototype.recordingFinished):
Create a unique name for the recording.
* UserInterface/Models/Recording.js:
(WI.Recording):
(WI.Recording.fromPayload):
(WI.Recording.prototype.get displayName):
(WI.Recording.prototype.createDisplayName):
* UserInterface/Views/RecordingContentView.js:
(WI.RecordingContentView.prototype.get saveData):
Use encodeURI so that special characters can be used in filenames, and
to be consistent with other `saveData` implementations.
* UserInterface/Views/RecordingNavigationSidebarPanel.js:
(WI.RecordingNavigationSidebarPanel.prototype.set recording):
(WI.RecordingNavigationSidebarPanel.prototype._importNavigationItemClicked):
Drive-by fix: wait until actions are resolved before updating UI.
* UserInterface/Views/RecordingTabContentView.js:
(WI.RecordingTabContentView.prototype._navigationSidebarImport):
Try to use the imported filename as the recording name. If the name
collides with that of another imported recording, append a unique suffix.
Modified Paths
Diff
Modified: trunk/Source/WebInspectorUI/ChangeLog (223321 => 223322)
--- trunk/Source/WebInspectorUI/ChangeLog 2017-10-14 18:56:32 UTC (rev 223321)
+++ trunk/Source/WebInspectorUI/ChangeLog 2017-10-14 19:05:16 UTC (rev 223322)
@@ -1,3 +1,43 @@
+2017-10-14 Matt Baker <[email protected]>
+
+ Web Inspector: Canvas tab: recordings should have a unique name
+ https://bugs.webkit.org/show_bug.cgi?id=178188
+ <rdar://problem/34943364>
+
+ Reviewed by Devin Rousso.
+
+ * Localizations/en.lproj/localizedStrings.js:
+ New format string "Recording %d".
+
+ * UserInterface/Base/FileUtilities.js:
+ (WI.loadDataFromFile):
+ Pass chosen filename to callback.
+
+ * UserInterface/Controllers/CanvasManager.js:
+ (WI.CanvasManager.prototype.recordingFinished):
+ Create a unique name for the recording.
+
+ * UserInterface/Models/Recording.js:
+ (WI.Recording):
+ (WI.Recording.fromPayload):
+ (WI.Recording.prototype.get displayName):
+ (WI.Recording.prototype.createDisplayName):
+
+ * UserInterface/Views/RecordingContentView.js:
+ (WI.RecordingContentView.prototype.get saveData):
+ Use encodeURI so that special characters can be used in filenames, and
+ to be consistent with other `saveData` implementations.
+
+ * UserInterface/Views/RecordingNavigationSidebarPanel.js:
+ (WI.RecordingNavigationSidebarPanel.prototype.set recording):
+ (WI.RecordingNavigationSidebarPanel.prototype._importNavigationItemClicked):
+ Drive-by fix: wait until actions are resolved before updating UI.
+
+ * UserInterface/Views/RecordingTabContentView.js:
+ (WI.RecordingTabContentView.prototype._navigationSidebarImport):
+ Try to use the imported filename as the recording name. If the name
+ collides with that of another imported recording, append a unique suffix.
+
2017-10-14 Devin Rousso <[email protected]>
Web Inspector: provide a way to enable/disable event listeners
Modified: trunk/Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js (223321 => 223322)
--- trunk/Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js 2017-10-14 18:56:32 UTC (rev 223321)
+++ trunk/Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js 2017-10-14 19:05:16 UTC (rev 223322)
@@ -708,6 +708,7 @@
localizedStrings["Reasons for compositing:"] = "Reasons for compositing:";
localizedStrings["Recently Closed Tabs"] = "Recently Closed Tabs";
localizedStrings["Recording"] = "Recording";
+localizedStrings["Recording %d"] = "Recording %d";
localizedStrings["Recording Timeline Data"] = "Recording Timeline Data";
localizedStrings["Recording error: %s"] = "Recording error: %s";
localizedStrings["Reference Issue"] = "Reference Issue";
Modified: trunk/Source/WebInspectorUI/UserInterface/Base/FileUtilities.js (223321 => 223322)
--- trunk/Source/WebInspectorUI/UserInterface/Base/FileUtilities.js 2017-10-14 18:56:32 UTC (rev 223321)
+++ trunk/Source/WebInspectorUI/UserInterface/Base/FileUtilities.js 2017-10-14 19:05:16 UTC (rev 223322)
@@ -76,11 +76,12 @@
return;
}
+ let file = inputElement.files[0];
let reader = new FileReader;
reader.addEventListener("loadend", (event) => {
- callback(reader.result);
+ callback(reader.result, file.name);
});
- reader.readAsText(inputElement.files[0]);
+ reader.readAsText(file);
});
inputElement.click();
};
Modified: trunk/Source/WebInspectorUI/UserInterface/Controllers/CanvasManager.js (223321 => 223322)
--- trunk/Source/WebInspectorUI/UserInterface/Controllers/CanvasManager.js 2017-10-14 18:56:32 UTC (rev 223321)
+++ trunk/Source/WebInspectorUI/UserInterface/Controllers/CanvasManager.js 2017-10-14 19:05:16 UTC (rev 223322)
@@ -158,9 +158,11 @@
if (!canvas)
return;
- let recording = recordingPayload ? WI.Recording.fromPayload(recordingPayload) : null;
- if (recording)
+ let recording = recordingPayload ? WI.Recording.fromPayload(recordingPayload) : null
+ if (recording) {
recording.source = canvas;
+ recording.createDisplayName();
+ }
this.dispatchEventToListeners(WI.CanvasManager.Event.RecordingStopped, {canvas, recording});
}
Modified: trunk/Source/WebInspectorUI/UserInterface/Models/Recording.js (223321 => 223322)
--- trunk/Source/WebInspectorUI/UserInterface/Models/Recording.js 2017-10-14 18:56:32 UTC (rev 223321)
+++ trunk/Source/WebInspectorUI/UserInterface/Models/Recording.js 2017-10-14 19:05:16 UTC (rev 223322)
@@ -32,6 +32,7 @@
this._initialState = initialState;
this._frames = frames;
this._data = data;
+ this._displayName = WI.UIString("Recording");
this._swizzle = [];
this._source = null;
@@ -63,12 +64,10 @@
});
}
- // Static
-
static fromPayload(payload)
{
if (typeof payload !== "object" || payload === null)
- payload = {};
+ return null;
if (isNaN(payload.version) || payload.version <= 0)
return null;
@@ -165,6 +164,7 @@
// Public
+ get displayName() { return this._displayName; }
get type() { return this._type; }
get initialState() { return this._initialState; }
get frames() { return this._frames; }
@@ -175,6 +175,33 @@
get source() { return this._source; }
set source(source) { this._source = source; }
+ createDisplayName(suggestedName)
+ {
+ let recordingNameSet;
+ if (this._source) {
+ recordingNameSet = this._source[WI.Recording.CanvasRecordingNamesSymbol];
+ if (!recordingNameSet)
+ this._source[WI.Recording.CanvasRecordingNamesSymbol] = recordingNameSet = new Set;
+ } else
+ recordingNameSet = WI.Recording._importedRecordingNameSet;
+
+ let name;
+ if (suggestedName) {
+ name = suggestedName;
+ let duplicateNumber = 2;
+ while (recordingNameSet.has(name))
+ name = `${suggestedName} (${duplicateNumber++})`;
+ } else {
+ let recordingNumber = 1;
+ do {
+ name = WI.UIString("Recording %d").format(recordingNumber++);
+ } while (recordingNameSet.has(name));
+ }
+
+ recordingNameSet.add(name);
+ this._displayName = name;
+ }
+
async swizzle(index, type)
{
if (typeof this._swizzle[index] !== "object")
@@ -282,6 +309,10 @@
}
};
+WI.Recording._importedRecordingNameSet = new Set;
+
+WI.Recording.CanvasRecordingNamesSymbol = Symbol("canvas-recording-names");
+
WI.Recording.Type = {
Canvas2D: "canvas-2d",
CanvasWebGL: "canvas-webgl",
Modified: trunk/Source/WebInspectorUI/UserInterface/Views/RecordingContentView.js (223321 => 223322)
--- trunk/Source/WebInspectorUI/UserInterface/Views/RecordingContentView.js 2017-10-14 18:56:32 UTC (rev 223321)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/RecordingContentView.js 2017-10-14 19:05:16 UTC (rev 223322)
@@ -148,8 +148,12 @@
get saveData()
{
+ let filename = this.representedObject.displayName;
+ if (!filename.endsWith(".json"))
+ filename += ".json";
+
return {
- url: "web-inspector:///Recording.json",
+ url: "web-inspector:///" + encodeURI(filename),
content: JSON.stringify(this.representedObject.toJSON()),
forceSaveAs: true,
};
Modified: trunk/Source/WebInspectorUI/UserInterface/Views/RecordingNavigationSidebarPanel.js (223321 => 223322)
--- trunk/Source/WebInspectorUI/UserInterface/Views/RecordingNavigationSidebarPanel.js 2017-10-14 18:56:32 UTC (rev 223321)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/RecordingNavigationSidebarPanel.js 2017-10-14 19:05:16 UTC (rev 223322)
@@ -56,36 +56,39 @@
this._recording = recording;
- if (this._recording) {
- this._recording.actions.then((actions) => {
- this.contentTreeOutline.element.dataset.indent = Number.countDigits(actions.length);
+ this.updateEmptyContentPlaceholder(WI.UIString("No Recording Data"));
- if (actions[0] instanceof WI.RecordingInitialStateAction)
- this.contentTreeOutline.appendChild(new WI.RecordingActionTreeElement(actions[0], 0, this._recording.type));
+ if (!this._recording) {
+ if (this._exportButton)
+ this._exportButton.disabled = true;
+ return;
+ }
- let cumulativeActionIndex = 1;
- this._recording.frames.forEach((frame, frameIndex) => {
- let folder = new WI.FolderTreeElement(WI.UIString("Frame %d").format((frameIndex + 1).toLocaleString()));
- this.contentTreeOutline.appendChild(folder);
+ this._recording.actions.then((actions) => {
+ this.contentTreeOutline.element.dataset.indent = Number.countDigits(actions.length);
- for (let i = 0; i < frame.actions.length; ++i)
- folder.appendChild(new WI.RecordingActionTreeElement(frame.actions[i], cumulativeActionIndex + i, this._recording.type));
+ if (actions[0] instanceof WI.RecordingInitialStateAction)
+ this.contentTreeOutline.appendChild(new WI.RecordingActionTreeElement(actions[0], 0, this._recording.type));
- if (frame.incomplete)
- folder.subtitle = WI.UIString("Incomplete");
+ let cumulativeActionIndex = 1;
+ this._recording.frames.forEach((frame, frameIndex) => {
+ let folder = new WI.FolderTreeElement(WI.UIString("Frame %d").format((frameIndex + 1).toLocaleString()));
+ this.contentTreeOutline.appendChild(folder);
- if (this._recording.frames.length === 1)
- folder.expand();
+ for (let i = 0; i < frame.actions.length; ++i)
+ folder.appendChild(new WI.RecordingActionTreeElement(frame.actions[i], cumulativeActionIndex + i, this._recording.type));
- cumulativeActionIndex += frame.actions.length;
- });
+ if (frame.incomplete)
+ folder.subtitle = WI.UIString("Incomplete");
+
+ if (this._recording.frames.length === 1)
+ folder.expand();
+
+ cumulativeActionIndex += frame.actions.length;
});
- }
- this.updateEmptyContentPlaceholder(WI.UIString("No Recording Data"));
-
- if (this._exportButton)
- this._exportButton.disabled = !this.contentTreeOutline.children.length;
+ this._exportButton.disabled = !actions.length;
+ });
}
updateActionIndex(index, options = {})
@@ -174,7 +177,7 @@
_importNavigationItemClicked(event)
{
- WI.loadDataFromFile((data) => {
+ WI.loadDataFromFile((data, filename) => {
if (!data)
return;
@@ -186,7 +189,7 @@
return;
}
- this.dispatchEventToListeners(WI.RecordingNavigationSidebarPanel.Event.Import, {payload});
+ this.dispatchEventToListeners(WI.RecordingNavigationSidebarPanel.Event.Import, {payload, filename});
});
}
Modified: trunk/Source/WebInspectorUI/UserInterface/Views/RecordingTabContentView.js (223321 => 223322)
--- trunk/Source/WebInspectorUI/UserInterface/Views/RecordingTabContentView.js 2017-10-14 18:56:32 UTC (rev 223321)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/RecordingTabContentView.js 2017-10-14 19:05:16 UTC (rev 223322)
@@ -162,12 +162,19 @@
_navigationSidebarImport(event)
{
- let recording = WI.Recording.fromPayload(event.data.payload);
+ let {filename, payload} = event.data;
+ let recording = WI.Recording.fromPayload(payload);
if (!recording) {
WI.Recording.synthesizeError(WI.UIString("unsupported version."));
return;
}
+ let extensionStart = filename.lastIndexOf(".");
+ if (extensionStart !== -1)
+ filename = filename.substring(0, extensionStart);
+
+ recording.createDisplayName(filename);
+
this.showRepresentedObject(recording);
}