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

Font settings for editor and ternimal (#4694)

* Add font settings for editor. Add terminal tab

Signed-off-by: DMYTRO ZHARKOV <dmytrozharkov@DMYTROs-MBP.fritz.box>

* Move shell settings to terminal tab

Signed-off-by: DMYTRO ZHARKOV <dmytrozharkov@DMYTROs-MBP.fritz.box>

* Add termilan font settings to store

Signed-off-by: DMYTRO ZHARKOV <dmytrozharkov@DMYTROs-MBP.fritz.box>

* Fix store crash

Signed-off-by: DMYTRO ZHARKOV <dmytrozharkov@DMYTROs-MBP.fritz.box>

* Cleanup

Signed-off-by: DMYTRO ZHARKOV <dmytrozharkov@DMYTROs-MBP.fritz.box>

* Remove unsued font-list

Signed-off-by: DMYTRO ZHARKOV <dmytrozharkov@DMYTROs-MBP.fritz.box>

* Cleanup. Move default font size to a const

Signed-off-by: DMYTRO ZHARKOV <dmytrozharkov@DMYTROs-MBP.fritz.box>

* Remove package.lock

Signed-off-by: DMYTRO ZHARKOV <dmytrozharkov@DMYTROs-MBP.fritz.box>

* PR fixes and cleanup

Signed-off-by: DMYTRO ZHARKOV <dmytrozharkov@DMYTROs-MBP.fritz.box>

* Move to settings object

Signed-off-by: DMYTRO ZHARKOV <dmytrozharkov@DMYTROs-MBP.fritz.box>

* Test

Signed-off-by: DMYTRO ZHARKOV <dmytrozharkov@DMYTROs-MBP.fritz.box>

* Add reaction to update terminals. Cleanup

Signed-off-by: DMYTRO ZHARKOV <dmytrozharkov@DMYTROs-MBP.fritz.box>

* Add config field to terminal

Signed-off-by: DMYTRO ZHARKOV <dmytrozharkov@DMYTROs-MBP.fritz.box>

* Merge with master and resolve conflicts

Signed-off-by: DMYTRO ZHARKOV <dmytrozharkov@DMYTROs-MBP.fritz.box>

* Fix merge issues

Signed-off-by: DMYTRO ZHARKOV <dmytrozharkov@DMYTROs-MBP.fritz.box>

* Fix lint and resolve conflicts

Signed-off-by: DMYTRO ZHARKOV <dmytrozharkov@DMYTROs-MBP.fritz.box>

Co-authored-by: DMYTRO ZHARKOV <dmytrozharkov@DMYTROs-MBP.fritz.box>
This commit is contained in:
Dmitriy Noa 2022-01-21 09:18:53 +01:00 committed by GitHub
parent 6cba82c491
commit b7d29f8c49
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 165 additions and 55 deletions

View File

@ -34,6 +34,9 @@ export const extensionRoute: RouteProps = {
path: `${preferencesRoute.path}/extensions`,
};
export const terminalRoute: RouteProps = {
path: `${preferencesRoute.path}/terminal`,
};
export const preferencesURL = buildURL(preferencesRoute.path);
export const appURL = buildURL(appRoute.path);
export const proxyURL = buildURL(proxyRoute.path);
@ -41,3 +44,4 @@ export const kubernetesURL = buildURL(kubernetesRoute.path);
export const editorURL = buildURL(editorRoute.path);
export const telemetryURL = buildURL(telemetryRoute.path);
export const extensionURL = buildURL(extensionRoute.path);
export const terminalURL = buildURL(terminalRoute.path);

View File

@ -10,7 +10,7 @@ import { getAppVersion, ObservableToggleSet } from "../utils";
import type { editor } from "monaco-editor";
import merge from "lodash/merge";
import { SemVer } from "semver";
import { defaultTheme } from "../vars";
import { defaultTheme, defaultEditorFontFamily, defaultFontSize, defaultTerminalFontFamily } from "../vars";
export interface KubeconfigSyncEntry extends KubeconfigSyncValue {
filePath: string;
@ -18,19 +18,29 @@ export interface KubeconfigSyncEntry extends KubeconfigSyncValue {
export interface KubeconfigSyncValue {
}
export interface TerminalConfig {
fontSize: number;
fontFamily: string;
}
export const defaultTerminalConfig: TerminalConfig = {
fontSize: defaultFontSize,
fontFamily: defaultTerminalFontFamily,
};
export type EditorConfiguration = Pick<editor.IStandaloneEditorConstructionOptions,
"minimap" | "tabSize" | "lineNumbers">;
"minimap" | "tabSize" | "lineNumbers" | "fontSize" | "fontFamily">;
export const defaultEditorConfig: EditorConfiguration = {
tabSize: 2,
lineNumbers: "on",
fontSize: defaultFontSize,
fontFamily: defaultEditorFontFamily,
minimap: {
enabled: true,
side: "right",
},
};
interface PreferenceDescription<T, R = T> {
fromStore(val: T | undefined): R;
toStore(val: R): T | undefined;
@ -273,6 +283,15 @@ const editorConfiguration: PreferenceDescription<EditorConfiguration, EditorConf
},
};
const terminalConfig: PreferenceDescription<TerminalConfig, TerminalConfig> = {
fromStore(val) {
return merge(defaultTerminalConfig, val);
},
toStore(val) {
return val;
},
};
const updateChannels = new Map([
["latest", {
label: "Stable",
@ -358,6 +377,7 @@ export const DESCRIPTORS = {
syncKubeconfigEntries,
editorConfiguration,
terminalCopyOnSelect,
terminalConfig,
updateChannel,
extensionRegistryUrl,
};

View File

@ -12,7 +12,7 @@ import { getAppVersion } from "../utils/app-version";
import { kubeConfigDefaultPath } from "../kube-helpers";
import { appEventBus } from "../app-event-bus/event-bus";
import { ObservableToggleSet, toJS } from "../../renderer/utils";
import { DESCRIPTORS, EditorConfiguration, ExtensionRegistry, KubeconfigSyncValue, UserPreferencesModel } from "./preferences-helpers";
import { DESCRIPTORS, EditorConfiguration, ExtensionRegistry, KubeconfigSyncValue, UserPreferencesModel, TerminalConfig } from "./preferences-helpers";
import logger from "../../main/logger";
export interface UserStoreModel {
@ -57,6 +57,7 @@ export class UserStore extends BaseStore<UserStoreModel> /* implements UserStore
@observable downloadBinariesPath?: string;
@observable kubectlBinariesPath?: string;
@observable terminalCopyOnSelect: boolean;
@observable terminalConfig: TerminalConfig;
@observable updateChannel?: string;
@observable extensionRegistryUrl: ExtensionRegistry;
@ -185,6 +186,7 @@ export class UserStore extends BaseStore<UserStoreModel> /* implements UserStore
this.syncKubeconfigEntries.replace(DESCRIPTORS.syncKubeconfigEntries.fromStore(preferences?.syncKubeconfigEntries));
this.editorConfiguration = DESCRIPTORS.editorConfiguration.fromStore(preferences?.editorConfiguration);
this.terminalCopyOnSelect = DESCRIPTORS.terminalCopyOnSelect.fromStore(preferences?.terminalCopyOnSelect);
this.terminalConfig = DESCRIPTORS.terminalConfig.fromStore(preferences?.terminalConfig);
this.updateChannel = DESCRIPTORS.updateChannel.fromStore(preferences?.updateChannel);
this.extensionRegistryUrl = DESCRIPTORS.extensionRegistryUrl.fromStore(preferences?.extensionRegistryUrl);
}
@ -210,6 +212,7 @@ export class UserStore extends BaseStore<UserStoreModel> /* implements UserStore
syncKubeconfigEntries: DESCRIPTORS.syncKubeconfigEntries.toStore(this.syncKubeconfigEntries),
editorConfiguration: DESCRIPTORS.editorConfiguration.toStore(this.editorConfiguration),
terminalCopyOnSelect: DESCRIPTORS.terminalCopyOnSelect.toStore(this.terminalCopyOnSelect),
terminalConfig: DESCRIPTORS.terminalConfig.toStore(this.terminalConfig),
updateChannel: DESCRIPTORS.updateChannel.toStore(this.updateChannel),
extensionRegistryUrl: DESCRIPTORS.extensionRegistryUrl.toStore(this.extensionRegistryUrl),
},

View File

@ -26,6 +26,9 @@ export const productName = packageInfo.productName;
export const appName = `${packageInfo.productName}${isDevelopment ? "Dev" : ""}`;
export const publicPath = "/build/" as string;
export const defaultTheme = "lens-dark" as string;
export const defaultFontSize = 12;
export const defaultTerminalFontFamily = "RobotoMono";
export const defaultEditorFontFamily = "RobotoMono";
// Webpack build paths
export const contextDir = process.cwd();

View File

@ -10,7 +10,6 @@ import { Select, SelectOption } from "../select";
import { ThemeStore } from "../../theme.store";
import { UserStore } from "../../../common/user-store";
import { Input } from "../input";
import { isWindows } from "../../../common/vars";
import { Switch } from "../switch";
import moment from "moment-timezone";
import { CONSTANTS, defaultExtensionRegistryUrl, ExtensionRegistryLocation } from "../../../common/user-store/preferences-helpers";
@ -36,16 +35,7 @@ interface Dependencies {
const NonInjectedApplication: React.FC<Dependencies> = ({ appPreferenceItems }) => {
const userStore = UserStore.getInstance();
const defaultShell = process.env.SHELL
|| process.env.PTYSHELL
|| (
isWindows
? "powershell.exe"
: "System default shell"
);
const [customUrl, setCustomUrl] = React.useState(userStore.extensionRegistryUrl.customUrl || "");
const [shell, setShell] = React.useState(userStore.shell || "");
const extensionSettings = appPreferenceItems.get().filter((preference) => preference.showInPreferencesTab === "application");
const themeStore = ThemeStore.getInstance();
@ -62,43 +52,7 @@ const NonInjectedApplication: React.FC<Dependencies> = ({ appPreferenceItems })
/>
</section>
<hr />
<section id="terminalTheme">
<SubTitle title="Terminal theme" />
<Select
themeName="lens"
options={[
{ label: "Match theme", value: "" },
...themeStore.themeOptions,
]}
value={userStore.terminalTheme}
onChange={({ value }) => userStore.terminalTheme = value}
/>
</section>
<section id="shell">
<SubTitle title="Terminal Shell Path" />
<Input
theme="round-black"
placeholder={defaultShell}
value={shell}
onChange={setShell}
onBlur={() => userStore.shell = shell}
/>
</section>
<section id="terminalSelection">
<SubTitle title="Terminal copy & paste" />
<Switch
checked={userStore.terminalCopyOnSelect}
onChange={() => userStore.terminalCopyOnSelect = !userStore.terminalCopyOnSelect}
>
Copy on select and paste on right-click
</Switch>
</section>
<hr />
<hr/>
<section id="extensionRegistryUrl">
<SubTitle title="Extension Install Registry" />

View File

@ -69,6 +69,27 @@ export const Editor = observer(() => {
onChange={value => editorConfiguration.tabSize = Number(value)}
/>
</section>
<section>
<SubTitle title="Font size"/>
<Input
theme="round-black"
type="number"
min={10}
validators={InputValidators.isNumber}
value={editorConfiguration.fontSize.toString()}
onChange={value => editorConfiguration.fontSize = Number(value)}
/>
</section>
<section>
<SubTitle title="Font family"/>
<Input
theme="round-black"
type="text"
validators={InputValidators.isNumber}
value={editorConfiguration.fontFamily}
onChange={value => editorConfiguration.fontFamily = value}
/>
</section>
</section>
);
});

View File

@ -22,6 +22,8 @@ import {
editorRoute,
telemetryRoute,
telemetryURL,
terminalRoute,
terminalURL,
} from "../../../common/routes";
import { navigateWithoutHistoryChange, navigation } from "../../navigation";
import { SettingLayout } from "../layout/setting-layout";
@ -29,6 +31,7 @@ import { Tab, Tabs } from "../tabs";
import { Application } from "./application";
import { Kubernetes } from "./kubernetes";
import { Editor } from "./editor";
import { Terminal } from "./terminal";
import { LensProxy } from "./proxy";
import { Telemetry } from "./telemetry";
import { Extensions } from "./extensions";
@ -56,6 +59,7 @@ const NonInjectedPreferences: React.FC<Dependencies> = ({ appPreferenceItems })
<Tab value={proxyURL()} label="Proxy" data-testid="proxy-tab" active={isActive(proxyRoute)}/>
<Tab value={kubernetesURL()} label="Kubernetes" data-testid="kubernetes-tab" active={isActive(kubernetesRoute)}/>
<Tab value={editorURL()} label="Editor" data-testid="editor-tab" active={isActive(editorRoute)}/>
<Tab value={terminalURL()} label="Terminal" data-testid="terminal-tab" active={isActive(terminalRoute)}/>
{(telemetryExtensions.length > 0 || !!sentryDsn) &&
<Tab value={telemetryURL()} label="Telemetry" data-testid="telemetry-tab" active={isActive(telemetryRoute)}/>
}
@ -77,6 +81,7 @@ const NonInjectedPreferences: React.FC<Dependencies> = ({ appPreferenceItems })
<Route path={proxyURL()} component={LensProxy}/>
<Route path={kubernetesURL()} component={Kubernetes}/>
<Route path={editorURL()} component={Editor}/>
<Route path={terminalURL()} component={Terminal}/>
<Route path={telemetryURL()} component={Telemetry}/>
<Route path={extensionURL()} component={Extensions}/>
<Redirect exact from={`${preferencesURL()}/`} to={appURL()}/>

View File

@ -0,0 +1,82 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import React from "react";
import { observer } from "mobx-react";
import { UserStore } from "../../../common/user-store";
import { SubTitle } from "../layout/sub-title";
import { Input, InputValidators } from "../input";
import { isWindows } from "../../../common/vars";
import { Switch } from "../switch";
import { Select } from "../select";
import { ThemeStore } from "../../theme.store";
export const Terminal = observer(() => {
const userStore = UserStore.getInstance();
const themeStore = ThemeStore.getInstance();
const defaultShell = process.env.SHELL
|| process.env.PTYSHELL
|| (
isWindows
? "powershell.exe"
: "System default shell"
);
return (<div>
<section id="shell">
<SubTitle title="Terminal Shell Path"/>
<Input
theme="round-black"
placeholder={defaultShell}
value={userStore.shell}
onChange={(value) => userStore.shell = value}
/>
</section>
<section id="terminalSelection">
<SubTitle title="Terminal copy & paste" />
<Switch
checked={userStore.terminalCopyOnSelect}
onChange={() => userStore.terminalCopyOnSelect = !userStore.terminalCopyOnSelect}
>
Copy on select and paste on right-click
</Switch>
</section>
<section id="terminalTheme">
<SubTitle title="Terminal theme" />
<Select
themeName="lens"
options={[
{ label: "Match theme", value: "" },
...themeStore.themeOptions,
]}
value={userStore.terminalTheme}
onChange={({ value }) => userStore.terminalTheme = value}
/>
</section>
<section>
<SubTitle title="Font size"/>
<Input
theme="round-black"
type="number"
min={10}
validators={InputValidators.isNumber}
value={userStore.terminalConfig.fontSize.toString()}
onChange={(value) => userStore.terminalConfig.fontSize=Number(value)}
/>
</section>
<section>
<SubTitle title="Font family"/>
<Input
theme="round-black"
type="text"
value={userStore.terminalConfig.fontFamily}
onChange={(value) => userStore.terminalConfig.fontFamily=value}
/>
</section>
</div>);
});

View File

@ -11,24 +11,28 @@ import type { DockStore, TabId } from "../dock-store/dock.store";
import { TerminalApi, TerminalChannels } from "../../../api/terminal-api";
import { ThemeStore } from "../../../theme.store";
import { disposer } from "../../../utils";
import { isMac } from "../../../../common/vars";
import { isMac, defaultTerminalFontFamily } from "../../../../common/vars";
import { once } from "lodash";
import { UserStore } from "../../../../common/user-store";
import { clipboard } from "electron";
import logger from "../../../../common/logger";
import type { TerminalConfig } from "../../../../common/user-store/preferences-helpers";
interface Dependencies {
dockStore: DockStore
}
export class Terminal {
private terminalConfig: TerminalConfig = UserStore.getInstance().terminalConfig;
public static get spawningPool() {
return document.getElementById("terminal-init");
}
static async preloadFonts() {
const fontPath = require("../../fonts/roboto-mono-nerd.ttf").default; // eslint-disable-line @typescript-eslint/no-var-requires
const fontFace = new FontFace("RobotoMono", `url(${fontPath})`);
const fontFace = new FontFace(defaultTerminalFontFamily, `url(${fontPath})`);
await fontFace.load();
document.fonts.add(fontFace);
@ -37,8 +41,8 @@ export class Terminal {
private xterm: XTerm | null = new XTerm({
cursorBlink: true,
cursorStyle: "bar",
fontSize: 13,
fontFamily: "RobotoMono",
fontSize: this.terminalConfig.fontSize,
fontFamily: this.terminalConfig.fontFamily,
});
private readonly fitAddon = new FitAddon();
private scrollPos = 0;
@ -97,6 +101,12 @@ export class Terminal {
}, {
fireImmediately: true,
}),
reaction(() => UserStore.getInstance().terminalConfig.fontSize, this.setFontSize, {
fireImmediately: true,
}),
reaction(() => UserStore.getInstance().terminalConfig.fontFamily, this.setFontFamily, {
fireImmediately: true,
}),
dependencies.dockStore.onResize(this.onResize),
() => onDataHandler.dispose(),
() => this.fitAddon.dispose(),
@ -192,6 +202,14 @@ export class Terminal {
}
};
setFontSize = (size: number) => {
this.xterm.options.fontSize = size;
};
setFontFamily = (family: string) => {
this.xterm.options.fontFamily = family;
};
keyHandler = (evt: KeyboardEvent): boolean => {
const { code, ctrlKey, metaKey } = evt;