mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-21 17:25:36 +00:00
Bug 1554877 - Make JsTerm editor resizable. r=Honza.
We add a GridElementWidthResizer to handle the editor width. The width is then persisted in a pref. A test is added to ensure this works as expected. Differential Revision: https://phabricator.services.mozilla.com/D37687 --HG-- extra : moz-landing-system : lando
This commit is contained in:
parent
5642141d9f
commit
73adf5f4f8
@ -290,6 +290,10 @@ pref("devtools.webconsole.features.editor", false);
|
||||
// Saved editor mode state in the console.
|
||||
pref("devtools.webconsole.input.editor", false);
|
||||
|
||||
// Editor width for webconsole and browserconsole
|
||||
pref("devtools.webconsole.input.editorWidth", 0);
|
||||
pref("devtools.browserconsole.input.editorWidth", 0);
|
||||
|
||||
// Disable the new performance recording panel by default
|
||||
pref("devtools.performance.new-panel-enabled", false);
|
||||
|
||||
|
@ -23,6 +23,7 @@ const {
|
||||
WARNING_GROUPS_TOGGLE,
|
||||
FILTERBAR_DISPLAY_MODE_SET,
|
||||
EDITOR_TOGGLE,
|
||||
EDITOR_SET_WIDTH,
|
||||
} = require("devtools/client/webconsole/constants");
|
||||
|
||||
function persistToggle() {
|
||||
@ -98,6 +99,16 @@ function editorToggle() {
|
||||
};
|
||||
}
|
||||
|
||||
function setEditorWidth(width) {
|
||||
return ({ dispatch, prefsService }) => {
|
||||
dispatch({
|
||||
type: EDITOR_SET_WIDTH,
|
||||
width,
|
||||
});
|
||||
prefsService.setIntPref(PREFS.UI.EDITOR_WIDTH, width);
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Dispatches a SHOW_OBJECT_IN_SIDEBAR action, with a grip property corresponding to the
|
||||
* {actor} parameter in the {messageId} message.
|
||||
@ -148,6 +159,7 @@ module.exports = {
|
||||
persistToggle,
|
||||
reverseSearchInputToggle,
|
||||
selectNetworkMessageTab,
|
||||
setEditorWidth,
|
||||
showMessageObjectInSidebar,
|
||||
showObjectInSidebar,
|
||||
sidebarClose,
|
||||
|
@ -46,6 +46,9 @@ const ConfirmDialog = createFactory(
|
||||
const NotificationBox = createFactory(
|
||||
require("devtools/client/shared/components/NotificationBox").NotificationBox
|
||||
);
|
||||
const GridElementWidthResizer = createFactory(
|
||||
require("devtools/client/shared/components/splitter/GridElementWidthResizer")
|
||||
);
|
||||
|
||||
const l10n = require("devtools/client/webconsole/webconsole-l10n");
|
||||
const { Utils: WebConsoleUtils } = require("devtools/client/webconsole/utils");
|
||||
@ -82,6 +85,7 @@ class App extends Component {
|
||||
reverseSearchInputVisible: PropTypes.bool,
|
||||
reverseSearchInitialValue: PropTypes.string,
|
||||
editorMode: PropTypes.bool,
|
||||
editorWidth: PropTypes.number,
|
||||
hideShowContentMessagesCheckbox: PropTypes.bool,
|
||||
sidebarVisible: PropTypes.bool.isRequired,
|
||||
filterBarDisplayMode: PropTypes.oneOf([
|
||||
@ -265,6 +269,7 @@ class App extends Component {
|
||||
jstermCodeMirror,
|
||||
autocomplete,
|
||||
editorMode,
|
||||
editorWidth,
|
||||
} = this.props;
|
||||
|
||||
return JSTerm({
|
||||
@ -275,6 +280,7 @@ class App extends Component {
|
||||
codeMirrorEnabled: jstermCodeMirror,
|
||||
autocomplete,
|
||||
editorMode,
|
||||
editorWidth,
|
||||
});
|
||||
}
|
||||
|
||||
@ -292,7 +298,6 @@ class App extends Component {
|
||||
|
||||
renderSideBar() {
|
||||
const { serviceContainer, sidebarVisible } = this.props;
|
||||
|
||||
return SideBar({
|
||||
key: "sidebar",
|
||||
serviceContainer,
|
||||
@ -349,7 +354,7 @@ class App extends Component {
|
||||
}
|
||||
|
||||
render() {
|
||||
const { webConsoleUI, editorMode } = this.props;
|
||||
const { webConsoleUI, editorMode, dispatch } = this.props;
|
||||
|
||||
const filterBar = this.renderFilterBar();
|
||||
const consoleOutput = this.renderConsoleOutput();
|
||||
@ -373,6 +378,13 @@ class App extends Component {
|
||||
notificationBox,
|
||||
jsterm
|
||||
),
|
||||
GridElementWidthResizer({
|
||||
enabled: editorMode,
|
||||
position: "end",
|
||||
className: "editor-resizer",
|
||||
getControlledElementNode: () => webConsoleUI.jsterm.node,
|
||||
onResizeEnd: width => dispatch(actions.setEditorWidth(width)),
|
||||
}),
|
||||
reverseSearch,
|
||||
sidebar,
|
||||
confirmDialog,
|
||||
@ -385,6 +397,7 @@ const mapStateToProps = state => ({
|
||||
reverseSearchInputVisible: state.ui.reverseSearchInputVisible,
|
||||
reverseSearchInitialValue: state.ui.reverseSearchInitialValue,
|
||||
editorMode: state.ui.editor,
|
||||
editorWidth: state.ui.editorWidth,
|
||||
sidebarVisible: state.ui.sidebarVisible,
|
||||
filterBarDisplayMode: state.ui.filterBarDisplayMode,
|
||||
});
|
||||
|
@ -114,6 +114,7 @@ class JSTerm extends Component {
|
||||
autocompleteData: PropTypes.object.isRequired,
|
||||
// Is the input in editor mode.
|
||||
editorMode: PropTypes.bool,
|
||||
editorWidth: PropTypes.number,
|
||||
autocomplete: PropTypes.bool,
|
||||
};
|
||||
}
|
||||
@ -154,6 +155,10 @@ class JSTerm extends Component {
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
if (this.props.editorMode) {
|
||||
this.setEditorWidth(this.props.editorWidth);
|
||||
}
|
||||
|
||||
const autocompleteOptions = {
|
||||
onSelect: this.onAutocompleteSelect.bind(this),
|
||||
onClick: this.acceptProposedCompletion.bind(this),
|
||||
@ -539,8 +544,33 @@ class JSTerm extends Component {
|
||||
this.updateAutocompletionPopup(nextProps.autocompleteData);
|
||||
}
|
||||
|
||||
if (this.editor && nextProps.editorMode !== this.props.editorMode) {
|
||||
this.editor.setOption("lineNumbers", nextProps.editorMode);
|
||||
if (nextProps.editorMode !== this.props.editorMode) {
|
||||
if (this.editor) {
|
||||
this.editor.setOption("lineNumbers", nextProps.editorMode);
|
||||
}
|
||||
|
||||
if (nextProps.editorMode && nextProps.editorWidth) {
|
||||
this.setEditorWidth(nextProps.editorWidth);
|
||||
} else {
|
||||
this.setEditorWidth(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {Number|null} editorWidth: The width to set the node to. If null, removes any
|
||||
* `width` property on node style.
|
||||
*/
|
||||
setEditorWidth(editorWidth) {
|
||||
if (!this.node) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (editorWidth) {
|
||||
this.node.style.width = `${editorWidth}px`;
|
||||
} else {
|
||||
this.node.style.removeProperty("width");
|
||||
}
|
||||
}
|
||||
|
||||
@ -1795,6 +1825,9 @@ class JSTerm extends Component {
|
||||
key: "jsterm-container",
|
||||
style: { direction: "ltr" },
|
||||
"aria-live": "off",
|
||||
ref: node => {
|
||||
this.node = node;
|
||||
},
|
||||
},
|
||||
dom.textarea({
|
||||
className: "jsterm-complete-node devtools-monospace",
|
||||
|
@ -47,6 +47,7 @@ const actionTypes = {
|
||||
PAUSED_EXCECUTION_POINT: "PAUSED_EXCECUTION_POINT",
|
||||
WARNING_GROUPS_TOGGLE: "WARNING_GROUPS_TOGGLE",
|
||||
WILL_NAVIGATE: "WILL_NAVIGATE",
|
||||
EDITOR_SET_WIDTH: "EDITOR_SET_WIDTH",
|
||||
};
|
||||
|
||||
const prefs = {
|
||||
@ -74,6 +75,8 @@ const prefs = {
|
||||
CONTENT_MESSAGES: "devtools.browserconsole.contentMessages",
|
||||
// Display timestamp in messages.
|
||||
MESSAGE_TIMESTAMP: "devtools.webconsole.timestampMessages",
|
||||
// Store the editor width.
|
||||
EDITOR_WIDTH: "input.editorWidth",
|
||||
},
|
||||
FEATURES: {
|
||||
// We use the same pref to enable the sidebar on webconsole and browser console.
|
||||
|
@ -19,6 +19,7 @@ const {
|
||||
FILTERBAR_DISPLAY_MODE_SET,
|
||||
FILTERBAR_DISPLAY_MODES,
|
||||
EDITOR_TOGGLE,
|
||||
EDITOR_SET_WIDTH,
|
||||
} = require("devtools/client/webconsole/constants");
|
||||
|
||||
const { PANELS } = require("devtools/client/netmonitor/src/constants");
|
||||
@ -38,6 +39,7 @@ const UiState = overrides =>
|
||||
reverseSearchInputVisible: false,
|
||||
reverseSearchInitialValue: "",
|
||||
editor: false,
|
||||
editorWidth: null,
|
||||
filterBarDisplayMode: FILTERBAR_DISPLAY_MODES.WIDE,
|
||||
},
|
||||
overrides
|
||||
@ -87,6 +89,11 @@ function ui(state = UiState(), action) {
|
||||
...state,
|
||||
editor: !state.editor,
|
||||
};
|
||||
case EDITOR_SET_WIDTH:
|
||||
return {
|
||||
...state,
|
||||
editorWidth: action.width,
|
||||
};
|
||||
}
|
||||
|
||||
return state;
|
||||
|
@ -78,6 +78,7 @@ function configureStore(webConsoleUI, options = {}) {
|
||||
? getBoolPref(PREFS.UI.CONTENT_MESSAGES)
|
||||
: true,
|
||||
editor: getBoolPref(PREFS.UI.EDITOR),
|
||||
editorWidth: getIntPref(PREFS.UI.EDITOR_WIDTH),
|
||||
timestampsVisible: getBoolPref(PREFS.UI.MESSAGE_TIMESTAMP),
|
||||
}),
|
||||
};
|
||||
|
@ -29,6 +29,7 @@ pref("devtools.webconsole.input.editor", false);
|
||||
pref("devtools.webconsole.input.autocomplete", true);
|
||||
pref("devtools.browserconsole.contentMessages", true);
|
||||
pref("devtools.webconsole.features.editor", true);
|
||||
pref("devtools.webconsole.input.editorWidth", 800);
|
||||
|
||||
global.loader = {
|
||||
lazyServiceGetter: () => {},
|
||||
|
@ -216,6 +216,7 @@ skip-if = os != 'mac' # The tested ctrl+key shortcuts are OSX only
|
||||
[browser_jsterm_editor_execute.js]
|
||||
[browser_jsterm_editor_gutter.js]
|
||||
[browser_jsterm_editor_toggle_keyboard_shortcut.js]
|
||||
[browser_jsterm_editor_resize.js]
|
||||
[browser_jsterm_editor_toolbar.js]
|
||||
[browser_jsterm_error_docs.js]
|
||||
[browser_jsterm_error_outside_valid_range.js]
|
||||
|
@ -0,0 +1,88 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
// Test that the editor can be resized and that its width is persisted.
|
||||
|
||||
"use strict";
|
||||
|
||||
const TEST_URI =
|
||||
"data:text/html;charset=utf-8,Web Console test for editor resize";
|
||||
|
||||
add_task(async function() {
|
||||
await pushPref("devtools.webconsole.features.editor", true);
|
||||
await pushPref("devtools.webconsole.input.editor", true);
|
||||
|
||||
// Run test with legacy JsTerm
|
||||
await pushPref("devtools.webconsole.jsterm.codeMirror", false);
|
||||
await performTests();
|
||||
// And then run it with the CodeMirror-powered one.
|
||||
await pushPref("devtools.webconsole.jsterm.codeMirror", true);
|
||||
await performTests();
|
||||
});
|
||||
|
||||
async function performTests() {
|
||||
// Reset editorWidth pref so we have steady results when running multiple times.
|
||||
await pushPref("devtools.webconsole.input.editorWidth", null);
|
||||
|
||||
let hud = await openNewTabAndConsole(TEST_URI);
|
||||
const getEditorEl = () =>
|
||||
hud.ui.outputNode.querySelector(".jsterm-input-container");
|
||||
const resizerEl = hud.ui.outputNode.querySelector(".editor-resizer");
|
||||
|
||||
const editorBoundingRect = getEditorEl().getBoundingClientRect();
|
||||
const delta = 100;
|
||||
const originalWidth = editorBoundingRect.width;
|
||||
const clientX = editorBoundingRect.right + delta;
|
||||
await resize(resizerEl, clientX);
|
||||
|
||||
const newWidth = Math.floor(originalWidth + delta);
|
||||
is(
|
||||
Math.floor(getEditorEl().getBoundingClientRect().width),
|
||||
newWidth,
|
||||
"The editor element was resized as expected"
|
||||
);
|
||||
info("Close and re-open the console to check if editor width was persisted");
|
||||
await closeConsole();
|
||||
hud = await openConsole();
|
||||
|
||||
is(
|
||||
Math.floor(getEditorEl().getBoundingClientRect().width),
|
||||
newWidth,
|
||||
"The editor element width was persisted"
|
||||
);
|
||||
await toggleLayout(hud);
|
||||
|
||||
ok(!getEditorEl().style.width, "The width isn't applied in in-line layout");
|
||||
|
||||
await toggleLayout(hud);
|
||||
is(
|
||||
getEditorEl().style.width,
|
||||
`${newWidth}px`,
|
||||
"The width is applied again when switching back to editor"
|
||||
);
|
||||
}
|
||||
|
||||
async function resize(resizer, clientX) {
|
||||
const doc = resizer.ownerDocument;
|
||||
const win = doc.defaultView;
|
||||
|
||||
info("Mouse down to start dragging");
|
||||
EventUtils.synthesizeMouseAtCenter(
|
||||
resizer,
|
||||
{ button: 0, type: "mousedown" },
|
||||
win
|
||||
);
|
||||
await waitFor(() => doc.querySelector(".dragging"));
|
||||
|
||||
const event = new MouseEvent("mousemove", { clientX });
|
||||
resizer.ownerDocument.dispatchEvent(event);
|
||||
|
||||
info("Mouse up to stop resizing");
|
||||
EventUtils.synthesizeMouseAtCenter(
|
||||
doc.body,
|
||||
{ button: 0, type: "mouseup" },
|
||||
win
|
||||
);
|
||||
|
||||
await waitFor(() => !doc.querySelector(".dragging"));
|
||||
}
|
@ -29,24 +29,31 @@ async function performTest() {
|
||||
await pushPref(EDITOR_PREF, false);
|
||||
let hud = await openNewTabAndConsole(TEST_URI);
|
||||
|
||||
const INPUT_VALUE = "hello";
|
||||
setInputValue(hud, INPUT_VALUE);
|
||||
|
||||
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");
|
||||
is(getInputValue(hud), INPUT_VALUE, "The input value wasn't cleared");
|
||||
|
||||
info("Close the console and reopen it");
|
||||
await closeConsole();
|
||||
hud = await openConsole();
|
||||
is(isEditorModeEnabled(hud), true, "Editor mode is still enabled");
|
||||
setInputValue(hud, INPUT_VALUE);
|
||||
|
||||
info("Disable the editor mode");
|
||||
await toggleLayout(hud);
|
||||
is(isEditorModeEnabled(hud), false, "Editor was disabled");
|
||||
is(getInputValue(hud), INPUT_VALUE, "The input value wasn't cleared");
|
||||
|
||||
info("Enable the editor mode again");
|
||||
await toggleLayout(hud);
|
||||
is(isEditorModeEnabled(hud), true, "Editor mode was enabled again");
|
||||
is(getInputValue(hud), INPUT_VALUE, "The input value wasn't cleared");
|
||||
|
||||
Services.prefs.clearUserPref(EDITOR_PREF);
|
||||
}
|
||||
|
@ -35,6 +35,8 @@ function getPrefsService(hud) {
|
||||
Services.prefs.getIntPref(getPrefName(pref), deflt),
|
||||
setBoolPref: (pref, value) =>
|
||||
Services.prefs.setBoolPref(getPrefName(pref), value),
|
||||
setIntPref: (pref, value) =>
|
||||
Services.prefs.setIntPref(getPrefName(pref), value),
|
||||
clearUserPref: pref => Services.prefs.clearUserPref(getPrefName(pref)),
|
||||
getPrefName,
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user