Bug 1572396 - Introduce Search button in the Net panel toolbar; r=nchevobbe
authorJan Odvarko <odvarko@gmail.com>
Fri, 16 Aug 2019 10:42:59 +0000
changeset 488478 90203b8c145dfc2c1672e0d59f1a2d07e4ee8c2a
parent 488477 61d898c2b4445f0a10c6d8b618e0dc13519642ce
child 488479 a61a256c7eafbbbc11b57ed0d8f0e1a1e0144cae
push id36444
push userccoroiu@mozilla.com
push dateFri, 16 Aug 2019 16:24:18 +0000
treeherdermozilla-central@8a9e9189cd98 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersnchevobbe
bugs1572396
milestone70.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1572396 - Introduce Search button in the Net panel toolbar; r=nchevobbe Differential Revision: https://phabricator.services.mozilla.com/D42080
devtools/client/locales/en-US/netmonitor.properties
devtools/client/netmonitor/src/assets/styles/Toolbar.css
devtools/client/netmonitor/src/components/RequestListContent.js
devtools/client/netmonitor/src/components/Toolbar.js
devtools/client/netmonitor/src/widgets/RequestListContextMenu.js
--- a/devtools/client/locales/en-US/netmonitor.properties
+++ b/devtools/client/locales/en-US/netmonitor.properties
@@ -887,16 +887,20 @@ netmonitor.toolbar.disableCache.tooltip=
 # LOCALIZATION NOTE (netmonitor.toolbar.clear): This is the label displayed
 # in the network toolbar for the "Clear" button.
 netmonitor.toolbar.clear=Clear
 
 # LOCALIZATION NOTE (netmonitor.toolbar.toggleRecording): This is the label displayed
 # in the network toolbar for the toggle recording button.
 netmonitor.toolbar.toggleRecording=Pause/Resume recording network log
 
+# LOCALIZATION NOTE (netmonitor.toolbar.search): This is the tooltip label displayed
+# in the network toolbar for the search  button.
+netmonitor.toolbar.search=Search
+
 # LOCALIZATION NOTE (netmonitor.toolbar.perf): This is the label displayed
 # in the network toolbar for the performance analysis button.
 netmonitor.toolbar.perf=Toggle performance analysis…
 
 # LOCALIZATION NOTE (netmonitor.toolbar.resetColumns): This is the label
 # displayed in the network table header context menu.
 netmonitor.toolbar.resetColumns=Reset Columns
 
--- a/devtools/client/netmonitor/src/assets/styles/Toolbar.css
+++ b/devtools/client/netmonitor/src/assets/styles/Toolbar.css
@@ -27,16 +27,23 @@
 .devtools-button.devtools-pause-icon::before {
   background-image: url("chrome://devtools/skin/images/pause.svg");
 }
 
 .devtools-button.devtools-play-icon::before {
   background-image: url("chrome://devtools/content/netmonitor/src/assets/icons/play.svg");
 }
 
+/* Search button */
+
+.devtools-button.devtools-search-icon::before {
+  background-image: url("chrome://devtools/skin/images/search.svg");
+  background-size: 13px;
+}
+
 /* HAR button */
 
 #devtools-har-button {
   margin-inline-end: 10px;
   padding-left: 2px;
   padding-right: 10px;
   background-position: right center;
 }
--- a/devtools/client/netmonitor/src/components/RequestListContent.js
+++ b/devtools/client/netmonitor/src/components/RequestListContent.js
@@ -83,18 +83,16 @@ class RequestListContent extends Compone
       onSelectDelta: PropTypes.func.isRequired,
       onWaterfallMouseDown: PropTypes.func.isRequired,
       openStatistics: PropTypes.func.isRequired,
       scale: PropTypes.number,
       selectRequest: PropTypes.func.isRequired,
       selectedRequest: PropTypes.object,
       unblockSelectedRequestURL: PropTypes.func.isRequired,
       requestFilterTypes: PropTypes.object.isRequired,
