feat: escape prevents automatic editor focus
This commit is contained in:
committed by
mrugesh
parent
a7c42446be
commit
95fdb74d95
@ -1,10 +1,14 @@
|
|||||||
import React, { Component, Suspense } from 'react';
|
import React, { Component, Suspense } from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { bindActionCreators } from 'redux';
|
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { createSelector } from 'reselect';
|
import { createSelector } from 'reselect';
|
||||||
|
|
||||||
import { executeChallenge, updateFile } from '../redux';
|
import {
|
||||||
|
canFocusEditorSelector,
|
||||||
|
executeChallenge,
|
||||||
|
setEditorFocusability,
|
||||||
|
updateFile
|
||||||
|
} from '../redux';
|
||||||
import { userSelector, isDonationModalOpenSelector } from '../../../redux';
|
import { userSelector, isDonationModalOpenSelector } from '../../../redux';
|
||||||
import { Loader } from '../../../components/helpers';
|
import { Loader } from '../../../components/helpers';
|
||||||
|
|
||||||
@ -18,27 +22,26 @@ const propTypes = {
|
|||||||
executeChallenge: PropTypes.func.isRequired,
|
executeChallenge: PropTypes.func.isRequired,
|
||||||
ext: PropTypes.string,
|
ext: PropTypes.string,
|
||||||
fileKey: PropTypes.string,
|
fileKey: PropTypes.string,
|
||||||
|
setEditorFocusability: PropTypes.func,
|
||||||
theme: PropTypes.string,
|
theme: PropTypes.string,
|
||||||
updateFile: PropTypes.func.isRequired
|
updateFile: PropTypes.func.isRequired
|
||||||
};
|
};
|
||||||
|
|
||||||
const mapStateToProps = createSelector(
|
const mapStateToProps = createSelector(
|
||||||
|
canFocusEditorSelector,
|
||||||
isDonationModalOpenSelector,
|
isDonationModalOpenSelector,
|
||||||
userSelector,
|
userSelector,
|
||||||
(open, { theme = 'night' }) => ({
|
(canFocus, open, { theme = 'night' }) => ({
|
||||||
canFocus: !open,
|
canFocus: open ? false : canFocus,
|
||||||
theme
|
theme
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
const mapDispatchToProps = dispatch =>
|
const mapDispatchToProps = {
|
||||||
bindActionCreators(
|
setEditorFocusability,
|
||||||
{
|
executeChallenge,
|
||||||
executeChallenge,
|
updateFile
|
||||||
updateFile
|
};
|
||||||
},
|
|
||||||
dispatch
|
|
||||||
);
|
|
||||||
|
|
||||||
const modeMap = {
|
const modeMap = {
|
||||||
css: 'css',
|
css: 'css',
|
||||||
@ -110,13 +113,15 @@ class Editor extends Component {
|
|||||||
|
|
||||||
editorDidMount = (editor, monaco) => {
|
editorDidMount = (editor, monaco) => {
|
||||||
this._editor = editor;
|
this._editor = editor;
|
||||||
if (this.props.canFocus) this._editor.focus();
|
if (this.props.canFocus) {
|
||||||
|
this._editor.focus();
|
||||||
|
} else this.focusOnHotkeys();
|
||||||
this._editor.addAction({
|
this._editor.addAction({
|
||||||
id: 'execute-challenge',
|
id: 'execute-challenge',
|
||||||
label: 'Run tests',
|
label: 'Run tests',
|
||||||
keybindings: [
|
keybindings: [
|
||||||
/* eslint-disable no-bitwise */
|
/* eslint-disable no-bitwise */
|
||||||
monaco.KeyMod.chord(monaco.KeyMod.WinCtrl | monaco.KeyCode.Enter)
|
monaco.KeyMod.chord(monaco.KeyMod.CtrlCmd | monaco.KeyCode.Enter)
|
||||||
],
|
],
|
||||||
run: this.props.executeChallenge
|
run: this.props.executeChallenge
|
||||||
});
|
});
|
||||||
@ -125,12 +130,21 @@ class Editor extends Component {
|
|||||||
label: 'Leave editor',
|
label: 'Leave editor',
|
||||||
keybindings: [monaco.KeyCode.Escape],
|
keybindings: [monaco.KeyCode.Escape],
|
||||||
run: () => {
|
run: () => {
|
||||||
if (this.props.containerRef.current)
|
this.focusOnHotkeys();
|
||||||
this.props.containerRef.current.focus();
|
this.props.setEditorFocusability(false);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
this._editor.onDidFocusEditorWidget(() =>
|
||||||
|
this.props.setEditorFocusability(true)
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
focusOnHotkeys() {
|
||||||
|
if (this.props.containerRef.current) {
|
||||||
|
this.props.containerRef.current.focus();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
onChange = editorValue => {
|
onChange = editorValue => {
|
||||||
const { updateFile, fileKey } = this.props;
|
const { updateFile, fileKey } = this.props;
|
||||||
updateFile({ key: fileKey, editorValue });
|
updateFile({ key: fileKey, editorValue });
|
||||||
|
@ -4,9 +4,9 @@ import { HotKeys, GlobalHotKeys } from 'react-hotkeys';
|
|||||||
import { navigate } from 'gatsby';
|
import { navigate } from 'gatsby';
|
||||||
|
|
||||||
const keyMap = {
|
const keyMap = {
|
||||||
EXECUTE_CHALLENGE: ['ctrl+enter'],
|
EXECUTE_CHALLENGE: ['ctrl+enter', 'command+enter'],
|
||||||
NAVIGATE_PREV: ['ctrl+left'],
|
NAVIGATE_PREV: ['p'],
|
||||||
NAVIGATE_NEXT: ['ctrl+right']
|
NAVIGATE_NEXT: ['n']
|
||||||
};
|
};
|
||||||
|
|
||||||
const propTypes = {
|
const propTypes = {
|
||||||
|
@ -18,6 +18,7 @@ export const ns = 'challenge';
|
|||||||
export const backendNS = 'backendChallenge';
|
export const backendNS = 'backendChallenge';
|
||||||
|
|
||||||
const initialState = {
|
const initialState = {
|
||||||
|
canFocusEditor: true,
|
||||||
challengeFiles: {},
|
challengeFiles: {},
|
||||||
challengeMeta: {
|
challengeMeta: {
|
||||||
id: '',
|
id: '',
|
||||||
@ -75,7 +76,9 @@ export const types = createTypes(
|
|||||||
'resetChallenge',
|
'resetChallenge',
|
||||||
'submitChallenge',
|
'submitChallenge',
|
||||||
|
|
||||||
'moveToTab'
|
'moveToTab',
|
||||||
|
|
||||||
|
'setEditorFocusability'
|
||||||
],
|
],
|
||||||
ns
|
ns
|
||||||
);
|
);
|
||||||
@ -148,6 +151,8 @@ export const submitChallenge = createAction(types.submitChallenge);
|
|||||||
|
|
||||||
export const moveToTab = createAction(types.moveToTab);
|
export const moveToTab = createAction(types.moveToTab);
|
||||||
|
|
||||||
|
export const setEditorFocusability = createAction(types.setEditorFocusability);
|
||||||
|
|
||||||
export const currentTabSelector = state => state[ns].currentTab;
|
export const currentTabSelector = state => state[ns].currentTab;
|
||||||
export const challengeFilesSelector = state => state[ns].challengeFiles;
|
export const challengeFilesSelector = state => state[ns].challengeFiles;
|
||||||
export const challengeMetaSelector = state => state[ns].challengeMeta;
|
export const challengeMetaSelector = state => state[ns].challengeMeta;
|
||||||
@ -217,6 +222,8 @@ export const challengeDataSelector = state => {
|
|||||||
return challengeData;
|
return challengeData;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const canFocusEditorSelector = state => state[ns].canFocusEditor;
|
||||||
|
|
||||||
const MAX_LOGS_SIZE = 64 * 1024;
|
const MAX_LOGS_SIZE = 64 * 1024;
|
||||||
|
|
||||||
export const reducer = handleActions(
|
export const reducer = handleActions(
|
||||||
@ -348,6 +355,10 @@ export const reducer = handleActions(
|
|||||||
[types.executeChallenge]: state => ({
|
[types.executeChallenge]: state => ({
|
||||||
...state,
|
...state,
|
||||||
currentTab: 3
|
currentTab: 3
|
||||||
|
}),
|
||||||
|
[types.setEditorFocusability]: (state, { payload }) => ({
|
||||||
|
...state,
|
||||||
|
canFocusEditor: payload
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
initialState
|
initialState
|
||||||
|
Reference in New Issue
Block a user