mirror of
https://github.com/pybricks/pybricks-code.git
synced 2026-09-12 09:36:27 +00:00
add keyboard shortcut to toggle docs
this is useful for users with small screens
This commit is contained in:
@@ -7,6 +7,7 @@ import { SettingId } from '../settings/user';
|
||||
/** Actions related to settings. */
|
||||
export enum SettingsActionType {
|
||||
SetBoolean = 'settings.action.setBoolean',
|
||||
ToggleBoolean = 'settings.action.toggleBoolean',
|
||||
DidFailToSetBoolean = 'settings.action.didFailToSetBoolean',
|
||||
DidBooleanChange = 'settings.action.didBooleanChange',
|
||||
}
|
||||
@@ -27,6 +28,16 @@ export function setBoolean(id: SettingId, newState: boolean): SettingsSetBoolean
|
||||
return { type: SettingsActionType.SetBoolean, id, newState };
|
||||
}
|
||||
|
||||
/** Action to toggle a setting. */
|
||||
export type SettingsToggleBooleanAction = Action<SettingsActionType.ToggleBoolean> & {
|
||||
id: SettingId;
|
||||
};
|
||||
|
||||
/** Creates an action to toggle a setting. */
|
||||
export function toggleBoolean(id: SettingId): SettingsToggleBooleanAction {
|
||||
return { type: SettingsActionType.ToggleBoolean, id };
|
||||
}
|
||||
|
||||
/** Action that indicates setting/storing a setting failed. */
|
||||
export type SettingsDidFailToSetBooleanAction = Action<SettingsActionType.DidFailToSetBoolean> & {
|
||||
id: SettingId;
|
||||
@@ -56,5 +67,6 @@ export function didBooleanChange(
|
||||
/** Common type for all settings actions. */
|
||||
export type SettingsAction =
|
||||
| SettingsSetBooleanAction
|
||||
| SettingsToggleBooleanAction
|
||||
| SettingsDidFailToSetBooleanAction
|
||||
| SettingsDidBooleanChangeAction;
|
||||
|
||||
@@ -17,7 +17,9 @@ import { connect } from 'react-redux';
|
||||
import { Action, Dispatch } from '../actions';
|
||||
import { setEditSession, storageChanged } from '../actions/editor';
|
||||
import { compile } from '../actions/mpy';
|
||||
import { toggleBoolean } from '../actions/settings';
|
||||
import { RootState } from '../reducers';
|
||||
import { SettingId } from '../settings/user';
|
||||
import { isMacOS } from '../utils/os';
|
||||
import { EditorStringId } from './editor-i18n';
|
||||
import en from './editor-i18n.en.json';
|
||||
@@ -34,12 +36,14 @@ import './editor.scss';
|
||||
|
||||
type StateProps = {
|
||||
darkMode: boolean;
|
||||
showDocs: boolean;
|
||||
};
|
||||
|
||||
type DispatchProps = {
|
||||
onSessionChanged: (session?: Ace.EditSession) => void;
|
||||
onProgramStorageChanged: (newValue: string) => void;
|
||||
onCheck: (script: string) => void;
|
||||
onToggleDocs: () => void;
|
||||
};
|
||||
|
||||
type EditorProps = StateProps & DispatchProps & WithI18nProps;
|
||||
@@ -78,7 +82,7 @@ class Editor extends React.Component<EditorProps> {
|
||||
}
|
||||
|
||||
render(): JSX.Element {
|
||||
const { darkMode, i18n, onSessionChanged, onCheck } = this.props;
|
||||
const { i18n, darkMode, onSessionChanged, onCheck, onToggleDocs } = this.props;
|
||||
return (
|
||||
<div className="h-100">
|
||||
<ResizeSensor onResize={(): void => this.editor?.resize()}>
|
||||
@@ -105,6 +109,13 @@ class Editor extends React.Component<EditorProps> {
|
||||
mac: 'Shift-F2',
|
||||
};
|
||||
|
||||
// we want to use Ctrl-D for docs toggle, so change
|
||||
// delete line to VSCode default
|
||||
e.commands.byName['removeline'].bindKey = {
|
||||
win: 'Ctrl-Shift-K',
|
||||
mac: 'Cmd-Shift-K',
|
||||
};
|
||||
|
||||
config.loadModule(
|
||||
'ace/ext/menu_tools/get_editor_keyboard_shortcuts',
|
||||
(m) => {
|
||||
@@ -129,6 +140,11 @@ class Editor extends React.Component<EditorProps> {
|
||||
bindKey: { win: 'F2', mac: 'F2' },
|
||||
exec: (editor) => onCheck(editor.getValue()),
|
||||
},
|
||||
{
|
||||
name: 'toggleDocs',
|
||||
bindKey: { win: 'Ctrl-D', mac: 'Cmd-D' },
|
||||
exec: () => onToggleDocs(),
|
||||
},
|
||||
{
|
||||
name: 'save',
|
||||
bindKey: { win: 'Ctrl-S', mac: 'Cmd-S' },
|
||||
@@ -202,6 +218,7 @@ class Editor extends React.Component<EditorProps> {
|
||||
|
||||
const mapStateToProps = (state: RootState): StateProps => ({
|
||||
darkMode: state.settings.darkMode,
|
||||
showDocs: state.settings.showDocs,
|
||||
});
|
||||
|
||||
const mapDispatchToProps = (dispatch: Dispatch): DispatchProps => ({
|
||||
@@ -210,6 +227,7 @@ const mapDispatchToProps = (dispatch: Dispatch): DispatchProps => ({
|
||||
// REVISIT: the options here might need to be changed - hopefully there is
|
||||
// one setting that works for all hub types for cases where we aren't connected.
|
||||
onCheck: (script) => dispatch(compile(script)),
|
||||
onToggleDocs: () => dispatch(toggleBoolean(SettingId.ShowDocs)),
|
||||
});
|
||||
|
||||
export default connect(
|
||||
|
||||
@@ -5,7 +5,12 @@
|
||||
|
||||
import { AsyncSaga } from '../../test';
|
||||
import { didStart } from '../actions/app';
|
||||
import { didBooleanChange, didFailToSetBoolean, setBoolean } from '../actions/settings';
|
||||
import {
|
||||
didBooleanChange,
|
||||
didFailToSetBoolean,
|
||||
setBoolean,
|
||||
toggleBoolean,
|
||||
} from '../actions/settings';
|
||||
import { SettingId } from '../settings/user';
|
||||
import settings from './settings';
|
||||
|
||||
@@ -345,3 +350,24 @@ describe('storage monitor', () => {
|
||||
await saga.end();
|
||||
});
|
||||
});
|
||||
|
||||
describe('toggle', () => {
|
||||
test('showDocs', async () => {
|
||||
const saga = new AsyncSaga(settings, { settings: { showDocs: false } });
|
||||
|
||||
const mockSetItem = jest
|
||||
.spyOn(Object.getPrototypeOf(window.localStorage), 'setItem')
|
||||
.mockImplementation((key, value) => {
|
||||
expect(key).toBe('setting.showDocs');
|
||||
expect(value).toBe('true');
|
||||
});
|
||||
|
||||
saga.put(toggleBoolean(SettingId.ShowDocs));
|
||||
expect(mockSetItem).toHaveBeenCalled();
|
||||
|
||||
const action = await saga.take();
|
||||
expect(action).toEqual(didBooleanChange(SettingId.ShowDocs, true));
|
||||
|
||||
await saga.end();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -11,8 +11,10 @@ import { AppActionType } from '../actions/app';
|
||||
import {
|
||||
SettingsActionType,
|
||||
SettingsSetBooleanAction,
|
||||
SettingsToggleBooleanAction,
|
||||
didBooleanChange,
|
||||
didFailToSetBoolean,
|
||||
setBoolean,
|
||||
} from '../actions/settings';
|
||||
import { RootState } from '../reducers';
|
||||
import { SettingId, getDefaultBooleanValue } from '../settings/user';
|
||||
@@ -97,8 +99,14 @@ function* storeSetting(action: SettingsSetBooleanAction): Generator {
|
||||
}
|
||||
}
|
||||
|
||||
function* toggleSetting(action: SettingsToggleBooleanAction): Generator {
|
||||
const oldValue = yield* select((s: RootState) => s.settings[action.id]);
|
||||
yield* storeSetting(setBoolean(action.id, !oldValue));
|
||||
}
|
||||
|
||||
export default function* (): Generator {
|
||||
yield* fork(monitorLocalStorage);
|
||||
yield* takeEvery(AppActionType.DidStart, loadSettings);
|
||||
yield* takeEvery(SettingsActionType.SetBoolean, storeSetting);
|
||||
yield* takeEvery(SettingsActionType.ToggleBoolean, toggleSetting);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user