-      panelOpen: PropTypes.bool,
-      toggleSearchPanel: PropTypes.func.isRequired,
     };
   }
 
   constructor(props) {
     super(props);
     this.isScrolledToBottom = this.isScrolledToBottom.bind(this);
     this.onHover = this.onHover.bind(this);
     this.onScroll = this.onScroll.bind(this);
@@ -307,30 +305,26 @@ class RequestListContent extends Compone
       const {
         blockSelectedRequestURL,
         connector,
         cloneRequest,
         openDetailsPanelTab,
         sendCustomRequest,
         openStatistics,
         unblockSelectedRequestURL,
-        toggleSearchPanel,
-        panelOpen,
       } = this.props;
       this.contextMenu = new RequestListContextMenu({
         blockSelectedRequestURL,
         connector,
         cloneRequest,
         openDetailsPanelTab,
         sendCustomRequest,
         openStatistics,
         openRequestInTab: this.openRequestInTab,
         unblockSelectedRequestURL,
-        toggleSearchPanel,
-        panelOpen,
       });
     }
 
     this.contextMenu.open(evt, clickedRequest, displayedRequests);
   }
 
   /**
    * If selection has just changed (by keyboard navigation), don't keep the list
@@ -411,17 +405,16 @@ module.exports = connect(
     networkDetailsWidth: state.ui.networkDetailsWidth,
     networkDetailsHeight: state.ui.networkDetailsHeight,
     clickedRequest: state.requests.clickedRequest,
     displayedRequests: getDisplayedRequests(state),
     firstRequestStartedMs: state.requests.firstStartedMs,
     selectedRequest: getSelectedRequest(state),
     scale: getWaterfallScale(state),
     requestFilterTypes: state.filters.requestFilterTypes,
-    panelOpen: state.search.panelOpen,
   }),
   (dispatch, props) => ({
     blockSelectedRequestURL: clickedRequest => {
       dispatch(
         Actions.blockSelectedRequestURL(props.connector, clickedRequest)
       );
     },
     cloneRequest: id => dispatch(Actions.cloneRequest(id)),
@@ -458,11 +451,10 @@ module.exports = connect(
     },
     onSelectDelta: delta => dispatch(Actions.selectDelta(delta)),
     /**
      * A handler that opens the timing sidebar panel if the waterfall is clicked.
      */
     onWaterfallMouseDown: () => {
       dispatch(Actions.selectDetailsPanelTab("timings"));
     },
-    toggleSearchPanel: () => dispatch(Actions.toggleSearchPanel()),
   })
 )(RequestListContent);
--- a/devtools/client/netmonitor/src/components/Toolbar.js
+++ b/devtools/client/netmonitor/src/components/Toolbar.js
@@ -47,16 +47,17 @@ const SEARCH_KEY_SHORTCUT = L10N.getStr(
 );
 const SEARCH_PLACE_HOLDER = L10N.getStr(
   "netmonitor.toolbar.filterFreetext.label"
 );
 const TOOLBAR_CLEAR = L10N.getStr("netmonitor.toolbar.clear");
 const TOOLBAR_TOGGLE_RECORDING = L10N.getStr(
   "netmonitor.toolbar.toggleRecording"
 );
+const TOOLBAR_SEARCH = L10N.getStr("netmonitor.toolbar.search");
 const TOOLBAR_HAR_BUTTON = L10N.getStr("netmonitor.label.har");
 const LEARN_MORE_TITLE = L10N.getStr(
   "netmonitor.toolbar.filterFreetext.learnMore"
 );
 
 // Preferences
 const DEVTOOLS_DISABLE_CACHE_PREF = "devtools.cache.disabled";
 const DEVTOOLS_ENABLE_PERSISTENT_LOG_PREF = "devtools.netmonitor.persistlog";
@@ -129,16 +130,18 @@ class Toolbar extends Component {
       // Set to true if there is enough horizontal space
       // and the toolbar needs just one row.
       singleRow: PropTypes.bool.isRequired,
       // Callback for opening split console.
       openSplitConsole: PropTypes.func,
       networkThrottling: PropTypes.shape(Types.networkThrottling).isRequired,
       // Executed when throttling changes (through toolbar button).
       onChangeNetworkThrottling: PropTypes.func.isRequired,
+      toggleSearchPanel: PropTypes.func.isRequired,
+      searchPanelOpen: PropTypes.bool.isRequired,
     };
   }
 
   constructor(props) {
     super(props);
 
     this.autocompleteProvider = this.autocompleteProvider.bind(this);
     this.onSearchBoxFocus = this.onSearchBoxFocus.bind(this);
@@ -162,16 +165,17 @@ class Toolbar extends Component {
     );
   }
 
   shouldComponentUpdate(nextProps) {
     return (
       this.props.persistentLogsEnabled !== nextProps.persistentLogsEnabled ||
       this.props.browserCacheDisabled !== nextProps.browserCacheDisabled ||
       this.props.recording !== nextProps.recording ||
+      this.props.searchPanelOpen !== nextProps.searchPanelOpen ||
       this.props.singleRow !== nextProps.singleRow ||
       !Object.is(this.props.requestFilterTypes, nextProps.requestFilterTypes) ||
       this.props.networkThrottling !== nextProps.networkThrottling ||
       // Filtered requests are useful only when searchbox is focused
       !!(this.refs.searchbox && this.refs.searchbox.focused)
     );
   }
 
