1
0
mirror of https://github.com/lensapp/lens.git synced 2025-05-20 05:10:56 +00:00

fix: apply global editor settings from app preferences

Signed-off-by: Roman <ixrock@gmail.com>
This commit is contained in:
Roman 2021-10-06 16:33:07 +03:00
parent c4aa88183f
commit e66ed4709b
4 changed files with 57 additions and 45 deletions

View File

@ -24,27 +24,26 @@ import path from "path";
import os from "os"; import os from "os";
import { ThemeStore } from "../../renderer/theme.store"; import { ThemeStore } from "../../renderer/theme.store";
import { ObservableToggleSet } from "../utils"; import { ObservableToggleSet } from "../utils";
import type * as monaco from "monaco-editor"; import type { editor } from "monaco-editor";
import merge from "lodash/merge"; import merge from "lodash/merge";
export interface KubeconfigSyncEntry extends KubeconfigSyncValue { export interface KubeconfigSyncEntry extends KubeconfigSyncValue {
filePath: string; filePath: string;
} }
export interface KubeconfigSyncValue { } export interface KubeconfigSyncValue {
export interface EditorConfiguration {
miniMap: monaco.editor.IEditorMinimapOptions;
lineNumbers: monaco.editor.LineNumbersType;
tabSize: number;
} }
export type EditorConfiguration = Pick<editor.IStandaloneEditorConstructionOptions,
"minimap" | "tabSize" | "lineNumbers">;
export const defaultEditorConfig: EditorConfiguration = { export const defaultEditorConfig: EditorConfiguration = {
tabSize: 2,
lineNumbers: "on", lineNumbers: "on",
miniMap: { minimap: {
enabled: true enabled: true,
side: "right",
}, },
tabSize: 2
}; };
interface PreferenceDescription<T, R = T> { interface PreferenceDescription<T, R = T> {

View File

@ -20,12 +20,13 @@
*/ */
import { observer } from "mobx-react"; import { observer } from "mobx-react";
import React from "react"; import React from "react";
import type { editor } from "monaco-editor";
import { UserStore } from "../../../common/user-store"; import { UserStore } from "../../../common/user-store";
import { FormSwitch, Switcher } from "../switch"; import { Switcher } from "../switch";
import { SubTitle } from "../layout/sub-title";
import { Input } from "../input";
import { isNumber } from "../input/input_validators";
import { Select } from "../select"; import { Select } from "../select";
import { SubTitle } from "../layout/sub-title";
import { SubHeader } from "../layout/sub-header";
import { Input, InputValidators } from "../input";
enum EditorLineNumbersStyles { enum EditorLineNumbersStyles {
on = "On", on = "On",
@ -40,18 +41,29 @@ export const Editor = observer(() => {
return ( return (
<section id="editor"> <section id="editor">
<h2 data-testid="editor-configuration-header">Editor configuration</h2> <h2 data-testid="editor-configuration-header">Editor configuration</h2>
<SubTitle title="Minimap"/>
<section> <section>
<FormSwitch <div className="flex gaps justify-space-between">
control={ <div className="flex gaps align-center">
<SubHeader compact>Show minimap</SubHeader>
<Switcher <Switcher
checked={editorConfiguration.miniMap.enabled} checked={editorConfiguration.minimap.enabled}
onChange={(evt, checked) => editorConfiguration.miniMap.enabled = checked} onChange={(evt, checked) => editorConfiguration.minimap.enabled = checked}
name="minimap"
/> />
} </div>
label="Show minimap" <div className="flex gaps align-center">
/> <SubHeader compact>Position</SubHeader>
<Select
themeName="lens"
options={["left", "right"] as editor.IEditorMinimapOptions["side"][]}
value={editorConfiguration.minimap.side}
onChange={({ value }) => editorConfiguration.minimap.side = value}
/>
</div>
</div>
</section> </section>
<section> <section>
<SubTitle title="Line numbers"/> <SubTitle title="Line numbers"/>
<Select <Select
@ -61,14 +73,14 @@ export const Editor = observer(() => {
themeName="lens" themeName="lens"
/> />
</section> </section>
<section> <section>
<SubTitle title="Tab size"/> <SubTitle title="Tab size"/>
<Input <Input
theme="round-black" theme="round-black"
min={1}
max={10}
type="number" type="number"
validators={[isNumber]} min={1}
validators={InputValidators.isNumber}
value={editorConfiguration.tabSize.toString()} value={editorConfiguration.tabSize.toString()}
onChange={value => editorConfiguration.tabSize = Number(value)} onChange={value => editorConfiguration.tabSize = Number(value)}
/> />

View File

@ -63,6 +63,10 @@
} }
} }
input[type=number]::-webkit-inner-spin-button {
-webkit-appearance: none; // hide browser controls (top/bottom arrows)
}
input, textarea { input, textarea {
background: none; background: none;
color: inherit; color: inherit;

View File

@ -36,7 +36,7 @@ export interface MonacoEditorProps {
readOnly?: boolean; readOnly?: boolean;
theme?: "vs" /* default, light theme */ | "vs-dark" | "hc-black" | string; theme?: "vs" /* default, light theme */ | "vs-dark" | "hc-black" | string;
language?: "yaml" | "json"; // configure bundled list of languages in via MonacoWebpackPlugin({languages: []}) language?: "yaml" | "json"; // configure bundled list of languages in via MonacoWebpackPlugin({languages: []})
options?: editor.IStandaloneEditorConstructionOptions; // customize editor's initialization options options?: Partial<editor.IStandaloneEditorConstructionOptions>; // customize editor's initialization options
onChange?: onChangeCallback; onChange?: onChangeCallback;
onError?: onErrorCallback; onError?: onErrorCallback;
onDidLayoutChange?(info: editor.EditorLayoutInfo): void; onDidLayoutChange?(info: editor.EditorLayoutInfo): void;
@ -55,10 +55,7 @@ export interface onErrorCallback {
} }
export const defaultEditorProps: Partial<MonacoEditorProps> = { export const defaultEditorProps: Partial<MonacoEditorProps> = {
value: "",
options: {},
language: "yaml", language: "yaml",
autoFocus: false,
get theme(): MonacoEditorProps["theme"] { get theme(): MonacoEditorProps["theme"] {
// theme for monaco-editor defined in `src/renderer/themes/lens-*.json` // theme for monaco-editor defined in `src/renderer/themes/lens-*.json`
return ThemeStore.getInstance().activeTheme.monacoTheme; return ThemeStore.getInstance().activeTheme.monacoTheme;
@ -71,7 +68,7 @@ export class MonacoEditor extends React.Component<MonacoEditorProps> {
static viewStates = new WeakMap<editor.ITextModel, editor.ICodeEditorViewState>(); static viewStates = new WeakMap<editor.ITextModel, editor.ICodeEditorViewState>();
public staticId = `editor-id#${Math.round(1e7 * Math.random())}`; public staticId = `editor-id#${Math.round(1e7 * Math.random())}`;
public disposeOnUnmount = disposer(); public dispose = disposer();
@observable.ref containerElem: HTMLElement; @observable.ref containerElem: HTMLElement;
@observable.ref editor: editor.IStandaloneCodeEditor; @observable.ref editor: editor.IStandaloneCodeEditor;
@ -83,6 +80,13 @@ export class MonacoEditor extends React.Component<MonacoEditorProps> {
makeObservable(this); makeObservable(this);
} }
@computed get options(): editor.IStandaloneEditorConstructionOptions {
return toJS({
...UserStore.getInstance().editorConfiguration,
...(this.props.options ?? {}),
});
}
/** /**
* Monitor editor's dom container element box-size and sync with monaco's dimensions * Monitor editor's dom container element box-size and sync with monaco's dimensions
* @private * @private
@ -135,21 +139,15 @@ export class MonacoEditor extends React.Component<MonacoEditorProps> {
} }
componentWillUnmount() { componentWillUnmount() {
try { this.unmounting = true;
console.info(`[MONACO]: unmounting editor..`); this.destroy();
this.unmounting = true;
this.destroyEditor();
} catch (error) {
console.error(`[MONACO]: unmounting error failed: ${String(error)}`, this, error);
}
} }
private createEditor() { private createEditor() {
if (!this.containerElem || this.editor || this.unmounting) { if (!this.containerElem || this.editor || this.unmounting) {
return; return;
} }
const { language, theme, readOnly, value: defaultValue, options } = this.props; const { language, theme, readOnly, value: defaultValue } = this.props;
const globalEditorOptions = toJS(UserStore.getInstance().editorConfiguration);
this.editor = editor.create(this.containerElem, { this.editor = editor.create(this.containerElem, {
model: this.model, model: this.model,
@ -157,8 +155,7 @@ export class MonacoEditor extends React.Component<MonacoEditorProps> {
language, language,
theme, theme,
readOnly, readOnly,
...globalEditorOptions, ...this.options,
...options,
}); });
console.info(`[MONACO]: editor created for language=${language}, theme=${theme}`); console.info(`[MONACO]: editor created for language=${language}, theme=${theme}`);
@ -182,11 +179,11 @@ export class MonacoEditor extends React.Component<MonacoEditorProps> {
// console.info("[MONACO]: onDidContentSizeChange():", params) // console.info("[MONACO]: onDidContentSizeChange():", params)
}); });
this.disposeOnUnmount.push( this.dispose.push(
reaction(() => this.model, this.onModelChange), reaction(() => this.model, this.onModelChange),
reaction(() => this.props.theme, editor.setTheme), reaction(() => this.props.theme, editor.setTheme),
reaction(() => this.props.value, value => this.setValue(value)), reaction(() => this.props.value, value => this.setValue(value)),
reaction(() => toJS(this.props.options), opts => this.editor.updateOptions(opts)), reaction(() => this.options, opts => this.editor.updateOptions(opts)),
() => onDidLayoutChangeDisposer.dispose(), () => onDidLayoutChangeDisposer.dispose(),
() => onValueChangeDisposer.dispose(), () => onValueChangeDisposer.dispose(),
@ -195,12 +192,12 @@ export class MonacoEditor extends React.Component<MonacoEditorProps> {
); );
} }
private destroyEditor(): void { destroy(): void {
if (!this.editor) return; if (!this.editor) return;
this.dispose();
this.editor.dispose(); this.editor.dispose();
this.editor = null; this.editor = null;
this.disposeOnUnmount();
} }
@action @action