Bug 1519105 - Add a keyboard shortcut to switch between inline and editor mode. r=Honza.
authorNicolas Chevobbe <nchevobbe@mozilla.com>
Fri, 28 Jun 2019 09:25:59 +0000
changeset 543338 8cb2280adc9c245ead1fe1de49793a38486bc92a
parent 543337 adf05ab240a59a1054e2d5f0dca0bf518b529283
child 543339 483b1e134ace636bd745403be2017a1b3cd18993
push id2131
push userffxbld-merge
push dateMon, 26 Aug 2019 18:30:20 +0000
treeherdermozilla-release@b19ffb3ca153 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersHonza
bugs1519105
milestone69.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 1519105 - Add a keyboard shortcut to switch between inline and editor mode. r=Honza. We use Cmd/Ctrl + B to switch between inline and editor mode. This should be familiar for VSCode users as it toggles the file sidebar. When changing the layout, we persist the choice into the editor pref so the user keeps the same layout the next time they open the console. Differential Revision: https://phabricator.services.mozilla.com/D34718
devtools/client/webconsole/actions/ui.js
devtools/client/webconsole/components/App.js
devtools/client/webconsole/constants.js
devtools/client/webconsole/reducers/ui.js
devtools/client/webconsole/test/mochitest/browser.ini
devtools/client/webconsole/test/mochitest/browser_jsterm_editor_toggle_keyboard_shortcut.js
devtools/client/webconsole/test/mochitest/head.js
--- a/devtools/client/webconsole/actions/ui.js
+++ b/devtools/client/webconsole/actions/ui.js
@@ -17,16 +17,17 @@ const {
   SELECT_NETWORK_MESSAGE_TAB,
   SHOW_CONTENT_MESSAGES_TOGGLE,
   SHOW_OBJECT_IN_SIDEBAR,
   SIDEBAR_CLOSE,
   SPLIT_CONSOLE_CLOSE_BUTTON_TOGGLE,
   TIMESTAMPS_TOGGLE,
   WARNING_GROUPS_TOGGLE,
   FILTERBAR_DISPLAY_MODE_SET,
+  EDITOR_TOGGLE,
 } = require("devtools/client/webconsole/constants");
 
 function persistToggle() {
   return ({dispatch, getState, prefsService}) => {
     dispatch({
       type: PERSIST_TOGGLE,
     });
     const uiState = getAllUi(getState());
@@ -66,29 +67,39 @@ function selectNetworkMessageTab(id) {
 }
 
 function initialize() {
   return {
     type: INITIALIZE,
   };
 }
 
-function sidebarClose(show) {
+function sidebarClose() {
   return {
     type: SIDEBAR_CLOSE,
   };
 }
 
 function splitConsoleCloseButtonToggle(shouldDisplayButton) {
   return {
     type: SPLIT_CONSOLE_CLOSE_BUTTON_TOGGLE,
     shouldDisplayButton,
   };
 }
 
+function editorToggle() {
+  return ({dispatch, getState, prefsService}) => {
+    dispatch({
+      type: EDITOR_TOGGLE,
+    });
+    const uiState = getAllUi(getState());
+    prefsService.setBoolPref(PREFS.UI.EDITOR, uiState.editor);
+  };
+}
+
 /**
  * Dispatches a SHOW_OBJECT_IN_SIDEBAR action, with a grip property corresponding to the
  * {actor} parameter in the {messageId} message.
  *
  * @param {String} actor: Actor id of the object we want to place in the sidebar.
  * @param {String} messageId: id of the message containing the {actor} parameter.
  */
 function showMessageObjectInSidebar(actor, messageId) {
@@ -123,16 +134,17 @@ function filterBarDisplayModeSet(display
   return {
     type: FILTERBAR_DISPLAY_MODE_SET,
     displayMode,
   };
 }
 
 module.exports = {
   contentMessagesToggle,
+  editorToggle,
   filterBarDisplayModeSet,
   initialize,
   persistToggle,
   reverseSearchInputToggle,
   selectNetworkMessageTab,
   showMessageObjectInSidebar,
   showObjectInSidebar,
   sidebarClose,
--- a/devtools/client/webconsole/components/App.js
+++ b/devtools/client/webconsole/components/App.js
@@ -79,16 +79,25 @@ class App extends Component {
     if (
       (!isMacOS && event.key === "F9") ||
       (isMacOS && event.key === "r" && event.ctrlKey === true)
     ) {
       const initialValue = webConsoleUI.jsterm && webConsoleUI.jsterm.getSelectedText();
       dispatch(actions.reverseSearchInputToggle({initialValue}));
       event.stopPropagation();
     }
+
+    if (event.key.toLowerCase() === "b" && (
+      isMacOS && event.metaKey ||
+      !isMacOS && event.ctrlKey
+    )) {
+      event.stopPropagation();
+      event.preventDefault();
+      dispatch(actions.editorToggle());
+    }
   }
 
   onClick(event) {
     const target = event.originalTarget || event.target;
     const {
       reverseSearchInputVisible,
       dispatch,
       webConsoleUI,
--- a/devtools/client/webconsole/constants.js
+++ b/devtools/client/webconsole/constants.js
@@ -9,16 +9,17 @@ const actionTypes = {
   APPEND_NOTIFICATION: "APPEND_NOTIFICATION",
   APPEND_TO_HISTORY: "APPEND_TO_HISTORY",
   AUTOCOMPLETE_CLEAR: "AUTOCOMPLETE_CLEAR",
   AUTOCOMPLETE_DATA_RECEIVE: "AUTOCOMPLETE_DATA_RECEIVE",
   AUTOCOMPLETE_PENDING_REQUEST: "AUTOCOMPLETE_PENDING_REQUEST",
   AUTOCOMPLETE_RETRIEVE_FROM_CACHE: "AUTOCOMPLETE_RETRIEVE_FROM_CACHE",
   BATCH_ACTIONS: "BATCH_ACTIONS",
   CLEAR_HISTORY: "CLEAR_HISTORY",
+  EDITOR_TOGGLE: "EDITOR_TOGGLE",
   FILTER_TEXT_SET: "FILTER_TEXT_SET",
   FILTER_TOGGLE: "FILTER_TOGGLE",
   FILTERS_CLEAR: "FILTERS_CLEAR",
   FILTERBAR_DISPLAY_MODE_SET: "FILTERBAR_DISPLAY_MODE_SET",
   HISTORY_LOADED: "HISTORY_LOADED",
   INITIALIZE: "INITIALIZE",
   MESSAGE_CLOSE: "MESSAGE_CLOSE",
   MESSAGE_OPEN: "MESSAGE_OPEN",
--- a/devtools/client/webconsole/reducers/ui.js
+++ b/devtools/client/webconsole/reducers/ui.js
@@ -13,16 +13,17 @@ const {
   SELECT_NETWORK_MESSAGE_TAB,
   SHOW_CONTENT_MESSAGES_TOGGLE,
   SHOW_OBJECT_IN_SIDEBAR,
   SIDEBAR_CLOSE,
   SPLIT_CONSOLE_CLOSE_BUTTON_TOGGLE,
   TIMESTAMPS_TOGGLE,
   FILTERBAR_DISPLAY_MODE_SET,
   FILTERBAR_DISPLAY_MODES,
+  EDITOR_TOGGLE,
 } = require("devtools/client/webconsole/constants");
 
 const {
   PANELS,
 } = require("devtools/client/netmonitor/src/constants");
 
 const UiState = (overrides) => Object.freeze(Object.assign({
   initialized: false,
@@ -72,16 +73,21 @@ function ui(state = UiState(), action) {
         reverseSearchInputVisible: !state.reverseSearchInputVisible,
         reverseSearchInitialValue: action.initialValue || "",
       };
     case FILTERBAR_DISPLAY_MODE_SET:
       return {
         ...state,
         filterBarDisplayMode: action.displayMode,
       };
+    case EDITOR_TOGGLE:
+      return {
+        ...state,
+        editor: !state.editor,
+      };
   }
 
   return state;
 }
 
 module.exports = {
   UiState,
   ui,
--- a/devtools/client/webconsole/test/mochitest/browser.ini
+++ b/devtools/client/webconsole/test/mochitest/browser.ini
@@ -207,16 +207,17 @@ skip-if = (os == "win" && processor == "
 [browser_jsterm_copy_command.js]
 [browser_jsterm_ctrl_a_select_all.js]
 [browser_jsterm_ctrl_key_nav.js]
 skip-if = os != 'mac' # The tested ctrl+key shortcuts are OSX only
 [browser_jsterm_document_no_xray.js]
 [browser_jsterm_editor.js]
 [browser_jsterm_editor_enter.js]
 [browser_jsterm_editor_execute.js]
+[browser_jsterm_editor_toggle_keyboard_shortcut.js]
 [browser_jsterm_editor_toolbar.js]
 [browser_jsterm_error_docs.js]
 [browser_jsterm_error_outside_valid_range.js]
 [browser_jsterm_focus_reload.js]
 [browser_jsterm_helper_clear.js]
 [browser_jsterm_helper_dollar_dollar.js]
 skip-if = (os == "win" && processor == "aarch64") # disabled on aarch64 due to 1535082
 [browser_jsterm_helper_dollar_x.js]
new file mode 100644
--- /dev/null
+++ b/devtools/client/webconsole/test/mochitest/browser_jsterm_editor_toggle_keyboard_shortcut.js
@@ -0,0 +1,61 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+// Test that hitting Ctrl + E does toggle the editor mode.
+// See https://bugzilla.mozilla.org/show_bug.cgi?id=1519105
+
+"use strict";
+
+const TEST_URI = "data:text/html;charset=utf-8,Test editor mode toggle keyboard shortcut";
+const EDITOR_PREF = "devtools.webconsole.input.editor";
+
+add_task(async function() {
+  await pushPref("devtools.webconsole.input.editor", true);
+  // Run test with legacy JsTerm
+  info("Test legacy JsTerm");
+  await pushPref("devtools.webconsole.jsterm.codeMirror", false);
+  await performTest();
+
+  // And then run it with the CodeMirror-powered one.
+  info("Test codeMirror JsTerm");
+  await pushPref("devtools.webconsole.jsterm.codeMirror", true);
+  await performTest();
+});
+
+async function performTest() {
+  // Start with the editor turned off
+  await pushPref(EDITOR_PREF, false);
+  let hud = await openNewTabAndConsole(TEST_URI);
+
+  is(isEditorModeEnabled(hud), false, "The console isn't in editor mode");
+
+  info("Enable the editor mode");
+  await toggleLayout(hud);
+  is(isEditorModeEnabled(hud), true, "Editor mode is enabled");
+
+  info("Close the console and reopen it");
+  await closeConsole();
+  hud = await openConsole();
+  is(isEditorModeEnabled(hud), true, "Editor mode is still enabled");
+
+  info("Disable the editor mode");
+  await toggleLayout(hud);
+  is(isEditorModeEnabled(hud), false, "Editor was disabled");
+
+  info("Enable the editor mode again");
+  await toggleLayout(hud);
+  is(isEditorModeEnabled(hud), true, "Editor mode was enabled again");
+
+  Services.prefs.clearUserPref(EDITOR_PREF);
+}
+
+function toggleLayout(hud) {
+  const isMacOS = Services.appinfo.OS === "Darwin";
+
+  const enabled = isEditorModeEnabled(hud);
+
+  EventUtils.synthesizeKey("b", {
+    [isMacOS ? "metaKey" : "ctrlKey"]: true,
+  });
+  return waitFor(() => isEditorModeEnabled(hud) === !enabled);
+}
--- a/devtools/client/webconsole/test/mochitest/head.js
+++ b/devtools/client/webconsole/test/mochitest/head.js
@@ -1386,17 +1386,16 @@ function reloadPage() {
   const onLoad = BrowserTestUtils.waitForContentEvent(
     gBrowser.selectedBrowser, "load", true);
   ContentTask.spawn(gBrowser.selectedBrowser, null, () => {
     content.location.reload();
   });
   return onLoad;
 }
 
-         
 /**
   * Check if the editor mode is enabled (i.e. .webconsole-app has the expected class).
   *
   * @param {WebConsole} hud
   * @returns {Boolean}
   */
 function isEditorModeEnabled(hud) {
   const {outputNode} = hud.ui;