@@ -260,16 +264,45 @@ class Toolbar extends Component {
     return button({
       className: toggleRecordingButtonClass,
       title: TOOLBAR_TOGGLE_RECORDING,
       onClick: toggleRecording,
     });
   }
 
   /**
+   * Render a search button.
+   */
+  renderSearchButton(toggleSearchPanel) {
+    const { searchPanelOpen } = this.props;
+
+    // The search feature is available behind a pref.
+    if (!Services.prefs.getBoolPref("devtools.netmonitor.features.search")) {
+      return null;
+    }
+
+    const className = [
+      "devtools-button",
+      "devtools-search-icon",
+      "requests-list-search-button",
+    ];
+
+    if (searchPanelOpen) {
+      className.push("checked");
+    }
+
+    return button({
+      className: className.join(" "),
+      title: TOOLBAR_SEARCH,
+      "aria-pressed": searchPanelOpen,
+      onClick: toggleSearchPanel,
+    });
+  }
+
+  /**
    * Render filter buttons.
    */
   renderFilterButtons(requestFilterTypes) {
     // Render list of filter-buttons.
     const buttons = Object.entries(requestFilterTypes).map(([type, checked]) =>
       button(
         {
           className: `devtools-togglebutton requests-list-filter-${type}-button`,
@@ -417,30 +450,32 @@ class Toolbar extends Component {
       requestFilterTypes,
       setRequestFilterText,
       togglePersistentLogs,
       persistentLogsEnabled,
       toggleBrowserCache,
       browserCacheDisabled,
       recording,
       singleRow,
+      toggleSearchPanel,
     } = this.props;
 
     // Render the entire toolbar.
     // dock at bottom or dock at side has different layout
     return singleRow
       ? span(
           { id: "netmonitor-toolbar-container" },
           span(
             { className: "devtools-toolbar devtools-input-toolbar" },
             this.renderClearButton(clearRequests),
             this.renderSeparator(),
             this.renderFilterBox(setRequestFilterText),
             this.renderSeparator(),
             this.renderToggleRecordingButton(recording, toggleRecording),
+            this.renderSearchButton(toggleSearchPanel),
             this.renderSeparator(),
             this.renderFilterButtons(requestFilterTypes),
             this.renderSeparator(),
             this.renderPersistlogCheckbox(
               persistentLogsEnabled,
               togglePersistentLogs
             ),
             this.renderCacheCheckbox(browserCacheDisabled, toggleBrowserCache),
@@ -453,16 +488,17 @@ class Toolbar extends Component {
           { id: "netmonitor-toolbar-container" },
           span(
             { className: "devtools-toolbar devtools-input-toolbar" },
             this.renderClearButton(clearRequests),
             this.renderSeparator(),
             this.renderFilterBox(setRequestFilterText),
             this.renderSeparator(),
             this.renderToggleRecordingButton(recording, toggleRecording),
+            this.renderSearchButton(toggleSearchPanel),
             this.renderSeparator(),
             this.renderPersistlogCheckbox(
               persistentLogsEnabled,
               togglePersistentLogs
             ),
             this.renderCacheCheckbox(browserCacheDisabled, toggleBrowserCache),
             this.renderSeparator(),
             this.renderThrottlingMenu(),
@@ -480,25 +516,27 @@ module.exports = connect(
   state => ({
     browserCacheDisabled: state.ui.browserCacheDisabled,
     displayedRequests: getDisplayedRequests(state),
     filteredRequests: getTypeFilteredRequests(state),
     persistentLogsEnabled: state.ui.persistentLogsEnabled,
     recording: getRecordingState(state),
     requestFilterTypes: state.filters.requestFilterTypes,
     networkThrottling: state.networkThrottling,
+    searchPanelOpen: state.search.panelOpen,
   }),
   dispatch => ({
     clearRequests: () => dispatch(Actions.clearRequests()),
     disableBrowserCache: disabled =>
       dispatch(Actions.disableBrowserCache(disabled)),
     enablePersistentLogs: (enabled, skipTelemetry) =>
       dispatch(Actions.enablePersistentLogs(enabled, skipTelemetry)),
     setRequestFilterText: text => dispatch(Actions.setRequestFilterText(text)),
     toggleBrowserCache: () => dispatch(Actions.toggleBrowserCache()),
     toggleRecording: () => dispatch(Actions.toggleRecording()),
     togglePersistentLogs: () => dispatch(Actions.togglePersistentLogs()),
     toggleRequestFilterType: type =>
       dispatch(Actions.toggleRequestFilterType(type)),
     onChangeNetworkThrottling: (enabled, profile) =>
       dispatch(changeNetworkThrottling(enabled, profile)),
+    toggleSearchPanel: () => dispatch(Actions.toggleSearchPanel()),
   })
 )(Toolbar);
--- a/devtools/client/netmonitor/src/widgets/RequestListContextMenu.js
+++ b/devtools/client/netmonitor/src/widgets/RequestListContextMenu.js
@@ -335,34 +335,16 @@ class RequestListContextMenu {
       id: "request-list-context-use-as-fetch",
       label: L10N.getStr("netmonitor.context.useAsFetch"),
       accesskey: L10N.getStr("netmonitor.context.useAsFetch.accesskey"),
       visible: !!clickedRequest,
       click: () =>
         this.useAsFetch(id, url, method, requestHeaders, requestPostData),
     });
 
-    if (Services.prefs.getBoolPref("devtools.netmonitor.features.search")) {
-      const { toggleSearchPanel, panelOpen } = this.props;
-
-      menu.push({
-        type: "separator",
-      });
-
-      menu.push({
-        id: "request-list-context-search",
-        label: "Search...", // TODO localization
-        accesskey: "S", // TODO localization
-        type: "checkbox",
-        checked: panelOpen,
-        visible: !!clickedRequest,
-        click: () => toggleSearchPanel(),
-      });
-    }
-
     showMenu(menu, {
       screenX: event.screenX,
       screenY: event.screenY,
     });
   }
 
   /**
    * Opens selected item in the debugger