mirror of
https://github.com/roytam1/palemoon27.git
synced 2026-06-02 15:10:56 +00:00
242 lines
8.4 KiB
JavaScript
242 lines
8.4 KiB
JavaScript
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
|
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
"use strict";
|
|
|
|
/**
|
|
* Functions handling the recordings UI.
|
|
*/
|
|
let RecordingsView = Heritage.extend(WidgetMethods, {
|
|
/**
|
|
* Initialization function, called when the tool is started.
|
|
*/
|
|
initialize: function() {
|
|
this.widget = new SideMenuWidget($("#recordings-list"));
|
|
|
|
this._onSelect = this._onSelect.bind(this);
|
|
this._onRecordingStarted = this._onRecordingStarted.bind(this);
|
|
this._onRecordingStopped = this._onRecordingStopped.bind(this);
|
|
this._onRecordingImported = this._onRecordingImported.bind(this);
|
|
this._onSaveButtonClick = this._onSaveButtonClick.bind(this);
|
|
this._onRecordingsCleared = this._onRecordingsCleared.bind(this);
|
|
|
|
this.emptyText = L10N.getStr("noRecordingsText");
|
|
|
|
PerformanceController.on(EVENTS.RECORDING_STARTED, this._onRecordingStarted);
|
|
PerformanceController.on(EVENTS.RECORDING_STOPPED, this._onRecordingStopped);
|
|
PerformanceController.on(EVENTS.RECORDING_IMPORTED, this._onRecordingImported);
|
|
PerformanceController.on(EVENTS.RECORDINGS_CLEARED, this._onRecordingsCleared);
|
|
this.widget.addEventListener("select", this._onSelect, false);
|
|
},
|
|
|
|
/**
|
|
* Destruction function, called when the tool is closed.
|
|
*/
|
|
destroy: function() {
|
|
PerformanceController.off(EVENTS.RECORDING_STARTED, this._onRecordingStarted);
|
|
PerformanceController.off(EVENTS.RECORDING_STOPPED, this._onRecordingStopped);
|
|
PerformanceController.off(EVENTS.RECORDING_IMPORTED, this._onRecordingImported);
|
|
PerformanceController.off(EVENTS.RECORDINGS_CLEARED, this._onRecordingsCleared);
|
|
this.widget.removeEventListener("select", this._onSelect, false);
|
|
},
|
|
|
|
/**
|
|
* Adds an empty recording to this container.
|
|
*
|
|
* @param RecordingModel recording
|
|
* A model for the new recording item created.
|
|
*/
|
|
addEmptyRecording: function (recording) {
|
|
let titleNode = document.createElement("label");
|
|
titleNode.className = "plain recording-item-title";
|
|
titleNode.setAttribute("value", recording.getLabel() ||
|
|
L10N.getFormatStr("recordingsList.itemLabel", this.itemCount + 1));
|
|
|
|
let durationNode = document.createElement("label");
|
|
durationNode.className = "plain recording-item-duration";
|
|
durationNode.setAttribute("value",
|
|
L10N.getStr("recordingsList.recordingLabel"));
|
|
|
|
let saveNode = document.createElement("label");
|
|
saveNode.className = "plain recording-item-save";
|
|
saveNode.addEventListener("click", this._onSaveButtonClick);
|
|
|
|
let hspacer = document.createElement("spacer");
|
|
hspacer.setAttribute("flex", "1");
|
|
|
|
let footerNode = document.createElement("hbox");
|
|
footerNode.className = "recording-item-footer";
|
|
footerNode.appendChild(durationNode);
|
|
footerNode.appendChild(hspacer);
|
|
footerNode.appendChild(saveNode);
|
|
|
|
let vspacer = document.createElement("spacer");
|
|
vspacer.setAttribute("flex", "1");
|
|
|
|
let contentsNode = document.createElement("vbox");
|
|
contentsNode.className = "recording-item";
|
|
contentsNode.setAttribute("flex", "1");
|
|
contentsNode.appendChild(titleNode);
|
|
contentsNode.appendChild(vspacer);
|
|
contentsNode.appendChild(footerNode);
|
|
|
|
// Append a recording item to this container.
|
|
return this.push([contentsNode], {
|
|
// Store the recording model that contains all the data to be
|
|
// rendered in the item.
|
|
attachment: recording
|
|
});
|
|
},
|
|
|
|
/**
|
|
* Signals that a recording session has started.
|
|
*
|
|
* @param RecordingModel recording
|
|
* Model of the recording that was started.
|
|
*/
|
|
_onRecordingStarted: function (_, recording) {
|
|
// Insert a "dummy" recording item, to hint that recording has now started.
|
|
let recordingItem;
|
|
|
|
// If a label is specified (e.g due to a call to `console.profile`),
|
|
// then try reusing a pre-existing recording item, if there is one.
|
|
// This is symmetrical to how `this.handleRecordingEnded` works.
|
|
let profileLabel = recording.getLabel();
|
|
if (profileLabel) {
|
|
recordingItem = this.getItemForAttachment(e => e.getLabel() == profileLabel);
|
|
}
|
|
// Otherwise, create a new empty recording item.
|
|
if (!recordingItem) {
|
|
recordingItem = this.addEmptyRecording(recording);
|
|
}
|
|
|
|
// Mark the corresponding item as being a "record in progress".
|
|
recordingItem.isRecording = true;
|
|
|
|
// If this is a manual recording, immediately select it.
|
|
if (!recording.getLabel()) {
|
|
this.selectedItem = recordingItem;
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Signals that a recording session has ended.
|
|
*
|
|
* @param RecordingModel recording
|
|
* The model of the recording that just stopped.
|
|
*/
|
|
_onRecordingStopped: function (_, recording) {
|
|
let recordingItem;
|
|
|
|
// If a label is specified (e.g due to a call to `console.profileEnd`),
|
|
// then try reusing a pre-existing recording item, if there is one.
|
|
// This is symmetrical to how `this.handleRecordingStarted` works.
|
|
let profileLabel = recording.getLabel();
|
|
if (profileLabel) {
|
|
recordingItem = this.getItemForAttachment(e => e.getLabel() == profileLabel);
|
|
}
|
|
// Otherwise, just use the first available recording item.
|
|
if (!recordingItem) {
|
|
recordingItem = this.getItemForPredicate(e => e.isRecording);
|
|
}
|
|
|
|
// Mark the corresponding item as being a "finished recording".
|
|
recordingItem.isRecording = false;
|
|
|
|
// Render the recording item with finalized information (timing, etc)
|
|
this.finalizeRecording(recordingItem);
|
|
this.forceSelect(recordingItem);
|
|
},
|
|
|
|
/**
|
|
* Signals that a recording has been imported.
|
|
*
|
|
* @param RecordingModel model
|
|
* The recording model containing data on the recording session.
|
|
*/
|
|
_onRecordingImported: function (_, model) {
|
|
let recordingItem = this.addEmptyRecording(model);
|
|
recordingItem.isRecording = false;
|
|
|
|
// Immediately select the imported recording
|
|
this.selectedItem = recordingItem;
|
|
|
|
// Render the recording item with finalized information (timing, etc)
|
|
this.finalizeRecording(recordingItem);
|
|
},
|
|
|
|
/**
|
|
* Clears out all recordings.
|
|
*/
|
|
_onRecordingsCleared: function () {
|
|
this.empty();
|
|
},
|
|
|
|
/**
|
|
* Adds recording data to a recording item in this container.
|
|
*
|
|
* @param Item recordingItem
|
|
* An item inserted via `RecordingsView.addEmptyRecording`.
|
|
*/
|
|
finalizeRecording: function (recordingItem) {
|
|
let model = recordingItem.attachment;
|
|
|
|
let saveNode = $(".recording-item-save", recordingItem.target);
|
|
saveNode.setAttribute("value",
|
|
L10N.getStr("recordingsList.saveLabel"));
|
|
|
|
let durationMillis = model.getDuration().toFixed(0);
|
|
let durationNode = $(".recording-item-duration", recordingItem.target);
|
|
durationNode.setAttribute("value",
|
|
L10N.getFormatStr("recordingsList.durationLabel", durationMillis));
|
|
},
|
|
|
|
/**
|
|
* The select listener for this container.
|
|
*/
|
|
_onSelect: Task.async(function*({ detail: recordingItem }) {
|
|
// TODO 1120699
|
|
// show appropriate empty/recording panels for several scenarios below
|
|
if (!recordingItem) {
|
|
return;
|
|
}
|
|
|
|
let model = recordingItem.attachment;
|
|
|
|
// If recording, don't abort completely, as we still want to fire an event
|
|
// for selection so we can continue repainting the overview graphs.
|
|
if (recordingItem.isRecording) {
|
|
this.emit(EVENTS.RECORDING_SELECTED, model);
|
|
return;
|
|
}
|
|
|
|
this.emit(EVENTS.RECORDING_SELECTED, model);
|
|
}),
|
|
|
|
/**
|
|
* The click listener for the "save" button of each item in this container.
|
|
*/
|
|
_onSaveButtonClick: function (e) {
|
|
let fp = Cc["@mozilla.org/filepicker;1"].createInstance(Ci.nsIFilePicker);
|
|
fp.init(window, L10N.getStr("recordingsList.saveDialogTitle"), Ci.nsIFilePicker.modeSave);
|
|
fp.appendFilter(L10N.getStr("recordingsList.saveDialogJSONFilter"), "*.json");
|
|
fp.appendFilter(L10N.getStr("recordingsList.saveDialogAllFilter"), "*.*");
|
|
fp.defaultString = "profile.json";
|
|
|
|
fp.open({ done: result => {
|
|
if (result == Ci.nsIFilePicker.returnCancel) {
|
|
return;
|
|
}
|
|
let recordingItem = this.getItemForElement(e.target);
|
|
this.emit(EVENTS.UI_EXPORT_RECORDING, recordingItem.attachment, fp.file);
|
|
}});
|
|
},
|
|
|
|
toString: () => "[object RecordingsView]"
|
|
});
|
|
|
|
/**
|
|
* Convenient way of emitting events from the RecordingsView.
|
|
*/
|
|
EventEmitter.decorate(RecordingsView);
|