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:
parent
6cba82c491
commit
b7d29f8c49
@ -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);
|
||||
|
||||
@ -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,
|
||||
};
|
||||
|
||||
@ -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),
|
||||
},
|
||||
|
||||
@ -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();
|
||||
|
||||
@ -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" />
|
||||
|
||||
@ -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>
|
||||
);
|
||||
});
|
||||
|
||||
@ -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()}/>
|
||||
|
||||
82
src/renderer/components/+preferences/terminal.tsx
Normal file
82
src/renderer/components/+preferences/terminal.tsx
Normal 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>);
|
||||
});
|
||||
@ -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;
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user