зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1309192 - Implement search filter in Net Panel Toolbar r=jsnajdr
MozReview-Commit-ID: FjVo69jmE7e --HG-- extra : rebase_source : 384206ee66824fe75d84232c7960280295909649
This commit is contained in:
Родитель
f0150be625
Коммит
0bae861b5c
|
@ -4,8 +4,9 @@
|
|||
"use strict";
|
||||
|
||||
const {
|
||||
TOGGLE_FILTER,
|
||||
ENABLE_FILTER_ONLY,
|
||||
TOGGLE_FILTER_TYPE,
|
||||
ENABLE_FILTER_TYPE_ONLY,
|
||||
SET_FILTER_TEXT,
|
||||
} = require("../constants");
|
||||
|
||||
/**
|
||||
|
@ -15,9 +16,9 @@ const {
|
|||
*
|
||||
* @param {string} filter - A filter type is going to be updated
|
||||
*/
|
||||
function toggleFilter(filter) {
|
||||
function toggleFilterType(filter) {
|
||||
return {
|
||||
type: TOGGLE_FILTER,
|
||||
type: TOGGLE_FILTER_TYPE,
|
||||
filter,
|
||||
};
|
||||
}
|
||||
|
@ -30,14 +31,27 @@ function toggleFilter(filter) {
|
|||
*
|
||||
* @param {string} filter - A filter type is going to be updated
|
||||
*/
|
||||
function enableFilterOnly(filter) {
|
||||
function enableFilterTypeOnly(filter) {
|
||||
return {
|
||||
type: ENABLE_FILTER_ONLY,
|
||||
type: ENABLE_FILTER_TYPE_ONLY,
|
||||
filter,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Set filter text.
|
||||
*
|
||||
* @param {string} url - A filter text is going to be set
|
||||
*/
|
||||
function setFilterText(url) {
|
||||
return {
|
||||
type: SET_FILTER_TEXT,
|
||||
url,
|
||||
};
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
toggleFilter,
|
||||
enableFilterOnly,
|
||||
toggleFilterType,
|
||||
enableFilterTypeOnly,
|
||||
setFilterText,
|
||||
};
|
||||
|
|
|
@ -42,7 +42,7 @@ module.exports = connect(
|
|||
if (evt.type === "keydown" && (evt.key !== "" || evt.key !== "Enter")) {
|
||||
return;
|
||||
}
|
||||
dispatch(Actions.toggleFilter(evt.target.dataset.key));
|
||||
dispatch(Actions.toggleFilterType(evt.target.dataset.key));
|
||||
},
|
||||
})
|
||||
)(FilterButtons);
|
||||
|
|
|
@ -5,5 +5,6 @@
|
|||
|
||||
DevToolsModules(
|
||||
'filter-buttons.js',
|
||||
'search-box.js',
|
||||
'toggle-button.js',
|
||||
)
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
/* 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";
|
||||
|
||||
const { connect } = require("devtools/client/shared/vendor/react-redux");
|
||||
const SearchBox = require("devtools/client/shared/components/search-box");
|
||||
const { L10N } = require("../l10n");
|
||||
const Actions = require("../actions/index");
|
||||
const { FREETEXT_FILTER_SEARCH_DELAY } = require("../constants");
|
||||
|
||||
module.exports = connect(
|
||||
(state) => ({
|
||||
delay: FREETEXT_FILTER_SEARCH_DELAY,
|
||||
keyShortcut: L10N.getStr("netmonitor.toolbar.filterFreetext.key"),
|
||||
placeholder: L10N.getStr("netmonitor.toolbar.filterFreetext.label"),
|
||||
type: "filter",
|
||||
}),
|
||||
(dispatch) => ({
|
||||
onChange: (url) => {
|
||||
dispatch(Actions.setFilterText(url));
|
||||
},
|
||||
})
|
||||
)(SearchBox);
|
|
@ -3,12 +3,17 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
"use strict";
|
||||
|
||||
const general = {
|
||||
FREETEXT_FILTER_SEARCH_DELAY: 200,
|
||||
};
|
||||
|
||||
const actionTypes = {
|
||||
TOGGLE_FILTER: "TOGGLE_FILTER",
|
||||
ENABLE_FILTER_ONLY: "ENABLE_FILTER_ONLY",
|
||||
TOGGLE_FILTER_TYPE: "TOGGLE_FILTER_TYPE",
|
||||
ENABLE_FILTER_TYPE_ONLY: "ENABLE_FILTER_TYPE_ONLY",
|
||||
TOGGLE_SIDEBAR: "TOGGLE_SIDEBAR",
|
||||
SHOW_SIDEBAR: "SHOW_SIDEBAR",
|
||||
DISABLE_TOGGLE_BUTTON: "DISABLE_TOGGLE_BUTTON",
|
||||
SET_FILTER_TEXT: "SET_FILTER_TEXT",
|
||||
};
|
||||
|
||||
module.exports = actionTypes;
|
||||
module.exports = Object.assign({}, general, actionTypes);
|
||||
|
|
|
@ -299,7 +299,7 @@ var NetMonitorController = {
|
|||
request = NetMonitorView.RequestsMenu.getItemForPredicate(predicate);
|
||||
if (!request) {
|
||||
// Reset filters so that the request is visible.
|
||||
gStore.dispatch(Actions.toggleFilter("all"));
|
||||
gStore.dispatch(Actions.toggleFilterType("all"));
|
||||
request = NetMonitorView.RequestsMenu.getItemForPredicate(predicate);
|
||||
}
|
||||
|
||||
|
|
|
@ -31,11 +31,10 @@
|
|||
<toolbarbutton id="requests-menu-network-summary-button"
|
||||
class="devtools-toolbarbutton icon-and-text"
|
||||
data-localization="tooltiptext=netmonitor.toolbar.perf"/>
|
||||
<textbox id="requests-menu-filter-freetext-text"
|
||||
class="devtools-filterinput"
|
||||
type="search"
|
||||
required="true"
|
||||
data-localization="placeholder=netmonitor.toolbar.filterFreetext.label"/>
|
||||
<html:div xmlns="http://www.w3.org/1999/xhtml"
|
||||
id="react-details-pane-toggle-hook"/>
|
||||
<html:div xmlns="http://www.w3.org/1999/xhtml"
|
||||
id="react-search-box-hook"/>
|
||||
<html:div xmlns="http://www.w3.org/1999/xhtml"
|
||||
id="react-details-pane-toggle-hook"/>
|
||||
</hbox>
|
||||
|
|
|
@ -9,8 +9,6 @@ const promise = require("promise");
|
|||
const EventEmitter = require("devtools/shared/event-emitter");
|
||||
const { Task } = require("devtools/shared/task");
|
||||
const { localizeMarkup } = require("devtools/shared/l10n");
|
||||
const {KeyShortcuts} = require("devtools/client/shared/key-shortcuts");
|
||||
const {L10N} = require("./l10n");
|
||||
|
||||
function NetMonitorPanel(iframeWindow, toolbox) {
|
||||
this.panelWin = iframeWindow;
|
||||
|
@ -23,15 +21,6 @@ function NetMonitorPanel(iframeWindow, toolbox) {
|
|||
this._controller._toolbox = this._toolbox;
|
||||
|
||||
EventEmitter.decorate(this);
|
||||
|
||||
this.shortcuts = new KeyShortcuts({
|
||||
window: this.panelDoc.defaultView,
|
||||
});
|
||||
let key = L10N.getStr("netmonitor.toolbar.filterFreetext.key");
|
||||
this.shortcuts.on(key, (name, event) => {
|
||||
event.preventDefault();
|
||||
this._view.RequestsMenu.freetextFilterBox.focus();
|
||||
});
|
||||
}
|
||||
|
||||
exports.NetMonitorPanel = NetMonitorPanel;
|
||||
|
@ -79,8 +68,6 @@ NetMonitorPanel.prototype = {
|
|||
let deferred = promise.defer();
|
||||
this._destroying = deferred.promise;
|
||||
|
||||
this.shortcuts.destroy();
|
||||
|
||||
yield this._controller.shutdownNetMonitor();
|
||||
this.emit("destroyed");
|
||||
|
||||
|
|
|
@ -5,11 +5,12 @@
|
|||
|
||||
const I = require("devtools/client/shared/vendor/immutable");
|
||||
const {
|
||||
TOGGLE_FILTER,
|
||||
ENABLE_FILTER_ONLY,
|
||||
TOGGLE_FILTER_TYPE,
|
||||
ENABLE_FILTER_TYPE_ONLY,
|
||||
SET_FILTER_TEXT,
|
||||
} = require("../constants");
|
||||
|
||||
const FiltersTypes = I.Record({
|
||||
const FilterTypes = I.Record({
|
||||
all: false,
|
||||
html: false,
|
||||
css: false,
|
||||
|
@ -24,10 +25,11 @@ const FiltersTypes = I.Record({
|
|||
});
|
||||
|
||||
const Filters = I.Record({
|
||||
types: new FiltersTypes({ all: true }),
|
||||
types: new FilterTypes({ all: true }),
|
||||
url: "",
|
||||
});
|
||||
|
||||
function toggleFilter(state, action) {
|
||||
function toggleFilterType(state, action) {
|
||||
let { filter } = action;
|
||||
let newState;
|
||||
|
||||
|
@ -36,7 +38,7 @@ function toggleFilter(state, action) {
|
|||
return state;
|
||||
}
|
||||
if (filter === "all") {
|
||||
return new FiltersTypes({ all: true });
|
||||
return new FilterTypes({ all: true });
|
||||
}
|
||||
|
||||
newState = state.withMutations(types => {
|
||||
|
@ -45,13 +47,13 @@ function toggleFilter(state, action) {
|
|||
});
|
||||
|
||||
if (!newState.includes(true)) {
|
||||
newState = new FiltersTypes({ all: true });
|
||||
newState = new FilterTypes({ all: true });
|
||||
}
|
||||
|
||||
return newState;
|
||||
}
|
||||
|
||||
function enableFilterOnly(state, action) {
|
||||
function enableFilterTypeOnly(state, action) {
|
||||
let { filter } = action;
|
||||
|
||||
// Ignore unknown filter type
|
||||
|
@ -59,18 +61,17 @@ function enableFilterOnly(state, action) {
|
|||
return state;
|
||||
}
|
||||
|
||||
return new FiltersTypes({ [filter]: true });
|
||||
return new FilterTypes({ [filter]: true });
|
||||
}
|
||||
|
||||
function filters(state = new Filters(), action) {
|
||||
let types;
|
||||
switch (action.type) {
|
||||
case TOGGLE_FILTER:
|
||||
types = toggleFilter(state.types, action);
|
||||
return state.set("types", types);
|
||||
case ENABLE_FILTER_ONLY:
|
||||
types = enableFilterOnly(state.types, action);
|
||||
return state.set("types", types);
|
||||
case TOGGLE_FILTER_TYPE:
|
||||
return state.set("types", toggleFilterType(state.types, action));
|
||||
case ENABLE_FILTER_TYPE_ONLY:
|
||||
return state.set("types", enableFilterTypeOnly(state.types, action));
|
||||
case SET_FILTER_TEXT:
|
||||
return state.set("url", action.url);
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
NetMonitorController, NetMonitorView */
|
||||
"use strict";
|
||||
/* eslint-disable mozilla/reject-some-requires */
|
||||
const { Cc, Ci, Cu } = require("chrome");
|
||||
const { Cu } = require("chrome");
|
||||
const Services = require("Services");
|
||||
const {Task} = require("devtools/shared/task");
|
||||
const {DeferredTask} = Cu.import("resource://gre/modules/DeferredTask.jsm", {});
|
||||
|
@ -70,8 +70,7 @@ const REQUESTS_WATERFALL_BACKGROUND_TICKS_OPACITY_MIN = 32;
|
|||
const REQUESTS_WATERFALL_BACKGROUND_TICKS_OPACITY_ADD = 32;
|
||||
const REQUESTS_WATERFALL_DOMCONTENTLOADED_TICKS_COLOR_RGBA = [255, 0, 0, 128];
|
||||
const REQUESTS_WATERFALL_LOAD_TICKS_COLOR_RGBA = [0, 0, 255, 128];
|
||||
// ms
|
||||
const FREETEXT_FILTER_SEARCH_DELAY = 200;
|
||||
|
||||
// Constants for formatting bytes.
|
||||
const BYTES_IN_KB = 1024;
|
||||
const BYTES_IN_MB = Math.pow(BYTES_IN_KB, 2);
|
||||
|
@ -134,8 +133,6 @@ RequestsMenuView.prototype = Heritage.extend(WidgetMethods, {
|
|||
this._splitter = $("#network-inspector-view-splitter");
|
||||
this._summary = $("#requests-menu-network-summary-button");
|
||||
this._summary.setAttribute("label", L10N.getStr("networkMenu.empty"));
|
||||
this.userInputTimer = Cc["@mozilla.org/timer;1"]
|
||||
.createInstance(Ci.nsITimer);
|
||||
|
||||
// Create a tooltip for the newly appended network request item.
|
||||
this.tooltip = new HTMLTooltip(NetMonitorController._toolbox.doc, { type: "arrow" });
|
||||
|
@ -174,16 +171,8 @@ RequestsMenuView.prototype = Heritage.extend(WidgetMethods, {
|
|||
this.cloneSelectedRequestEvent = this.cloneSelectedRequest.bind(this);
|
||||
this.toggleRawHeadersEvent = this.toggleRawHeaders.bind(this);
|
||||
|
||||
this.requestsFreetextFilterEvent =
|
||||
this.requestsFreetextFilterEvent.bind(this);
|
||||
this.reFilterRequests = this.reFilterRequests.bind(this);
|
||||
|
||||
this.freetextFilterBox = $("#requests-menu-filter-freetext-text");
|
||||
this.freetextFilterBox.addEventListener("input",
|
||||
this.requestsFreetextFilterEvent, false);
|
||||
this.freetextFilterBox.addEventListener("command",
|
||||
this.requestsFreetextFilterEvent, false);
|
||||
|
||||
$("#toolbar-labels").addEventListener("click",
|
||||
this.requestsMenuSortEvent, false);
|
||||
$("#toolbar-labels").addEventListener("keydown",
|
||||
|
@ -195,18 +184,20 @@ RequestsMenuView.prototype = Heritage.extend(WidgetMethods, {
|
|||
|
||||
this.unsubscribeStore = store.subscribe(storeWatcher(
|
||||
null,
|
||||
() => store.getState().filters.types,
|
||||
(newTypes) => {
|
||||
this._activeFilters = newTypes
|
||||
() => store.getState().filters,
|
||||
(newFilters) => {
|
||||
this._activeFilters = newFilters.types
|
||||
.toSeq()
|
||||
.filter((checked, key) => checked)
|
||||
.keySeq()
|
||||
.toArray();
|
||||
this._currentFreetextFilter = newFilters.url;
|
||||
this.reFilterRequests();
|
||||
}
|
||||
));
|
||||
|
||||
Prefs.filters.forEach(type => store.dispatch(Actions.toggleFilter(type)));
|
||||
Prefs.filters.forEach(type =>
|
||||
store.dispatch(Actions.toggleFilterType(type)));
|
||||
|
||||
window.once("connected", this._onConnect.bind(this));
|
||||
},
|
||||
|
@ -268,12 +259,7 @@ RequestsMenuView.prototype = Heritage.extend(WidgetMethods, {
|
|||
this.requestsMenuSortEvent, false);
|
||||
$("#toolbar-labels").removeEventListener("keydown",
|
||||
this.requestsMenuSortKeyboardEvent, false);
|
||||
this.freetextFilterBox.removeEventListener("input",
|
||||
this.requestsFreetextFilterEvent, false);
|
||||
this.freetextFilterBox.removeEventListener("command",
|
||||
this.requestsFreetextFilterEvent, false);
|
||||
|
||||
this.userInputTimer.cancel();
|
||||
this._flushRequestsTask.disarm();
|
||||
|
||||
$("#requests-menu-reload-notice-button").removeEventListener("command",
|
||||
|
@ -615,23 +601,6 @@ RequestsMenuView.prototype = Heritage.extend(WidgetMethods, {
|
|||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Handles the timeout on the freetext filter textbox
|
||||
*/
|
||||
requestsFreetextFilterEvent: function () {
|
||||
this.userInputTimer.cancel();
|
||||
this._currentFreetextFilter = this.freetextFilterBox.value || "";
|
||||
|
||||
if (this._currentFreetextFilter.length === 0) {
|
||||
this.freetextFilterBox.removeAttribute("filled");
|
||||
} else {
|
||||
this.freetextFilterBox.setAttribute("filled", true);
|
||||
}
|
||||
|
||||
this.userInputTimer.initWithCallback(this.reFilterRequests,
|
||||
FREETEXT_FILTER_SEARCH_DELAY, Ci.nsITimer.TYPE_ONE_SHOT);
|
||||
},
|
||||
|
||||
/**
|
||||
* Refreshes the view contents with the newly selected filters
|
||||
*/
|
||||
|
|
|
@ -29,14 +29,12 @@ const REQUESTS_WITH_MEDIA_AND_FLASH_AND_WS = REQUESTS_WITH_MEDIA_AND_FLASH.conca
|
|||
]);
|
||||
|
||||
add_task(function* () {
|
||||
let Actions = require("devtools/client/netmonitor/actions/index");
|
||||
let { monitor } = yield initNetMonitor(FILTERING_URL);
|
||||
let { gStore } = monitor.panelWin;
|
||||
|
||||
function setFreetextFilter(value) {
|
||||
// Set the text and manually call all callbacks synchronously to avoid the timeout
|
||||
RequestsMenu.freetextFilterBox.value = value;
|
||||
RequestsMenu.requestsFreetextFilterEvent();
|
||||
RequestsMenu.userInputTimer.cancel();
|
||||
RequestsMenu.reFilterRequests();
|
||||
gStore.dispatch(Actions.setFilterText(value));
|
||||
}
|
||||
|
||||
info("Starting test... ");
|
||||
|
|
|
@ -28,7 +28,7 @@ add_task(function* () {
|
|||
info("Checking the image thumbnail when all items are sorted.");
|
||||
checkImageThumbnail();
|
||||
|
||||
gStore.dispatch(Actions.toggleFilter("images"));
|
||||
gStore.dispatch(Actions.toggleFilterType("images"));
|
||||
info("Checking the image thumbnail when only images are shown.");
|
||||
checkImageThumbnail();
|
||||
|
||||
|
|
|
@ -32,7 +32,7 @@ add_task(function* () {
|
|||
// Predicate used to modify the frontend when setting the new pref value,
|
||||
// before trying to validate the changes.
|
||||
modifyFrontend: ($, value) => value.forEach(e =>
|
||||
getStore().dispatch(Actions.toggleFilter(e)))
|
||||
getStore().dispatch(Actions.toggleFilterType(e)))
|
||||
},
|
||||
networkDetailsWidth: {
|
||||
newValue: ~~(Math.random() * 200 + 100),
|
||||
|
|
|
@ -6,6 +6,7 @@ const ReactDOM = require("devtools/client/shared/vendor/react-dom");
|
|||
const Provider = createFactory(require("devtools/client/shared/vendor/react-redux").Provider);
|
||||
const FilterButtons = createFactory(require("./components/filter-buttons"));
|
||||
const ToggleButton = createFactory(require("./components/toggle-button"));
|
||||
const SearchBox = createFactory(require("./components/search-box"));
|
||||
const { L10N } = require("./l10n");
|
||||
|
||||
// Shortcuts
|
||||
|
@ -28,6 +29,7 @@ ToolbarView.prototype = {
|
|||
this._clearContainerNode = $("#react-clear-button-hook");
|
||||
this._filterContainerNode = $("#react-filter-buttons-hook");
|
||||
this._toggleContainerNode = $("#react-details-pane-toggle-hook");
|
||||
this._searchContainerNode = $("#react-search-box-hook");
|
||||
|
||||
// clear button
|
||||
ReactDOM.render(button({
|
||||
|
@ -45,6 +47,13 @@ ToolbarView.prototype = {
|
|||
FilterButtons()
|
||||
), this._filterContainerNode);
|
||||
|
||||
// search box
|
||||
ReactDOM.render(Provider(
|
||||
{ store },
|
||||
SearchBox()
|
||||
), this._searchContainerNode);
|
||||
|
||||
// details pane toggle button
|
||||
ReactDOM.render(Provider(
|
||||
{ store },
|
||||
ToggleButton()
|
||||
|
@ -60,7 +69,9 @@ ToolbarView.prototype = {
|
|||
ReactDOM.unmountComponentAtNode(this._clearContainerNode);
|
||||
ReactDOM.unmountComponentAtNode(this._filterContainerNode);
|
||||
ReactDOM.unmountComponentAtNode(this._toggleContainerNode);
|
||||
ReactDOM.unmountComponentAtNode(this._searchContainerNode);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
exports.ToolbarView = ToolbarView;
|
||||
|
|
|
@ -44,7 +44,10 @@ module.exports = createClass({
|
|||
},
|
||||
|
||||
componentWillUnmount() {
|
||||
this.shortcuts.destroy();
|
||||
if (this.shortcuts) {
|
||||
this.shortcuts.destroy();
|
||||
}
|
||||
|
||||
// Clean up an existing timeout.
|
||||
if (this.searchTimeout) {
|
||||
clearTimeout(this.searchTimeout);
|
||||
|
|
|
@ -47,7 +47,7 @@ add_task(function* () {
|
|||
"The correct request is definitely selected");
|
||||
|
||||
// Filter out the HTML request.
|
||||
panel.panelWin.gStore.dispatch(Actions.toggleFilter("js"));
|
||||
panel.panelWin.gStore.dispatch(Actions.toggleFilterType("js"));
|
||||
|
||||
yield toolbox.selectTool("webconsole");
|
||||
is(toolbox.currentToolId, "webconsole", "Web console was selected");
|
||||
|
|
Загрузка…
Ссылка в новой задаче