mirror of
https://gitcode.com/gh_mirrors/hy/Hydro.git
synced 2026-10-20 09:46:28 +08:00
ui: add editor setting (#622)
This commit is contained in:
1 parent
3615d13ce2
commit
2dabe3194e
4 files changed
+100
-1
No files matched your search
@@ -8,11 +8,16 @@ interface ScratchpadOptions {
|
|||||||
value?: string;
|
value?: string;
|
||||||
language?: string;
|
language?: string;
|
||||||
handleUpdateCode?: (str: string, event: monaco.editor.IModelContentChangedEvent) => void;
|
handleUpdateCode?: (str: string, event: monaco.editor.IModelContentChangedEvent) => void;
|
||||||
|
settings?: any;
|
||||||
|
pendingCommand?: string;
|
||||||
|
commandDone?: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default connect((state: any) => ({
|
export default connect((state: any) => ({
|
||||||
value: state.editor.code,
|
value: state.editor.code,
|
||||||
language: window.LANGS[state.editor.lang]?.monaco,
|
language: window.LANGS[state.editor.lang]?.monaco,
|
||||||
|
settings: state.ui.settings.config,
|
||||||
|
pendingCommand: state.ui.pendingCommand,
|
||||||
}), (dispatch) => ({
|
}), (dispatch) => ({
|
||||||
handleUpdateCode: (code: string) => {
|
handleUpdateCode: (code: string) => {
|
||||||
dispatch({
|
dispatch({
|
||||||
@@ -20,6 +25,12 @@ export default connect((state: any) => ({
|
|||||||
payload: code,
|
payload: code,
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
commandDone: () => {
|
||||||
|
dispatch({
|
||||||
|
type: 'SCRATCHPAD_TRIGGER_EDITOR_COMMAND',
|
||||||
|
payload: { command: '' },
|
||||||
|
});
|
||||||
|
},
|
||||||
}))(class MonacoEditor extends React.PureComponent<ScratchpadOptions> {
|
}))(class MonacoEditor extends React.PureComponent<ScratchpadOptions> {
|
||||||
disposable: monaco.IDisposable[] = [];
|
disposable: monaco.IDisposable[] = [];
|
||||||
__prevent_trigger_change_event = false;
|
__prevent_trigger_change_event = false;
|
||||||
@@ -36,8 +47,8 @@ export default connect((state: any) => ({
|
|||||||
if (this.containerElement) {
|
if (this.containerElement) {
|
||||||
const config: monaco.editor.IStandaloneEditorConstructionOptions = {
|
const config: monaco.editor.IStandaloneEditorConstructionOptions = {
|
||||||
theme: 'vs-light',
|
theme: 'vs-light',
|
||||||
...customOptions,
|
|
||||||
fontFamily: UserContext.codeFontFamily,
|
fontFamily: UserContext.codeFontFamily,
|
||||||
|
...customOptions,
|
||||||
lineNumbers: 'on',
|
lineNumbers: 'on',
|
||||||
glyphMargin: true,
|
glyphMargin: true,
|
||||||
lightbulb: { enabled: true },
|
lightbulb: { enabled: true },
|
||||||
@@ -88,6 +99,14 @@ export default connect((state: any) => ({
|
|||||||
this.model = monaco.editor.getModel(uri) || monaco.editor.createModel(val, language, uri);
|
this.model = monaco.editor.getModel(uri) || monaco.editor.createModel(val, language, uri);
|
||||||
editor.setModel(this.model);
|
editor.setModel(this.model);
|
||||||
}
|
}
|
||||||
|
if (editor && this.props.settings) {
|
||||||
|
editor.updateOptions(this.props.settings);
|
||||||
|
}
|
||||||
|
if (this.props.pendingCommand) {
|
||||||
|
editor.focus();
|
||||||
|
editor.getAction(this.props.pendingCommand)?.run();
|
||||||
|
this.props.commandDone();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillUnmount() {
|
componentWillUnmount() {
|
||||||
|
|||||||
@@ -0,0 +1,48 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { useDispatch, useSelector } from 'react-redux';
|
||||||
|
import { i18n } from 'vj/utils';
|
||||||
|
import { RootState } from './reducers';
|
||||||
|
|
||||||
|
export default function ScratchpadSettings() {
|
||||||
|
const config = useSelector((state: RootState) => state.ui.settings.config);
|
||||||
|
const parsed = React.useMemo(() => {
|
||||||
|
const settings = { fontSize: 14, tabSize: 4 };
|
||||||
|
try {
|
||||||
|
Object.assign(settings, config);
|
||||||
|
} catch (e) { }
|
||||||
|
return settings;
|
||||||
|
}, [config]);
|
||||||
|
const dispatch = useDispatch();
|
||||||
|
function dispatcher(setting: string, numeric = false) {
|
||||||
|
return (ev) => {
|
||||||
|
const val = ev?.target?.value || ev;
|
||||||
|
dispatch({ type: 'SCRATCHPAD_SETTING_UPDATE', payload: { setting, value: numeric ? +val : val } });
|
||||||
|
};
|
||||||
|
}
|
||||||
|
function openThemeSelect() {
|
||||||
|
dispatch({ type: 'SCRATCHPAD_TRIGGER_EDITOR_COMMAND', payload: { command: 'hydro.changeEditorTheme' } });
|
||||||
|
}
|
||||||
|
// TODO update style
|
||||||
|
return <div>
|
||||||
|
<div className="row"><div className="medium-6 columns">
|
||||||
|
<label>
|
||||||
|
{i18n('Font size')}:
|
||||||
|
<div className="textbox-container">
|
||||||
|
<input type="number" step="1" value={parsed.fontSize} onChange={dispatcher('fontSize', true)} className="textbox" />
|
||||||
|
</div>
|
||||||
|
</label>
|
||||||
|
</div></div>
|
||||||
|
<div className="row"><div className="medium-6 columns">
|
||||||
|
<label>
|
||||||
|
{i18n('Tab size')}:
|
||||||
|
<div className="textbox-container">
|
||||||
|
<input type="number" step="1" value={parsed.tabSize} onChange={dispatcher('tabSize', true)} className="textbox" />
|
||||||
|
</div>
|
||||||
|
</label>
|
||||||
|
</div></div>
|
||||||
|
<div className="row"><div className="columns">
|
||||||
|
<p>{i18n('Theme')}: </p>
|
||||||
|
<button className="rounded primary button" onClick={openThemeSelect}>{i18n('Open theme select')}</button>
|
||||||
|
</div></div>
|
||||||
|
</div>;
|
||||||
|
}
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
import ProblemIcon from '@vscode/codicons/src/icons/file.svg?react';
|
import ProblemIcon from '@vscode/codicons/src/icons/file.svg?react';
|
||||||
|
import SettingsIcon from '@vscode/codicons/src/icons/settings-gear.svg?react';
|
||||||
import { Allotment } from 'allotment';
|
import { Allotment } from 'allotment';
|
||||||
import $ from 'jquery';
|
import $ from 'jquery';
|
||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
@@ -10,6 +11,7 @@ import { Context, ctx, Service } from 'vj/context';
|
|||||||
import ScratchpadEditor from './ScratchpadEditorContainer';
|
import ScratchpadEditor from './ScratchpadEditorContainer';
|
||||||
import ScratchpadPretest from './ScratchpadPretestContainer';
|
import ScratchpadPretest from './ScratchpadPretestContainer';
|
||||||
import ScratchpadRecords from './ScratchpadRecordsContainer';
|
import ScratchpadRecords from './ScratchpadRecordsContainer';
|
||||||
|
import ScratchpadSettings from './ScratchpadSettings';
|
||||||
import ScratchpadToolbar from './ScratchpadToolbarContainer';
|
import ScratchpadToolbar from './ScratchpadToolbarContainer';
|
||||||
|
|
||||||
const pages = {
|
const pages = {
|
||||||
@@ -17,6 +19,10 @@ const pages = {
|
|||||||
icon: () => <ProblemIcon />,
|
icon: () => <ProblemIcon />,
|
||||||
component: () => <Dom childDom={$('.problem-content').get(0)} />,
|
component: () => <Dom childDom={$('.problem-content').get(0)} />,
|
||||||
},
|
},
|
||||||
|
settings: {
|
||||||
|
icon: () => <SettingsIcon />,
|
||||||
|
component: () => <ScratchpadSettings />,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
let rerenderCallback = null;
|
let rerenderCallback = null;
|
||||||
|
|||||||
@@ -11,11 +11,16 @@ export default function reducer(state = {
|
|||||||
visible: UiContext.canViewRecord && localStorage.getItem('scratchpad/records') === 'true',
|
visible: UiContext.canViewRecord && localStorage.getItem('scratchpad/records') === 'true',
|
||||||
isLoading: false,
|
isLoading: false,
|
||||||
},
|
},
|
||||||
|
settings: {
|
||||||
|
visible: false,
|
||||||
|
config: JSON.parse(localStorage.getItem('editor.config') || '{}'),
|
||||||
|
},
|
||||||
isPosting: false,
|
isPosting: false,
|
||||||
pretestWaitSec: 0,
|
pretestWaitSec: 0,
|
||||||
submitWaitSec: 0,
|
submitWaitSec: 0,
|
||||||
lastTick: 0,
|
lastTick: 0,
|
||||||
activePage: 'problem',
|
activePage: 'problem',
|
||||||
|
pendingCommand: '',
|
||||||
}, action: any = {}) {
|
}, action: any = {}) {
|
||||||
switch (action.type) {
|
switch (action.type) {
|
||||||
case 'SCRATCHPAD_UI_SET_VISIBILITY': {
|
case 'SCRATCHPAD_UI_SET_VISIBILITY': {
|
||||||
@@ -40,6 +45,27 @@ export default function reducer(state = {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
case 'SCRATCHPAD_SETTING_UPDATE': {
|
||||||
|
const { setting, value } = action.payload;
|
||||||
|
const config = {
|
||||||
|
...state.settings.config,
|
||||||
|
[setting]: value,
|
||||||
|
};
|
||||||
|
localStorage.setItem('editor.config', JSON.stringify(config));
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
settings: {
|
||||||
|
...state.settings,
|
||||||
|
config,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
case 'SCRATCHPAD_TRIGGER_EDITOR_COMMAND': {
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
pendingCommand: action.payload.command,
|
||||||
|
};
|
||||||
|
}
|
||||||
case 'SCRATCHPAD_POST_PRETEST_PENDING':
|
case 'SCRATCHPAD_POST_PRETEST_PENDING':
|
||||||
case 'SCRATCHPAD_POST_SUBMIT_PENDING': {
|
case 'SCRATCHPAD_POST_SUBMIT_PENDING': {
|
||||||
return {
|
return {
|
||||||
|
|||||||
Reference in new issue
Block a user