mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
Fix crash when switching OS theme type
- Changed the representation of theme preferences to no longer use sentinal values and instead use flags - This new format is forward looking to when support for user provided themes is added, which is now quite easy. - Added unit tests for the migration code - Made Theme's more type safe my having the lens themes be .ts files - Moved ThemeStore into renderer/themes as it is a more fitting place Signed-off-by: Sebastian Malton <sebastian@malton.name>
This commit is contained in:
parent
cfc702f89f
commit
8b19da5359
@ -3,7 +3,7 @@
|
|||||||
"productName": "OpenLens",
|
"productName": "OpenLens",
|
||||||
"description": "OpenLens - Open Source IDE for Kubernetes",
|
"description": "OpenLens - Open Source IDE for Kubernetes",
|
||||||
"homepage": "https://github.com/lensapp/lens",
|
"homepage": "https://github.com/lensapp/lens",
|
||||||
"version": "5.5.0-alpha.0",
|
"version": "5.5.0-alpha.1",
|
||||||
"main": "static/build/main.js",
|
"main": "static/build/main.js",
|
||||||
"copyright": "© 2021 OpenLens Authors",
|
"copyright": "© 2021 OpenLens Authors",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
|||||||
@ -22,23 +22,21 @@ jest.mock("electron", () => ({
|
|||||||
}));
|
}));
|
||||||
|
|
||||||
import { UserStore } from "../user-store";
|
import { UserStore } from "../user-store";
|
||||||
import { Console } from "console";
|
|
||||||
import { SemVer } from "semver";
|
import { SemVer } from "semver";
|
||||||
import electron from "electron";
|
import electron from "electron";
|
||||||
import { stdout, stderr } from "process";
|
|
||||||
import userStoreInjectable from "../user-store/user-store.injectable";
|
import userStoreInjectable from "../user-store/user-store.injectable";
|
||||||
import type { DiContainer } from "@ogre-tools/injectable";
|
import type { DiContainer } from "@ogre-tools/injectable";
|
||||||
import directoryForUserDataInjectable from "../app-paths/directory-for-user-data/directory-for-user-data.injectable";
|
import directoryForUserDataInjectable from "../app-paths/directory-for-user-data/directory-for-user-data.injectable";
|
||||||
import type { ClusterStoreModel } from "../cluster-store/cluster-store";
|
import type { ClusterStoreModel } from "../cluster-store/cluster-store";
|
||||||
import { defaultTheme } from "../vars";
|
|
||||||
import writeFileInjectable from "../fs/write-file.injectable";
|
import writeFileInjectable from "../fs/write-file.injectable";
|
||||||
import { getDiForUnitTesting } from "../../main/getDiForUnitTesting";
|
import { getDiForUnitTesting } from "../../main/getDiForUnitTesting";
|
||||||
import getConfigurationFileModelInjectable
|
import getConfigurationFileModelInjectable
|
||||||
from "../get-configuration-file-model/get-configuration-file-model.injectable";
|
from "../get-configuration-file-model/get-configuration-file-model.injectable";
|
||||||
import appVersionInjectable
|
import appVersionInjectable
|
||||||
from "../get-configuration-file-model/app-version/app-version.injectable";
|
from "../get-configuration-file-model/app-version/app-version.injectable";
|
||||||
|
import { defaultColorThemeConf, defaultTerminalThemeConf } from "../user-store/preferences-helpers";
|
||||||
|
|
||||||
console = new Console(stdout, stderr);
|
console.log("This is a reminder to get rid of mockFs because it breaks console.log");
|
||||||
|
|
||||||
describe("user store tests", () => {
|
describe("user store tests", () => {
|
||||||
let userStore: UserStore;
|
let userStore: UserStore;
|
||||||
@ -76,20 +74,16 @@ describe("user store tests", () => {
|
|||||||
expect(userStore.lastSeenAppVersion).toBe("1.2.3");
|
expect(userStore.lastSeenAppVersion).toBe("1.2.3");
|
||||||
});
|
});
|
||||||
|
|
||||||
it("allows setting and getting preferences", () => {
|
it("allows setting preferences", () => {
|
||||||
userStore.httpsProxy = "abcd://defg";
|
userStore.httpsProxy = "abcd://defg";
|
||||||
|
|
||||||
expect(userStore.httpsProxy).toBe("abcd://defg");
|
expect(userStore.httpsProxy).toBe("abcd://defg");
|
||||||
expect(userStore.colorTheme).toBe(defaultTheme);
|
|
||||||
|
|
||||||
userStore.colorTheme = "light";
|
|
||||||
expect(userStore.colorTheme).toBe("light");
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it("correctly resets theme to default value", async () => {
|
it("correctly resets theme to default value", async () => {
|
||||||
userStore.colorTheme = "some other theme";
|
(userStore.colorTheme as any) = "some other theme";
|
||||||
userStore.resetTheme();
|
userStore.resetThemeSettings();
|
||||||
expect(userStore.colorTheme).toBe(defaultTheme);
|
expect(userStore.colorTheme).toEqual(defaultColorThemeConf);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("correctly calculates if the last seen version is an old release", () => {
|
it("correctly calculates if the last seen version is an old release", () => {
|
||||||
@ -107,7 +101,6 @@ describe("user store tests", () => {
|
|||||||
"config.json": JSON.stringify({
|
"config.json": JSON.stringify({
|
||||||
user: { username: "foobar" },
|
user: { username: "foobar" },
|
||||||
preferences: { colorTheme: "light" },
|
preferences: { colorTheme: "light" },
|
||||||
lastSeenAppVersion: "1.2.3",
|
|
||||||
}),
|
}),
|
||||||
"lens-cluster-store.json": JSON.stringify({
|
"lens-cluster-store.json": JSON.stringify({
|
||||||
clusters: [
|
clusters: [
|
||||||
@ -137,9 +130,148 @@ describe("user store tests", () => {
|
|||||||
expect(userStore.lastSeenAppVersion).toBe("0.0.0");
|
expect(userStore.lastSeenAppVersion).toBe("0.0.0");
|
||||||
});
|
});
|
||||||
|
|
||||||
it.only("skips clusters for adding to kube-sync with files under extension_data/", () => {
|
it("skips clusters for adding to kube-sync with files under extension_data/", () => {
|
||||||
expect(userStore.syncKubeconfigEntries.has("some-directory-for-user-data/extension_data/foo/bar")).toBe(false);
|
expect(userStore.syncKubeconfigEntries.has("some-directory-for-user-data/extension_data/foo/bar")).toBe(false);
|
||||||
expect(userStore.syncKubeconfigEntries.has("some/other/path")).toBe(true);
|
expect(userStore.syncKubeconfigEntries.has("some/other/path")).toBe(true);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe("5.5.0-alpha.1 migrations", () => {
|
||||||
|
it("given the invalid colorTheme setting of 'light', this migration resets value to default", () => {
|
||||||
|
mockFs({
|
||||||
|
"some-directory-for-user-data": {
|
||||||
|
"lens-user-store.json": JSON.stringify({
|
||||||
|
__internal__: {
|
||||||
|
migrations: {
|
||||||
|
version: "5.5.0-alpha.0",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
preferences: { colorTheme: "light" },
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
userStore = di.inject(userStoreInjectable);
|
||||||
|
expect(userStore.colorTheme).toEqual(defaultColorThemeConf);
|
||||||
|
});
|
||||||
|
it("given the invalid colorTheme setting of false, this migration resets value to default", () => {
|
||||||
|
mockFs({
|
||||||
|
"some-directory-for-user-data": {
|
||||||
|
"lens-user-store.json": JSON.stringify({
|
||||||
|
__internal__: {
|
||||||
|
migrations: {
|
||||||
|
version: "5.5.0-alpha.0",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
preferences: { colorTheme: false },
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
userStore = di.inject(userStoreInjectable);
|
||||||
|
expect(userStore.colorTheme).toEqual(defaultColorThemeConf);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("given the colorTheme setting of 'system', this migration sets to tracking the system color theme type", () => {
|
||||||
|
mockFs({
|
||||||
|
"some-directory-for-user-data": {
|
||||||
|
"lens-user-store.json": JSON.stringify({
|
||||||
|
__internal__: {
|
||||||
|
migrations: {
|
||||||
|
version: "5.5.0-alpha.0",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
preferences: { colorTheme: "system" },
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
userStore = di.inject(userStoreInjectable);
|
||||||
|
expect(userStore.colorTheme).toEqual({
|
||||||
|
followSystemThemeType: true,
|
||||||
|
name: "lens",
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("given the colorTheme setting of 'lens-light', this migration sets to the new format without loosing data", () => {
|
||||||
|
mockFs({
|
||||||
|
"some-directory-for-user-data": {
|
||||||
|
"lens-user-store.json": JSON.stringify({
|
||||||
|
__internal__: {
|
||||||
|
migrations: {
|
||||||
|
version: "5.5.0-alpha.0",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
preferences: { colorTheme: "lens-light" },
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
userStore = di.inject(userStoreInjectable);
|
||||||
|
expect(userStore.colorTheme).toEqual({
|
||||||
|
followSystemThemeType: false,
|
||||||
|
name: "lens",
|
||||||
|
type: "light",
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("given the terminalTheme setting of '', this migration sets to the new format of following lens theme", () => {
|
||||||
|
mockFs({
|
||||||
|
"some-directory-for-user-data": {
|
||||||
|
"lens-user-store.json": JSON.stringify({
|
||||||
|
__internal__: {
|
||||||
|
migrations: {
|
||||||
|
version: "5.5.0-alpha.0",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
preferences: { terminalTheme: "" },
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
userStore = di.inject(userStoreInjectable);
|
||||||
|
expect(userStore.terminalTheme).toEqual(defaultTerminalThemeConf);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("given the invalid terminalTheme setting of 10, this migration sets to default", () => {
|
||||||
|
mockFs({
|
||||||
|
"some-directory-for-user-data": {
|
||||||
|
"lens-user-store.json": JSON.stringify({
|
||||||
|
__internal__: {
|
||||||
|
migrations: {
|
||||||
|
version: "5.5.0-alpha.0",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
preferences: { terminalTheme: 10 },
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
userStore = di.inject(userStoreInjectable);
|
||||||
|
expect(userStore.terminalTheme).toEqual(defaultTerminalThemeConf);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("given the valid terminalTheme setting of 'lens-dark', this migration sets to the new format", () => {
|
||||||
|
mockFs({
|
||||||
|
"some-directory-for-user-data": {
|
||||||
|
"lens-user-store.json": JSON.stringify({
|
||||||
|
__internal__: {
|
||||||
|
migrations: {
|
||||||
|
version: "5.5.0-alpha.0",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
preferences: { terminalTheme: "lens-dark" },
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
userStore = di.inject(userStoreInjectable);
|
||||||
|
expect(userStore.terminalTheme).toEqual({
|
||||||
|
isGlobalTheme: false,
|
||||||
|
isGlobalThemeType: false,
|
||||||
|
name: "lens",
|
||||||
|
type: "dark",
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@ -10,7 +10,9 @@ import { getAppVersion } from "../utils";
|
|||||||
import type { editor } from "monaco-editor";
|
import type { editor } from "monaco-editor";
|
||||||
import merge from "lodash/merge";
|
import merge from "lodash/merge";
|
||||||
import { SemVer } from "semver";
|
import { SemVer } from "semver";
|
||||||
import { defaultTheme, defaultEditorFontFamily, defaultFontSize, defaultTerminalFontFamily } from "../vars";
|
import { defaultEditorFontFamily, defaultFontSize, defaultTerminalFontFamily, defaultThemeName, defaultThemeType } from "../vars";
|
||||||
|
import type { ThemeType } from "../../renderer/themes/types";
|
||||||
|
import { equals } from "lodash/fp";
|
||||||
|
|
||||||
export interface KubeconfigSyncEntry extends KubeconfigSyncValue {
|
export interface KubeconfigSyncEntry extends KubeconfigSyncValue {
|
||||||
filePath: string;
|
filePath: string;
|
||||||
@ -43,7 +45,7 @@ export const defaultEditorConfig: EditorConfiguration = {
|
|||||||
};
|
};
|
||||||
interface PreferenceDescription<T, R = T> {
|
interface PreferenceDescription<T, R = T> {
|
||||||
fromStore(val: T | undefined): R;
|
fromStore(val: T | undefined): R;
|
||||||
toStore(val: R): T | undefined;
|
toStore(val: R | undefined): T | undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
const httpsProxy: PreferenceDescription<string | undefined> = {
|
const httpsProxy: PreferenceDescription<string | undefined> = {
|
||||||
@ -64,12 +66,28 @@ const shell: PreferenceDescription<string | undefined> = {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const colorTheme: PreferenceDescription<string> = {
|
export type ColorThemeConf = {
|
||||||
|
name: string;
|
||||||
|
} & ({
|
||||||
|
followSystemThemeType: true;
|
||||||
|
type?: undefined;
|
||||||
|
} | {
|
||||||
|
followSystemThemeType: false;
|
||||||
|
type: ThemeType;
|
||||||
|
});
|
||||||
|
|
||||||
|
export const defaultColorThemeConf: ColorThemeConf = {
|
||||||
|
name: defaultThemeName,
|
||||||
|
followSystemThemeType: false,
|
||||||
|
type: defaultThemeType,
|
||||||
|
};
|
||||||
|
|
||||||
|
const colorTheme: PreferenceDescription<ColorThemeConf> = {
|
||||||
fromStore(val) {
|
fromStore(val) {
|
||||||
return val || defaultTheme;
|
return val || defaultColorThemeConf;
|
||||||
},
|
},
|
||||||
toStore(val) {
|
toStore(val) {
|
||||||
if (!val || val === defaultTheme) {
|
if (!val || equals(val, defaultColorThemeConf)) {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -77,12 +95,35 @@ const colorTheme: PreferenceDescription<string> = {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const terminalTheme: PreferenceDescription<string | undefined> = {
|
export type TerminalThemeConf = ({
|
||||||
|
isGlobalTheme: true;
|
||||||
|
name?: undefined;
|
||||||
|
} | {
|
||||||
|
isGlobalTheme: false;
|
||||||
|
name: string;
|
||||||
|
}) & ({
|
||||||
|
isGlobalThemeType: true;
|
||||||
|
type?: undefined;
|
||||||
|
} | {
|
||||||
|
isGlobalThemeType: false;
|
||||||
|
type: ThemeType;
|
||||||
|
});
|
||||||
|
|
||||||
|
export const defaultTerminalThemeConf: TerminalThemeConf = {
|
||||||
|
isGlobalTheme: true,
|
||||||
|
isGlobalThemeType: true,
|
||||||
|
};
|
||||||
|
|
||||||
|
const terminalTheme: PreferenceDescription<TerminalThemeConf> = {
|
||||||
fromStore(val) {
|
fromStore(val) {
|
||||||
return val || "";
|
return val || defaultTerminalThemeConf;
|
||||||
},
|
},
|
||||||
toStore(val) {
|
toStore(val) {
|
||||||
return val || undefined;
|
if (!val || equals(val, defaultTerminalThemeConf)) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
return defaultTerminalThemeConf;
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -12,7 +12,7 @@ import { getAppVersion } from "../utils/app-version";
|
|||||||
import { kubeConfigDefaultPath } from "../kube-helpers";
|
import { kubeConfigDefaultPath } from "../kube-helpers";
|
||||||
import { appEventBus } from "../app-event-bus/event-bus";
|
import { appEventBus } from "../app-event-bus/event-bus";
|
||||||
import { getOrInsertSet, toggle, toJS, entries, fromEntries } from "../../renderer/utils";
|
import { getOrInsertSet, toggle, toJS, entries, fromEntries } from "../../renderer/utils";
|
||||||
import { DESCRIPTORS } from "./preferences-helpers";
|
import { ColorThemeConf, DESCRIPTORS, TerminalThemeConf } from "./preferences-helpers";
|
||||||
import type { EditorConfiguration, ExtensionRegistry, KubeconfigSyncValue, UserPreferencesModel, TerminalConfig } from "./preferences-helpers";
|
import type { EditorConfiguration, ExtensionRegistry, KubeconfigSyncValue, UserPreferencesModel, TerminalConfig } from "./preferences-helpers";
|
||||||
import logger from "../../main/logger";
|
import logger from "../../main/logger";
|
||||||
|
|
||||||
@ -49,8 +49,8 @@ export class UserStore extends BaseStore<UserStoreModel> /* implements UserStore
|
|||||||
@observable allowTelemetry: boolean;
|
@observable allowTelemetry: boolean;
|
||||||
@observable allowErrorReporting: boolean;
|
@observable allowErrorReporting: boolean;
|
||||||
@observable allowUntrustedCAs: boolean;
|
@observable allowUntrustedCAs: boolean;
|
||||||
@observable colorTheme: string;
|
@observable colorTheme: ColorThemeConf;
|
||||||
@observable terminalTheme: string;
|
@observable terminalTheme: TerminalThemeConf;
|
||||||
@observable localeTimezone: string;
|
@observable localeTimezone: string;
|
||||||
@observable downloadMirror: string;
|
@observable downloadMirror: string;
|
||||||
@observable httpsProxy?: string;
|
@observable httpsProxy?: string;
|
||||||
@ -142,8 +142,9 @@ export class UserStore extends BaseStore<UserStoreModel> /* implements UserStore
|
|||||||
}
|
}
|
||||||
|
|
||||||
@action
|
@action
|
||||||
resetTheme() {
|
resetThemeSettings() {
|
||||||
this.colorTheme = DESCRIPTORS.colorTheme.fromStore(undefined);
|
this.colorTheme = DESCRIPTORS.colorTheme.fromStore(undefined);
|
||||||
|
this.terminalTheme = DESCRIPTORS.terminalTheme.fromStore(undefined);
|
||||||
}
|
}
|
||||||
|
|
||||||
@action
|
@action
|
||||||
|
|||||||
@ -3,6 +3,7 @@
|
|||||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Narrows `val` to include the property `key` (if true is returned)
|
* Narrows `val` to include the property `key` (if true is returned)
|
||||||
* @param val The object to be tested
|
* @param val The object to be tested
|
||||||
@ -73,6 +74,20 @@ export function isString(val: unknown): val is string {
|
|||||||
return typeof val === "string";
|
return typeof val === "string";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A function to validate (into the typesystem) that a certain string ends with a specific suffix.
|
||||||
|
*/
|
||||||
|
export function endsWith<T extends string>(val: string, suffix: T): val is `${string}${T}` {
|
||||||
|
return val.endsWith(suffix);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A predicate for determining (in the type system) that a given string has a certain prefix
|
||||||
|
*/
|
||||||
|
export function startsWith<T extends string>(val: string, prefix: T): val is `${T}${string}`{
|
||||||
|
return val.startsWith(prefix) as never;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* checks if val is of type object and isn't null
|
* checks if val is of type object and isn't null
|
||||||
* @param val the value to be checked
|
* @param val the value to be checked
|
||||||
|
|||||||
16
src/common/utils/types.ts
Normal file
16
src/common/utils/types.ts
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||||
|
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
export type SafeCapitalize<S> = S extends string
|
||||||
|
? Capitalize<S>
|
||||||
|
: never;
|
||||||
|
|
||||||
|
export type PrefixCamelCasedProperties<Value, Prefix extends string> = Value extends Function
|
||||||
|
? Value
|
||||||
|
: Value extends Array<any>
|
||||||
|
? Value
|
||||||
|
: {
|
||||||
|
[K in keyof Value as `${Prefix}${SafeCapitalize<K>}`]: Value[K];
|
||||||
|
};
|
||||||
@ -7,6 +7,7 @@
|
|||||||
import path from "path";
|
import path from "path";
|
||||||
import { SemVer } from "semver";
|
import { SemVer } from "semver";
|
||||||
import packageInfo from "../../package.json";
|
import packageInfo from "../../package.json";
|
||||||
|
import type { ThemeType } from "../renderer/themes/types";
|
||||||
import { defineGlobal } from "./utils/defineGlobal";
|
import { defineGlobal } from "./utils/defineGlobal";
|
||||||
import { lazyInitialized } from "./utils/lazy-initialized";
|
import { lazyInitialized } from "./utils/lazy-initialized";
|
||||||
|
|
||||||
@ -26,7 +27,10 @@ export const isIntegrationTesting = process.argv.includes(integrationTestingArg)
|
|||||||
export const productName = packageInfo.productName;
|
export const productName = packageInfo.productName;
|
||||||
export const appName = `${packageInfo.productName}${isDevelopment ? "Dev" : ""}`;
|
export const appName = `${packageInfo.productName}${isDevelopment ? "Dev" : ""}`;
|
||||||
export const publicPath = "/build/" as string;
|
export const publicPath = "/build/" as string;
|
||||||
export const defaultTheme = "lens-dark" as string;
|
|
||||||
|
export const defaultThemeName = "lens";
|
||||||
|
export const defaultThemeType: ThemeType = "dark";
|
||||||
|
|
||||||
export const defaultFontSize = 12;
|
export const defaultFontSize = 12;
|
||||||
export const defaultTerminalFontFamily = "RobotoMono";
|
export const defaultTerminalFontFamily = "RobotoMono";
|
||||||
export const defaultEditorFontFamily = "RobotoMono";
|
export const defaultEditorFontFamily = "RobotoMono";
|
||||||
|
|||||||
@ -3,7 +3,7 @@
|
|||||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { ThemeStore } from "../../renderer/theme.store";
|
import { ThemeStore } from "../../renderer/themes/store";
|
||||||
|
|
||||||
export function getActiveTheme() {
|
export function getActiveTheme() {
|
||||||
return ThemeStore.getInstance().activeTheme;
|
return ThemeStore.getInstance().activeTheme;
|
||||||
|
|||||||
69
src/migrations/user-store/5.5.0-alpha.1.ts
Normal file
69
src/migrations/user-store/5.5.0-alpha.1.ts
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||||
|
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import type { TerminalThemeConf, ColorThemeConf } from "../../common/user-store/preferences-helpers";
|
||||||
|
import type { ThemeType } from "../../renderer/themes/types";
|
||||||
|
import type { MigrationDeclaration } from "../helpers";
|
||||||
|
|
||||||
|
type Pre550Alpha1ColorTheme = string; // theme-id or "system"
|
||||||
|
type Pre550TerminalTheme = string; // theme-id or "" (for match)
|
||||||
|
|
||||||
|
const themeIdMatcher = /^(?<name>[a-z0-9]+)-(?<type>dark|light)$/i;
|
||||||
|
|
||||||
|
const v550alpha1Migration: MigrationDeclaration = {
|
||||||
|
version: "5.5.0-alpha.1",
|
||||||
|
run(store) {
|
||||||
|
const colorTheme = store.get("preferences.colorTheme") as Pre550Alpha1ColorTheme | undefined;
|
||||||
|
const terminalTheme = store.get("preferences.terminalTheme") as Pre550TerminalTheme | undefined;
|
||||||
|
|
||||||
|
if (typeof colorTheme !== "string") {
|
||||||
|
store.delete("preferences.colorTheme"); // use default
|
||||||
|
} else {
|
||||||
|
if (colorTheme === "system") {
|
||||||
|
const newSetting: ColorThemeConf = {
|
||||||
|
followSystemThemeType: true,
|
||||||
|
name: "lens",
|
||||||
|
};
|
||||||
|
|
||||||
|
store.set("preferences.colorTheme", newSetting);
|
||||||
|
} else {
|
||||||
|
const match = colorTheme.match(themeIdMatcher);
|
||||||
|
|
||||||
|
if (!match?.groups) {
|
||||||
|
store.delete("preferences.colorTheme"); // use default
|
||||||
|
} else {
|
||||||
|
const newSetting: ColorThemeConf = {
|
||||||
|
followSystemThemeType: false,
|
||||||
|
name: match.groups.name,
|
||||||
|
type: match.groups.type as ThemeType,
|
||||||
|
};
|
||||||
|
|
||||||
|
store.set("preferences.colorTheme", newSetting);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof terminalTheme !== "string") {
|
||||||
|
store.delete("preferences.terminalTheme"); // use default
|
||||||
|
} else {
|
||||||
|
const match = terminalTheme.match(themeIdMatcher);
|
||||||
|
|
||||||
|
if (!match?.groups) {
|
||||||
|
store.delete("preferences.terminalTheme"); // use default
|
||||||
|
} else {
|
||||||
|
const newSetting: TerminalThemeConf = {
|
||||||
|
isGlobalTheme: false,
|
||||||
|
isGlobalThemeType: false,
|
||||||
|
name: match.groups.name,
|
||||||
|
type: match.groups.type as ThemeType,
|
||||||
|
};
|
||||||
|
|
||||||
|
store.set("preferences.terminalTheme", newSetting);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export default v550alpha1Migration;
|
||||||
@ -10,6 +10,7 @@ import { joinMigrations } from "../helpers";
|
|||||||
import version210Beta4 from "./2.1.0-beta.4";
|
import version210Beta4 from "./2.1.0-beta.4";
|
||||||
import version500Alpha3 from "./5.0.0-alpha.3";
|
import version500Alpha3 from "./5.0.0-alpha.3";
|
||||||
import version503Beta1 from "./5.0.3-beta.1";
|
import version503Beta1 from "./5.0.3-beta.1";
|
||||||
|
import v550alpha1Migration from "./5.5.0-alpha.1";
|
||||||
import { fileNameMigration } from "./file-name-migration";
|
import { fileNameMigration } from "./file-name-migration";
|
||||||
|
|
||||||
export {
|
export {
|
||||||
@ -20,4 +21,5 @@ export default joinMigrations(
|
|||||||
version210Beta4,
|
version210Beta4,
|
||||||
version500Alpha3,
|
version500Alpha3,
|
||||||
version503Beta1,
|
version503Beta1,
|
||||||
|
v550alpha1Migration,
|
||||||
);
|
);
|
||||||
|
|||||||
@ -36,7 +36,7 @@ import initClusterFrameInjectable from "./frames/cluster-frame/init-cluster-fram
|
|||||||
import commandOverlayInjectable from "./components/command-palette/command-overlay.injectable";
|
import commandOverlayInjectable from "./components/command-palette/command-overlay.injectable";
|
||||||
import { Router } from "react-router";
|
import { Router } from "react-router";
|
||||||
import historyInjectable from "./navigation/history.injectable";
|
import historyInjectable from "./navigation/history.injectable";
|
||||||
import themeStoreInjectable from "./theme-store.injectable";
|
import themeStoreInjectable from "./themes/store.injectable";
|
||||||
import navigateToAddClusterInjectable from "../common/front-end-routing/routes/add-cluster/navigate-to-add-cluster.injectable";
|
import navigateToAddClusterInjectable from "../common/front-end-routing/routes/add-cluster/navigate-to-add-cluster.injectable";
|
||||||
import addSyncEntriesInjectable from "./initializers/add-sync-entries.injectable";
|
import addSyncEntriesInjectable from "./initializers/add-sync-entries.injectable";
|
||||||
import hotbarStoreInjectable from "../common/hotbar-store.injectable";
|
import hotbarStoreInjectable from "../common/hotbar-store.injectable";
|
||||||
|
|||||||
@ -18,7 +18,7 @@ import catalogEntityStoreInjectable from "./catalog-entity-store/catalog-entity-
|
|||||||
import catalogEntityRegistryInjectable from "../../api/catalog-entity-registry/catalog-entity-registry.injectable";
|
import catalogEntityRegistryInjectable from "../../api/catalog-entity-registry/catalog-entity-registry.injectable";
|
||||||
import type { DiRender } from "../test-utils/renderFor";
|
import type { DiRender } from "../test-utils/renderFor";
|
||||||
import { renderFor } from "../test-utils/renderFor";
|
import { renderFor } from "../test-utils/renderFor";
|
||||||
import { ThemeStore } from "../../theme.store";
|
import { ThemeStore } from "../../themes/store";
|
||||||
import { UserStore } from "../../../common/user-store";
|
import { UserStore } from "../../../common/user-store";
|
||||||
import mockFs from "mock-fs";
|
import mockFs from "mock-fs";
|
||||||
import directoryForUserDataInjectable from "../../../common/app-paths/directory-for-user-data/directory-for-user-data.injectable";
|
import directoryForUserDataInjectable from "../../../common/app-paths/directory-for-user-data/directory-for-user-data.injectable";
|
||||||
|
|||||||
@ -16,7 +16,7 @@ import { eventStore } from "../+events/event.store";
|
|||||||
import { boundMethod, cssNames, prevDefault } from "../../utils";
|
import { boundMethod, cssNames, prevDefault } from "../../utils";
|
||||||
import type { ItemObject } from "../../../common/item.store";
|
import type { ItemObject } from "../../../common/item.store";
|
||||||
import { Spinner } from "../spinner";
|
import { Spinner } from "../spinner";
|
||||||
import { ThemeStore } from "../../theme.store";
|
import { ThemeStore } from "../../themes/store";
|
||||||
import { kubeSelectedUrlParam, toggleDetails } from "../kube-detail-params";
|
import { kubeSelectedUrlParam, toggleDetails } from "../kube-detail-params";
|
||||||
import { apiManager } from "../../../common/k8s-api/api-manager";
|
import { apiManager } from "../../../common/k8s-api/api-manager";
|
||||||
import { KubeObjectAge } from "../kube-object/age";
|
import { KubeObjectAge } from "../kube-object/age";
|
||||||
|
|||||||
@ -14,7 +14,7 @@ import { nodesStore } from "../+nodes/nodes.store";
|
|||||||
import { ChartData, PieChart } from "../chart";
|
import { ChartData, PieChart } from "../chart";
|
||||||
import { ClusterNoMetrics } from "./cluster-no-metrics";
|
import { ClusterNoMetrics } from "./cluster-no-metrics";
|
||||||
import { bytesToUnits, cssNames } from "../../utils";
|
import { bytesToUnits, cssNames } from "../../utils";
|
||||||
import { ThemeStore } from "../../theme.store";
|
import { ThemeStore } from "../../themes/store";
|
||||||
import { getMetricLastPoints } from "../../../common/k8s-api/endpoints/metrics.api";
|
import { getMetricLastPoints } from "../../../common/k8s-api/endpoints/metrics.api";
|
||||||
import { withInjectables } from "@ogre-tools/injectable-react";
|
import { withInjectables } from "@ogre-tools/injectable-react";
|
||||||
import clusterOverviewStoreInjectable from "./cluster-overview-store/cluster-overview-store.injectable";
|
import clusterOverviewStoreInjectable from "./cluster-overview-store/cluster-overview-store.injectable";
|
||||||
|
|||||||
@ -20,7 +20,7 @@ import { Spinner } from "../../spinner";
|
|||||||
import { Table, TableCell, TableHead, TableRow } from "../../table";
|
import { Table, TableCell, TableHead, TableRow } from "../../table";
|
||||||
import { Button } from "../../button";
|
import { Button } from "../../button";
|
||||||
import { Notifications } from "../../notifications";
|
import { Notifications } from "../../notifications";
|
||||||
import { ThemeStore } from "../../../theme.store";
|
import { ThemeStore } from "../../../themes/store";
|
||||||
import { apiManager } from "../../../../common/k8s-api/api-manager";
|
import { apiManager } from "../../../../common/k8s-api/api-manager";
|
||||||
import { SubTitle } from "../../layout/sub-title";
|
import { SubTitle } from "../../layout/sub-title";
|
||||||
import { getDetailsUrl } from "../../kube-detail-params";
|
import { getDetailsUrl } from "../../kube-detail-params";
|
||||||
|
|||||||
@ -11,7 +11,7 @@ import { NoMetrics } from "../resource-metrics/no-metrics";
|
|||||||
import { IResourceMetricsValue, ResourceMetricsContext } from "../resource-metrics";
|
import { IResourceMetricsValue, ResourceMetricsContext } from "../resource-metrics";
|
||||||
import { observer } from "mobx-react";
|
import { observer } from "mobx-react";
|
||||||
import type { ChartOptions, ChartPoint } from "chart.js";
|
import type { ChartOptions, ChartPoint } from "chart.js";
|
||||||
import { ThemeStore } from "../../theme.store";
|
import { ThemeStore } from "../../themes/store";
|
||||||
import { mapValues } from "lodash";
|
import { mapValues } from "lodash";
|
||||||
|
|
||||||
type IContext = IResourceMetricsValue<Node, { metrics: IClusterMetrics }>;
|
type IContext = IResourceMetricsValue<Node, { metrics: IClusterMetrics }>;
|
||||||
|
|||||||
@ -7,7 +7,7 @@ import React from "react";
|
|||||||
import { observer } from "mobx-react";
|
import { observer } from "mobx-react";
|
||||||
import { SubTitle } from "../layout/sub-title";
|
import { SubTitle } from "../layout/sub-title";
|
||||||
import { Select, SelectOption } from "../select";
|
import { Select, SelectOption } from "../select";
|
||||||
import type { ThemeStore } from "../../theme.store";
|
import { themeTypeOptions } from "../../themes/store";
|
||||||
import type { UserStore } from "../../../common/user-store";
|
import type { UserStore } from "../../../common/user-store";
|
||||||
import { Input } from "../input";
|
import { Input } from "../input";
|
||||||
import { Switch } from "../switch";
|
import { Switch } from "../switch";
|
||||||
@ -21,7 +21,6 @@ import { withInjectables } from "@ogre-tools/injectable-react";
|
|||||||
import appPreferencesInjectable from "./app-preferences/app-preferences.injectable";
|
import appPreferencesInjectable from "./app-preferences/app-preferences.injectable";
|
||||||
import { Preferences } from "./preferences";
|
import { Preferences } from "./preferences";
|
||||||
import userStoreInjectable from "../../../common/user-store/user-store.injectable";
|
import userStoreInjectable from "../../../common/user-store/user-store.injectable";
|
||||||
import themeStoreInjectable from "../../theme-store.injectable";
|
|
||||||
|
|
||||||
const timezoneOptions: SelectOption<string>[] = moment.tz.names().map(zone => ({
|
const timezoneOptions: SelectOption<string>[] = moment.tz.names().map(zone => ({
|
||||||
label: zone,
|
label: zone,
|
||||||
@ -35,10 +34,9 @@ const updateChannelOptions: SelectOption<string>[] = Array.from(
|
|||||||
interface Dependencies {
|
interface Dependencies {
|
||||||
appPreferenceItems: IComputedValue<RegisteredAppPreference[]>;
|
appPreferenceItems: IComputedValue<RegisteredAppPreference[]>;
|
||||||
userStore: UserStore;
|
userStore: UserStore;
|
||||||
themeStore: ThemeStore;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const NonInjectedApplication: React.FC<Dependencies> = ({ appPreferenceItems, userStore, themeStore }) => {
|
const NonInjectedApplication = observer(({ appPreferenceItems, userStore }: Dependencies) => {
|
||||||
const [customUrl, setCustomUrl] = React.useState(userStore.extensionRegistryUrl.customUrl || "");
|
const [customUrl, setCustomUrl] = React.useState(userStore.extensionRegistryUrl.customUrl || "");
|
||||||
const extensionSettings = appPreferenceItems.get().filter((preference) => preference.showInPreferencesTab === "application");
|
const extensionSettings = appPreferenceItems.get().filter((preference) => preference.showInPreferencesTab === "application");
|
||||||
|
|
||||||
@ -48,16 +46,27 @@ const NonInjectedApplication: React.FC<Dependencies> = ({ appPreferenceItems, us
|
|||||||
<h2 data-testid="application-header">Application</h2>
|
<h2 data-testid="application-header">Application</h2>
|
||||||
<section id="appearance">
|
<section id="appearance">
|
||||||
<SubTitle title="Theme" />
|
<SubTitle title="Theme" />
|
||||||
<Select
|
<Switch
|
||||||
id="theme-input"
|
checked={userStore.colorTheme.followSystemThemeType}
|
||||||
options={[
|
onChange={() => userStore.colorTheme.followSystemThemeType = !userStore.colorTheme.followSystemThemeType}
|
||||||
{ label: "Sync with computer", value: "system" },
|
>
|
||||||
...themeStore.themeOptions,
|
Sync theme type with Operating System settings
|
||||||
]}
|
</Switch>
|
||||||
value={userStore.colorTheme}
|
|
||||||
onChange={({ value }) => userStore.colorTheme = value}
|
{!userStore.colorTheme.followSystemThemeType && (
|
||||||
themeName="lens"
|
<>
|
||||||
/>
|
<p className="mt-4 mb-5 leading-relaxed">
|
||||||
|
Choose whether you want dark or light theming for Lens.
|
||||||
|
</p>
|
||||||
|
<Select
|
||||||
|
id="theme-type-input"
|
||||||
|
options={themeTypeOptions}
|
||||||
|
value={userStore.colorTheme.type}
|
||||||
|
onChange={({ value }) => userStore.colorTheme.type = value}
|
||||||
|
themeName="lens"
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<hr />
|
<hr />
|
||||||
@ -135,16 +144,11 @@ const NonInjectedApplication: React.FC<Dependencies> = ({ appPreferenceItems, us
|
|||||||
</section>
|
</section>
|
||||||
</Preferences>
|
</Preferences>
|
||||||
);
|
);
|
||||||
};
|
});
|
||||||
|
|
||||||
export const Application = withInjectables<Dependencies>(
|
export const Application = withInjectables<Dependencies>(NonInjectedApplication, {
|
||||||
observer(NonInjectedApplication),
|
getProps: (di) => ({
|
||||||
|
appPreferenceItems: di.inject(appPreferencesInjectable),
|
||||||
{
|
userStore: di.inject(userStoreInjectable),
|
||||||
getProps: (di) => ({
|
}),
|
||||||
appPreferenceItems: di.inject(appPreferencesInjectable),
|
});
|
||||||
userStore: di.inject(userStoreInjectable),
|
|
||||||
themeStore: di.inject(themeStoreInjectable),
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|||||||
@ -10,20 +10,18 @@ import { SubTitle } from "../layout/sub-title";
|
|||||||
import { Input, InputValidators } from "../input";
|
import { Input, InputValidators } from "../input";
|
||||||
import { Switch } from "../switch";
|
import { Switch } from "../switch";
|
||||||
import { Select } from "../select";
|
import { Select } from "../select";
|
||||||
import type { ThemeStore } from "../../theme.store";
|
import { themeTypeOptions } from "../../themes/store";
|
||||||
import { Preferences } from "./preferences";
|
import { Preferences } from "./preferences";
|
||||||
import { withInjectables } from "@ogre-tools/injectable-react";
|
import { withInjectables } from "@ogre-tools/injectable-react";
|
||||||
import userStoreInjectable from "../../../common/user-store/user-store.injectable";
|
import userStoreInjectable from "../../../common/user-store/user-store.injectable";
|
||||||
import themeStoreInjectable from "../../theme-store.injectable";
|
|
||||||
import defaultShellInjectable from "./default-shell.injectable";
|
import defaultShellInjectable from "./default-shell.injectable";
|
||||||
|
|
||||||
interface Dependencies {
|
interface Dependencies {
|
||||||
userStore: UserStore;
|
userStore: UserStore;
|
||||||
themeStore: ThemeStore;
|
|
||||||
defaultShell: string;
|
defaultShell: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const NonInjectedTerminal = observer(({ userStore, themeStore, defaultShell }: Dependencies) => {
|
const NonInjectedTerminal = observer(({ userStore, defaultShell }: Dependencies) => {
|
||||||
return (
|
return (
|
||||||
<Preferences data-testid="terminal-preferences-page">
|
<Preferences data-testid="terminal-preferences-page">
|
||||||
<section>
|
<section>
|
||||||
@ -51,18 +49,28 @@ const NonInjectedTerminal = observer(({ userStore, themeStore, defaultShell }: D
|
|||||||
|
|
||||||
<section id="terminalTheme">
|
<section id="terminalTheme">
|
||||||
<SubTitle title="Terminal theme" />
|
<SubTitle title="Terminal theme" />
|
||||||
<Select
|
<Switch
|
||||||
id="terminal-theme-input"
|
checked={userStore.terminalTheme.isGlobalThemeType}
|
||||||
themeName="lens"
|
onChange={() => userStore.terminalTheme.isGlobalThemeType = !userStore.terminalTheme.isGlobalThemeType}
|
||||||
options={[
|
>
|
||||||
{ label: "Match theme", value: "" },
|
Sync terminal theme type with that of Lens
|
||||||
...themeStore.themeOptions,
|
</Switch>
|
||||||
]}
|
|
||||||
value={userStore.terminalTheme}
|
{
|
||||||
onChange={({ value }) => userStore.terminalTheme = value}
|
!userStore.terminalTheme.isGlobalThemeType && (
|
||||||
/>
|
<Select
|
||||||
|
id="terminal-theme-input"
|
||||||
|
themeName="lens"
|
||||||
|
options={themeTypeOptions}
|
||||||
|
value={userStore.terminalTheme.type}
|
||||||
|
onChange={({ value }) => userStore.terminalTheme.type = value}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
|
{/* Once other themes are supported add an option to sync those as well */}
|
||||||
|
|
||||||
<section>
|
<section>
|
||||||
<SubTitle title="Font size" />
|
<SubTitle title="Font size" />
|
||||||
<Input
|
<Input
|
||||||
@ -88,15 +96,10 @@ const NonInjectedTerminal = observer(({ userStore, themeStore, defaultShell }: D
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
export const Terminal = withInjectables<Dependencies>(
|
export const Terminal = withInjectables<Dependencies>(NonInjectedTerminal, {
|
||||||
NonInjectedTerminal,
|
getProps: (di) => ({
|
||||||
|
userStore: di.inject(userStoreInjectable),
|
||||||
{
|
defaultShell: di.inject(defaultShellInjectable),
|
||||||
getProps: (di) => ({
|
}),
|
||||||
userStore: di.inject(userStoreInjectable),
|
});
|
||||||
themeStore: di.inject(themeStoreInjectable),
|
|
||||||
defaultShell: di.inject(defaultShellInjectable),
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|||||||
@ -10,7 +10,7 @@ import { BarChart, ChartDataSets, memoryOptions } from "../chart";
|
|||||||
import { isMetricsEmpty, normalizeMetrics } from "../../../common/k8s-api/endpoints/metrics.api";
|
import { isMetricsEmpty, normalizeMetrics } from "../../../common/k8s-api/endpoints/metrics.api";
|
||||||
import { NoMetrics } from "../resource-metrics/no-metrics";
|
import { NoMetrics } from "../resource-metrics/no-metrics";
|
||||||
import { IResourceMetricsValue, ResourceMetricsContext } from "../resource-metrics";
|
import { IResourceMetricsValue, ResourceMetricsContext } from "../resource-metrics";
|
||||||
import { ThemeStore } from "../../theme.store";
|
import { ThemeStore } from "../../themes/store";
|
||||||
|
|
||||||
type IContext = IResourceMetricsValue<PersistentVolumeClaim, { metrics: IPvcMetrics }>;
|
type IContext = IResourceMetricsValue<PersistentVolumeClaim, { metrics: IPvcMetrics }>;
|
||||||
|
|
||||||
|
|||||||
@ -11,7 +11,7 @@ import { observer } from "mobx-react";
|
|||||||
import { PieChart } from "../chart";
|
import { PieChart } from "../chart";
|
||||||
import { cssVar } from "../../utils";
|
import { cssVar } from "../../utils";
|
||||||
import type { ChartData } from "chart.js";
|
import type { ChartData } from "chart.js";
|
||||||
import { ThemeStore } from "../../theme.store";
|
import { ThemeStore } from "../../themes/store";
|
||||||
|
|
||||||
export interface OverviewWorkloadStatusProps {
|
export interface OverviewWorkloadStatusProps {
|
||||||
status: Record<string, number>;
|
status: Record<string, number>;
|
||||||
|
|||||||
@ -10,7 +10,7 @@ import { BarChart, cpuOptions, memoryOptions } from "../chart";
|
|||||||
import { isMetricsEmpty, normalizeMetrics } from "../../../common/k8s-api/endpoints/metrics.api";
|
import { isMetricsEmpty, normalizeMetrics } from "../../../common/k8s-api/endpoints/metrics.api";
|
||||||
import { NoMetrics } from "../resource-metrics/no-metrics";
|
import { NoMetrics } from "../resource-metrics/no-metrics";
|
||||||
import { IResourceMetricsValue, ResourceMetricsContext } from "../resource-metrics";
|
import { IResourceMetricsValue, ResourceMetricsContext } from "../resource-metrics";
|
||||||
import { ThemeStore } from "../../theme.store";
|
import { ThemeStore } from "../../themes/store";
|
||||||
import { mapValues } from "lodash";
|
import { mapValues } from "lodash";
|
||||||
|
|
||||||
type IContext = IResourceMetricsValue<any, { metrics: IPodMetrics }>;
|
type IContext = IResourceMetricsValue<any, { metrics: IPodMetrics }>;
|
||||||
|
|||||||
@ -12,7 +12,7 @@ import type { ChartData, ChartOptions, ChartPoint, ChartTooltipItem, Scriptable
|
|||||||
import { Chart, ChartKind, ChartProps } from "./chart";
|
import { Chart, ChartKind, ChartProps } from "./chart";
|
||||||
import { bytesToUnits, cssNames } from "../../utils";
|
import { bytesToUnits, cssNames } from "../../utils";
|
||||||
import { ZebraStripes } from "./zebra-stripes.plugin";
|
import { ZebraStripes } from "./zebra-stripes.plugin";
|
||||||
import { ThemeStore } from "../../theme.store";
|
import { ThemeStore } from "../../themes/store";
|
||||||
import { NoMetrics } from "../resource-metrics/no-metrics";
|
import { NoMetrics } from "../resource-metrics/no-metrics";
|
||||||
|
|
||||||
export interface BarChartProps extends ChartProps {
|
export interface BarChartProps extends ChartProps {
|
||||||
|
|||||||
@ -9,7 +9,7 @@ import { observer } from "mobx-react";
|
|||||||
import ChartJS, { ChartOptions } from "chart.js";
|
import ChartJS, { ChartOptions } from "chart.js";
|
||||||
import { Chart, ChartProps } from "./chart";
|
import { Chart, ChartProps } from "./chart";
|
||||||
import { cssNames } from "../../utils";
|
import { cssNames } from "../../utils";
|
||||||
import { ThemeStore } from "../../theme.store";
|
import { ThemeStore } from "../../themes/store";
|
||||||
|
|
||||||
export interface PieChartProps extends ChartProps {
|
export interface PieChartProps extends ChartProps {
|
||||||
}
|
}
|
||||||
|
|||||||
@ -10,7 +10,7 @@ import fse from "fs-extra";
|
|||||||
import { DockTabs } from "../dock-tabs";
|
import { DockTabs } from "../dock-tabs";
|
||||||
import { DockStore, DockTab, TabKind } from "../dock/store";
|
import { DockStore, DockTab, TabKind } from "../dock/store";
|
||||||
import { noop } from "../../../utils";
|
import { noop } from "../../../utils";
|
||||||
import { ThemeStore } from "../../../theme.store";
|
import { ThemeStore } from "../../../themes/store";
|
||||||
import { UserStore } from "../../../../common/user-store";
|
import { UserStore } from "../../../../common/user-store";
|
||||||
import { getDiForUnitTesting } from "../../../getDiForUnitTesting";
|
import { getDiForUnitTesting } from "../../../getDiForUnitTesting";
|
||||||
import dockStoreInjectable from "../dock/store.injectable";
|
import dockStoreInjectable from "../dock/store.injectable";
|
||||||
|
|||||||
@ -9,7 +9,7 @@ import * as selectEvent from "react-select-event";
|
|||||||
import { Pod } from "../../../../../common/k8s-api/endpoints";
|
import { Pod } from "../../../../../common/k8s-api/endpoints";
|
||||||
import { LogResourceSelector } from "../resource-selector";
|
import { LogResourceSelector } from "../resource-selector";
|
||||||
import { dockerPod, deploymentPod1, deploymentPod2 } from "./pod.mock";
|
import { dockerPod, deploymentPod1, deploymentPod2 } from "./pod.mock";
|
||||||
import { ThemeStore } from "../../../../theme.store";
|
import { ThemeStore } from "../../../../themes/store";
|
||||||
import { UserStore } from "../../../../../common/user-store";
|
import { UserStore } from "../../../../../common/user-store";
|
||||||
import mockFs from "mock-fs";
|
import mockFs from "mock-fs";
|
||||||
import { getDiForUnitTesting } from "../../../../getDiForUnitTesting";
|
import { getDiForUnitTesting } from "../../../../getDiForUnitTesting";
|
||||||
|
|||||||
@ -9,7 +9,7 @@ import { Terminal as XTerm } from "xterm";
|
|||||||
import { FitAddon } from "xterm-addon-fit";
|
import { FitAddon } from "xterm-addon-fit";
|
||||||
import type { TabId } from "../dock/store";
|
import type { TabId } from "../dock/store";
|
||||||
import { TerminalApi, TerminalChannels } from "../../../api/terminal-api";
|
import { TerminalApi, TerminalChannels } from "../../../api/terminal-api";
|
||||||
import { ThemeStore } from "../../../theme.store";
|
import { ThemeStore } from "../../../themes/store";
|
||||||
import { disposer } from "../../../utils";
|
import { disposer } from "../../../utils";
|
||||||
import { isMac } from "../../../../common/vars";
|
import { isMac } from "../../../../common/vars";
|
||||||
import { once } from "lodash";
|
import { once } from "lodash";
|
||||||
|
|||||||
@ -10,7 +10,7 @@ import { disposeOnUnmount, observer } from "mobx-react";
|
|||||||
import { cssNames } from "../../../utils";
|
import { cssNames } from "../../../utils";
|
||||||
import type { Terminal } from "./terminal";
|
import type { Terminal } from "./terminal";
|
||||||
import type { TerminalStore } from "./store";
|
import type { TerminalStore } from "./store";
|
||||||
import { ThemeStore } from "../../../theme.store";
|
import { ThemeStore } from "../../../themes/store";
|
||||||
import type { DockTab, DockStore } from "../dock/store";
|
import type { DockTab, DockStore } from "../dock/store";
|
||||||
import { withInjectables } from "@ogre-tools/injectable-react";
|
import { withInjectables } from "@ogre-tools/injectable-react";
|
||||||
import dockStoreInjectable from "../dock/store.injectable";
|
import dockStoreInjectable from "../dock/store.injectable";
|
||||||
|
|||||||
@ -11,7 +11,7 @@ import type { DiContainer } from "@ogre-tools/injectable";
|
|||||||
import { getDiForUnitTesting } from "../../../getDiForUnitTesting";
|
import { getDiForUnitTesting } from "../../../getDiForUnitTesting";
|
||||||
import { DiRender, renderFor } from "../../test-utils/renderFor";
|
import { DiRender, renderFor } from "../../test-utils/renderFor";
|
||||||
import hotbarStoreInjectable from "../../../../common/hotbar-store.injectable";
|
import hotbarStoreInjectable from "../../../../common/hotbar-store.injectable";
|
||||||
import { ThemeStore } from "../../../theme.store";
|
import { ThemeStore } from "../../../themes/store";
|
||||||
import { ConfirmDialog } from "../../confirm-dialog";
|
import { ConfirmDialog } from "../../confirm-dialog";
|
||||||
import { UserStore } from "../../../../common/user-store";
|
import { UserStore } from "../../../../common/user-store";
|
||||||
import mockFs from "mock-fs";
|
import mockFs from "mock-fs";
|
||||||
|
|||||||
@ -16,7 +16,7 @@ import { NoItems } from "../no-items";
|
|||||||
import { Spinner } from "../spinner";
|
import { Spinner } from "../spinner";
|
||||||
import type { ItemObject, ItemStore } from "../../../common/item.store";
|
import type { ItemObject, ItemStore } from "../../../common/item.store";
|
||||||
import { Filter, pageFilters } from "./page-filters.store";
|
import { Filter, pageFilters } from "./page-filters.store";
|
||||||
import { ThemeStore } from "../../theme.store";
|
import { ThemeStore } from "../../themes/store";
|
||||||
import { MenuActions } from "../menu/menu-actions";
|
import { MenuActions } from "../menu/menu-actions";
|
||||||
import { MenuItem } from "../menu";
|
import { MenuItem } from "../menu";
|
||||||
import { Checkbox } from "../checkbox";
|
import { Checkbox } from "../checkbox";
|
||||||
|
|||||||
@ -13,7 +13,7 @@ import { MonacoValidator, monacoValidators } from "./monaco-validators";
|
|||||||
import { debounce, merge } from "lodash";
|
import { debounce, merge } from "lodash";
|
||||||
import { cssNames, disposer } from "../../utils";
|
import { cssNames, disposer } from "../../utils";
|
||||||
import { UserStore } from "../../../common/user-store";
|
import { UserStore } from "../../../common/user-store";
|
||||||
import { ThemeStore } from "../../theme.store";
|
import { ThemeStore } from "../../themes/store";
|
||||||
|
|
||||||
export type MonacoEditorId = string;
|
export type MonacoEditorId = string;
|
||||||
|
|
||||||
|
|||||||
@ -6,7 +6,7 @@ import React from "react";
|
|||||||
import "@testing-library/jest-dom/extend-expect";
|
import "@testing-library/jest-dom/extend-expect";
|
||||||
import { Select } from "./select";
|
import { Select } from "./select";
|
||||||
import { UserStore } from "../../../common/user-store";
|
import { UserStore } from "../../../common/user-store";
|
||||||
import { ThemeStore } from "../../theme.store";
|
import { ThemeStore } from "../../themes/store";
|
||||||
import { getDiForUnitTesting } from "../../getDiForUnitTesting";
|
import { getDiForUnitTesting } from "../../getDiForUnitTesting";
|
||||||
import type { DiContainer } from "@ogre-tools/injectable";
|
import type { DiContainer } from "@ogre-tools/injectable";
|
||||||
import { DiRender, renderFor } from "../test-utils/renderFor";
|
import { DiRender, renderFor } from "../test-utils/renderFor";
|
||||||
|
|||||||
@ -15,7 +15,7 @@ import ReactSelectCreatable from "react-select/creatable";
|
|||||||
import type { ActionMeta, OptionTypeBase, Props as ReactSelectProps, Styles } from "react-select";
|
import type { ActionMeta, OptionTypeBase, Props as ReactSelectProps, Styles } from "react-select";
|
||||||
import type { CreatableProps } from "react-select/creatable";
|
import type { CreatableProps } from "react-select/creatable";
|
||||||
|
|
||||||
import { ThemeStore } from "../../theme.store";
|
import { ThemeStore } from "../../themes/store";
|
||||||
import { boundMethod, cssNames } from "../../utils";
|
import { boundMethod, cssNames } from "../../utils";
|
||||||
|
|
||||||
const { Menu } = components;
|
const { Menu } = components;
|
||||||
|
|||||||
@ -1,148 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
|
||||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import { comparer, computed, makeObservable, observable, reaction } from "mobx";
|
|
||||||
import { autoBind, Singleton } from "./utils";
|
|
||||||
import { UserStore } from "../common/user-store";
|
|
||||||
import logger from "../main/logger";
|
|
||||||
import lensDarkThemeJson from "./themes/lens-dark.json";
|
|
||||||
import lensLightThemeJson from "./themes/lens-light.json";
|
|
||||||
import type { SelectOption } from "./components/select";
|
|
||||||
import type { MonacoEditorProps } from "./components/monaco-editor";
|
|
||||||
import { defaultTheme } from "../common/vars";
|
|
||||||
import { camelCase } from "lodash";
|
|
||||||
import { ipcRenderer } from "electron";
|
|
||||||
import { getNativeThemeChannel, setNativeThemeChannel } from "../common/ipc/native-theme";
|
|
||||||
|
|
||||||
export type ThemeId = string;
|
|
||||||
|
|
||||||
export interface Theme {
|
|
||||||
name: string;
|
|
||||||
type: "dark" | "light";
|
|
||||||
colors: Record<string, string>;
|
|
||||||
description: string;
|
|
||||||
author: string;
|
|
||||||
monacoTheme: MonacoEditorProps["theme"];
|
|
||||||
}
|
|
||||||
|
|
||||||
export class ThemeStore extends Singleton {
|
|
||||||
private terminalColorPrefix = "terminal";
|
|
||||||
|
|
||||||
// bundled themes from `themes/${themeId}.json`
|
|
||||||
private themes = observable.map<ThemeId, Theme>({
|
|
||||||
"lens-dark": lensDarkThemeJson as Theme,
|
|
||||||
"lens-light": lensLightThemeJson as Theme,
|
|
||||||
});
|
|
||||||
|
|
||||||
@observable osNativeTheme: "dark" | "light" | undefined;
|
|
||||||
|
|
||||||
@computed get activeThemeId(): ThemeId {
|
|
||||||
return UserStore.getInstance().colorTheme;
|
|
||||||
}
|
|
||||||
|
|
||||||
@computed get terminalThemeId(): ThemeId {
|
|
||||||
return UserStore.getInstance().terminalTheme;
|
|
||||||
}
|
|
||||||
|
|
||||||
@computed get activeTheme(): Theme {
|
|
||||||
return this.systemTheme ?? this.themes.get(this.activeThemeId) ?? this.themes.get(defaultTheme);
|
|
||||||
}
|
|
||||||
|
|
||||||
@computed get terminalColors(): [string, string][] {
|
|
||||||
const theme = this.themes.get(this.terminalThemeId) ?? this.activeTheme;
|
|
||||||
|
|
||||||
return Object
|
|
||||||
.entries(theme.colors)
|
|
||||||
.filter(([name]) => name.startsWith(this.terminalColorPrefix));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Replacing keys stored in styles to format accepted by terminal
|
|
||||||
// E.g. terminalBrightBlack -> brightBlack
|
|
||||||
@computed get xtermColors(): Record<string, string> {
|
|
||||||
return Object.fromEntries(
|
|
||||||
this.terminalColors.map(([name, color]) => [
|
|
||||||
camelCase(name.replace(this.terminalColorPrefix, "")),
|
|
||||||
color,
|
|
||||||
]),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
@computed get themeOptions(): SelectOption<string>[] {
|
|
||||||
return Array.from(this.themes).map(([themeId, theme]) => ({
|
|
||||||
label: theme.name,
|
|
||||||
value: themeId,
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
|
||||||
@computed get systemTheme() {
|
|
||||||
if (this.activeThemeId == "system" && this.osNativeTheme) {
|
|
||||||
return this.themes.get(`lens-${this.osNativeTheme}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
constructor() {
|
|
||||||
super();
|
|
||||||
|
|
||||||
makeObservable(this);
|
|
||||||
autoBind(this);
|
|
||||||
this.init();
|
|
||||||
}
|
|
||||||
|
|
||||||
async init() {
|
|
||||||
await this.setNativeTheme();
|
|
||||||
this.bindNativeThemeUpdateEvent();
|
|
||||||
|
|
||||||
// auto-apply active theme
|
|
||||||
reaction(() => ({
|
|
||||||
themeId: this.activeThemeId,
|
|
||||||
terminalThemeId: this.terminalThemeId,
|
|
||||||
}), ({ themeId }) => {
|
|
||||||
try {
|
|
||||||
this.applyTheme(themeId);
|
|
||||||
} catch (err) {
|
|
||||||
logger.error(err);
|
|
||||||
UserStore.getInstance().resetTheme();
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
fireImmediately: true,
|
|
||||||
equals: comparer.shallow,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
bindNativeThemeUpdateEvent() {
|
|
||||||
ipcRenderer.on(setNativeThemeChannel, (event, theme: "dark" | "light") => {
|
|
||||||
this.osNativeTheme = theme;
|
|
||||||
this.applyTheme(theme);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
async setNativeTheme() {
|
|
||||||
const theme: "dark" | "light" = await ipcRenderer.invoke(getNativeThemeChannel);
|
|
||||||
|
|
||||||
this.osNativeTheme = theme;
|
|
||||||
}
|
|
||||||
|
|
||||||
getThemeById(themeId: ThemeId): Theme {
|
|
||||||
return this.themes.get(themeId);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected applyTheme(themeId: ThemeId) {
|
|
||||||
const theme = this.systemTheme ?? this.getThemeById(themeId);
|
|
||||||
|
|
||||||
const colors = Object.entries({
|
|
||||||
...theme.colors,
|
|
||||||
...Object.fromEntries(this.terminalColors),
|
|
||||||
});
|
|
||||||
|
|
||||||
colors.forEach(([name, value]) => {
|
|
||||||
document.documentElement.style.setProperty(`--${name}`, value);
|
|
||||||
});
|
|
||||||
|
|
||||||
// Adding universal theme flag which can be used in component styles
|
|
||||||
document.body.classList.toggle("theme-light", theme.type === "light");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,4 +1,11 @@
|
|||||||
{
|
/**
|
||||||
|
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||||
|
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import type { Theme } from "./types";
|
||||||
|
|
||||||
|
const lensDarkTheme: Theme = {
|
||||||
"name": "Dark",
|
"name": "Dark",
|
||||||
"type": "dark",
|
"type": "dark",
|
||||||
"description": "Original Lens dark theme",
|
"description": "Original Lens dark theme",
|
||||||
@ -136,6 +143,8 @@
|
|||||||
"navSelectedBackground": "#262b2e",
|
"navSelectedBackground": "#262b2e",
|
||||||
"navHoverColor": "#dcddde",
|
"navHoverColor": "#dcddde",
|
||||||
"hrColor": "#ffffff0f",
|
"hrColor": "#ffffff0f",
|
||||||
"tooltipBackground": "#18191c"
|
"tooltipBackground": "#18191c",
|
||||||
}
|
},
|
||||||
}
|
};
|
||||||
|
|
||||||
|
export default lensDarkTheme;
|
||||||
@ -1,141 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "Light",
|
|
||||||
"type": "light",
|
|
||||||
"description": "Original Lens light theme",
|
|
||||||
"author": "Mirantis",
|
|
||||||
"monacoTheme": "vs",
|
|
||||||
"colors": {
|
|
||||||
"blue": "#3d90ce",
|
|
||||||
"magenta": "#c93dce",
|
|
||||||
"golden": "#ffc63d",
|
|
||||||
"halfGray": "#87909c80",
|
|
||||||
"primary": "#3d90ce",
|
|
||||||
"textColorPrimary": "#555555",
|
|
||||||
"textColorSecondary": "#51575d",
|
|
||||||
"textColorTertiary": "#555555",
|
|
||||||
"textColorAccent": "#222222",
|
|
||||||
"textColorDimmed": "#5557598c",
|
|
||||||
"borderColor": "#c9cfd3",
|
|
||||||
"borderFaintColor": "#dfdfdf",
|
|
||||||
"mainBackground": "#f1f1f1",
|
|
||||||
"secondaryBackground": "#f2f3f5",
|
|
||||||
"contentColor": "#ffffff",
|
|
||||||
"layoutBackground": "#e8e8e8",
|
|
||||||
"layoutTabsBackground": "#f8f8f8",
|
|
||||||
"layoutTabsActiveColor": "#333333",
|
|
||||||
"layoutTabsLineColor": "#87909c80",
|
|
||||||
"sidebarLogoBackground": "#f1f1f1",
|
|
||||||
"sidebarActiveColor": "#ffffff",
|
|
||||||
"sidebarSubmenuActiveColor": "#3d90ce",
|
|
||||||
"sidebarBackground": "#e8e8e8",
|
|
||||||
"sidebarItemHoverBackground": "#f0f2f5",
|
|
||||||
"buttonPrimaryBackground": "#3d90ce",
|
|
||||||
"buttonDefaultBackground": "#414448",
|
|
||||||
"buttonLightBackground": "#f1f1f1",
|
|
||||||
"buttonAccentBackground": "#e85555",
|
|
||||||
"buttonDisabledBackground": "#808080",
|
|
||||||
"tableBgcStripe": "#f8f8f8",
|
|
||||||
"tableBgcSelected": "#f4f5f5",
|
|
||||||
"tableHeaderBackground": "#f1f1f1",
|
|
||||||
"tableHeaderBorderWidth": "2px",
|
|
||||||
"tableHeaderBorderColor": "#3d90ce",
|
|
||||||
"tableHeaderColor": "#555555",
|
|
||||||
"tableSelectedRowColor": "#222222",
|
|
||||||
"helmLogoBackground": "#ffffff",
|
|
||||||
"helmImgBackground": "#e8e8e8",
|
|
||||||
"helmStableRepo": "#3d90ce",
|
|
||||||
"helmIncubatorRepo": "#ff7043",
|
|
||||||
"helmDescriptionHr": "#dddddd",
|
|
||||||
"helmDescriptionBlockquoteColor": "#555555",
|
|
||||||
"helmDescriptionBlockquoteBorder": "#8a8f93",
|
|
||||||
"helmDescriptionBlockquoteBackground": "#eeeeee",
|
|
||||||
"helmDescriptionHeaders": "#3e4147",
|
|
||||||
"helmDescriptionH6": "#6a737d",
|
|
||||||
"helmDescriptionTdBorder": "#c6c6c6",
|
|
||||||
"helmDescriptionTrBackground": "#1c2125",
|
|
||||||
"helmDescriptionCodeBackground": "#ffffff1a",
|
|
||||||
"helmDescriptionPreBackground": "#eeeeee",
|
|
||||||
"helmDescriptionPreColor": "#555555",
|
|
||||||
"colorSuccess": "#206923",
|
|
||||||
"colorOk": "#399c3d",
|
|
||||||
"colorInfo": "#2d71a4",
|
|
||||||
"colorError": "#ce3933",
|
|
||||||
"colorSoftError": "#e85555",
|
|
||||||
"colorWarning": "#ff9800",
|
|
||||||
"colorVague": "#ededed",
|
|
||||||
"colorTerminated": "#9dabb5",
|
|
||||||
"dockHeadBackground": "#e8e8e8",
|
|
||||||
"dockInfoBackground": "#f3f3f3",
|
|
||||||
"dockInfoBorderColor": "#c9cfd3",
|
|
||||||
"dockEditorBackground": "#24292e",
|
|
||||||
"dockEditorTag": "#8e97a3",
|
|
||||||
"dockEditorKeyword": "#ffffff",
|
|
||||||
"dockEditorComment": "#808080",
|
|
||||||
"dockEditorActiveLineBackground": "#3a3d41",
|
|
||||||
"dockBadgeBackground": "#dedede",
|
|
||||||
"dockTabBorderColor": "#d5d4de",
|
|
||||||
"dockTabActiveBackground": "#ffffff",
|
|
||||||
"logsBackground": "#24292e",
|
|
||||||
"logsForeground": "#ffffff",
|
|
||||||
"logRowHoverBackground": "#35373a",
|
|
||||||
"terminalBackground": "#ffffff",
|
|
||||||
"terminalForeground": "#2d2d2d",
|
|
||||||
"terminalCursor": "#2d2d2d",
|
|
||||||
"terminalCursorAccent": "#ffffff",
|
|
||||||
"terminalSelection": "#bfbfbf",
|
|
||||||
"terminalBlack": "#2d2d2d",
|
|
||||||
"terminalRed": "#cd3734 ",
|
|
||||||
"terminalGreen": "#18cf12",
|
|
||||||
"terminalYellow": "#acb300",
|
|
||||||
"terminalBlue": "#3d90ce",
|
|
||||||
"terminalMagenta": "#c100cd",
|
|
||||||
"terminalCyan": "#07c4b9",
|
|
||||||
"terminalWhite": "#d3d7cf",
|
|
||||||
"terminalBrightBlack": "#a8a8a8",
|
|
||||||
"terminalBrightRed": "#ff6259",
|
|
||||||
"terminalBrightGreen": "#5cdb59",
|
|
||||||
"terminalBrightYellow": "#f8c000",
|
|
||||||
"terminalBrightBlue": "#008db6",
|
|
||||||
"terminalBrightMagenta": "#ee55f8",
|
|
||||||
"terminalBrightCyan": "#50e8df",
|
|
||||||
"terminalBrightWhite": "#eeeeec",
|
|
||||||
"dialogTextColor": "#87909c",
|
|
||||||
"dialogBackground": "#ffffff",
|
|
||||||
"dialogHeaderBackground": "#36393e",
|
|
||||||
"dialogFooterBackground": "#f4f4f4",
|
|
||||||
"drawerTogglerBackground": "#eaeced",
|
|
||||||
"drawerTitleText": "#ffffff",
|
|
||||||
"drawerSubtitleBackground": "#f1f1f1",
|
|
||||||
"drawerItemNameColor": "#727272",
|
|
||||||
"drawerItemValueColor": "#555555",
|
|
||||||
"clusterMenuBackground": "#d7d8da",
|
|
||||||
"clusterMenuBorderColor": "#c9cfd3",
|
|
||||||
"clusterMenuCellBackground": "#bbbbbb",
|
|
||||||
"clusterSettingsBackground": "#ffffff",
|
|
||||||
"addClusterIconColor": "#8d8d8d",
|
|
||||||
"boxShadow": "#0000003a",
|
|
||||||
"iconActiveColor": "#ffffff",
|
|
||||||
"iconActiveBackground": "#a6a6a694",
|
|
||||||
"filterAreaBackground": "#f7f7f7",
|
|
||||||
"chartLiveBarBackground": "#00000033",
|
|
||||||
"chartStripesColor": "#00000009",
|
|
||||||
"chartCapacityColor": "#cccccc",
|
|
||||||
"pieChartDefaultColor": "#efefef",
|
|
||||||
"inputOptionHoverColor": "#ffffff",
|
|
||||||
"inputControlBackground": "#f6f6f7",
|
|
||||||
"inputControlBorder": "#cccdcf",
|
|
||||||
"inputControlHoverBorder": "#b9bbbe",
|
|
||||||
"lineProgressBackground": "#e8e8e8",
|
|
||||||
"radioActiveBackground": "#f1f1f1",
|
|
||||||
"menuActiveBackground": "#3d90ce",
|
|
||||||
"menuSelectedOptionBgc": "#e8e8e8",
|
|
||||||
"canvasBackground": "#24292e",
|
|
||||||
"scrollBarColor": "#bbbbbb",
|
|
||||||
"settingsBackground": "#ffffff",
|
|
||||||
"settingsColor": "#555555",
|
|
||||||
"navSelectedBackground": "#ffffff",
|
|
||||||
"navHoverColor": "#2e3135",
|
|
||||||
"hrColor": "#06060714",
|
|
||||||
"tooltipBackground": "#ffffff"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
150
src/renderer/themes/lens-light.ts
Normal file
150
src/renderer/themes/lens-light.ts
Normal file
@ -0,0 +1,150 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||||
|
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import type { Theme } from "./types";
|
||||||
|
|
||||||
|
const lensLightTheme: Theme = {
|
||||||
|
name: "Light",
|
||||||
|
type: "light",
|
||||||
|
description: "Original Lens light theme",
|
||||||
|
author: "Mirantis",
|
||||||
|
monacoTheme: "vs",
|
||||||
|
colors: {
|
||||||
|
blue: "#3d90ce",
|
||||||
|
magenta: "#c93dce",
|
||||||
|
golden: "#ffc63d",
|
||||||
|
halfGray: "#87909c80",
|
||||||
|
primary: "#3d90ce",
|
||||||
|
textColorPrimary: "#555555",
|
||||||
|
textColorSecondary: "#51575d",
|
||||||
|
textColorTertiary: "#555555",
|
||||||
|
textColorAccent: "#222222",
|
||||||
|
textColorDimmed: "#5557598c",
|
||||||
|
borderColor: "#c9cfd3",
|
||||||
|
borderFaintColor: "#dfdfdf",
|
||||||
|
mainBackground: "#f1f1f1",
|
||||||
|
secondaryBackground: "#f2f3f5",
|
||||||
|
contentColor: "#ffffff",
|
||||||
|
layoutBackground: "#e8e8e8",
|
||||||
|
layoutTabsBackground: "#f8f8f8",
|
||||||
|
layoutTabsActiveColor: "#333333",
|
||||||
|
layoutTabsLineColor: "#87909c80",
|
||||||
|
sidebarLogoBackground: "#f1f1f1",
|
||||||
|
sidebarActiveColor: "#ffffff",
|
||||||
|
sidebarSubmenuActiveColor: "#3d90ce",
|
||||||
|
sidebarBackground: "#e8e8e8",
|
||||||
|
sidebarItemHoverBackground: "#f0f2f5",
|
||||||
|
buttonPrimaryBackground: "#3d90ce",
|
||||||
|
buttonDefaultBackground: "#414448",
|
||||||
|
buttonLightBackground: "#f1f1f1",
|
||||||
|
buttonAccentBackground: "#e85555",
|
||||||
|
buttonDisabledBackground: "#808080",
|
||||||
|
tableBgcStripe: "#f8f8f8",
|
||||||
|
tableBgcSelected: "#f4f5f5",
|
||||||
|
tableHeaderBackground: "#f1f1f1",
|
||||||
|
tableHeaderBorderWidth: "2px",
|
||||||
|
tableHeaderBorderColor: "#3d90ce",
|
||||||
|
tableHeaderColor: "#555555",
|
||||||
|
tableSelectedRowColor: "#222222",
|
||||||
|
helmLogoBackground: "#ffffff",
|
||||||
|
helmImgBackground: "#e8e8e8",
|
||||||
|
helmStableRepo: "#3d90ce",
|
||||||
|
helmIncubatorRepo: "#ff7043",
|
||||||
|
helmDescriptionHr: "#dddddd",
|
||||||
|
helmDescriptionBlockquoteColor: "#555555",
|
||||||
|
helmDescriptionBlockquoteBorder: "#8a8f93",
|
||||||
|
helmDescriptionBlockquoteBackground: "#eeeeee",
|
||||||
|
helmDescriptionHeaders: "#3e4147",
|
||||||
|
helmDescriptionH6: "#6a737d",
|
||||||
|
helmDescriptionTdBorder: "#c6c6c6",
|
||||||
|
helmDescriptionTrBackground: "#1c2125",
|
||||||
|
helmDescriptionCodeBackground: "#ffffff1a",
|
||||||
|
helmDescriptionPreBackground: "#eeeeee",
|
||||||
|
helmDescriptionPreColor: "#555555",
|
||||||
|
colorSuccess: "#206923",
|
||||||
|
colorOk: "#399c3d",
|
||||||
|
colorInfo: "#2d71a4",
|
||||||
|
colorError: "#ce3933",
|
||||||
|
colorSoftError: "#e85555",
|
||||||
|
colorWarning: "#ff9800",
|
||||||
|
colorVague: "#ededed",
|
||||||
|
colorTerminated: "#9dabb5",
|
||||||
|
dockHeadBackground: "#e8e8e8",
|
||||||
|
dockInfoBackground: "#f3f3f3",
|
||||||
|
dockInfoBorderColor: "#c9cfd3",
|
||||||
|
dockEditorBackground: "#24292e",
|
||||||
|
dockEditorTag: "#8e97a3",
|
||||||
|
dockEditorKeyword: "#ffffff",
|
||||||
|
dockEditorComment: "#808080",
|
||||||
|
dockEditorActiveLineBackground: "#3a3d41",
|
||||||
|
dockBadgeBackground: "#dedede",
|
||||||
|
dockTabBorderColor: "#d5d4de",
|
||||||
|
dockTabActiveBackground: "#ffffff",
|
||||||
|
logsBackground: "#24292e",
|
||||||
|
logsForeground: "#ffffff",
|
||||||
|
logRowHoverBackground: "#35373a",
|
||||||
|
terminalBackground: "#ffffff",
|
||||||
|
terminalForeground: "#2d2d2d",
|
||||||
|
terminalCursor: "#2d2d2d",
|
||||||
|
terminalCursorAccent: "#ffffff",
|
||||||
|
terminalSelection: "#bfbfbf",
|
||||||
|
terminalBlack: "#2d2d2d",
|
||||||
|
terminalRed: "#cd3734 ",
|
||||||
|
terminalGreen: "#18cf12",
|
||||||
|
terminalYellow: "#acb300",
|
||||||
|
terminalBlue: "#3d90ce",
|
||||||
|
terminalMagenta: "#c100cd",
|
||||||
|
terminalCyan: "#07c4b9",
|
||||||
|
terminalWhite: "#d3d7cf",
|
||||||
|
terminalBrightBlack: "#a8a8a8",
|
||||||
|
terminalBrightRed: "#ff6259",
|
||||||
|
terminalBrightGreen: "#5cdb59",
|
||||||
|
terminalBrightYellow: "#f8c000",
|
||||||
|
terminalBrightBlue: "#008db6",
|
||||||
|
terminalBrightMagenta: "#ee55f8",
|
||||||
|
terminalBrightCyan: "#50e8df",
|
||||||
|
terminalBrightWhite: "#eeeeec",
|
||||||
|
dialogTextColor: "#87909c",
|
||||||
|
dialogBackground: "#ffffff",
|
||||||
|
dialogHeaderBackground: "#36393e",
|
||||||
|
dialogFooterBackground: "#f4f4f4",
|
||||||
|
drawerTogglerBackground: "#eaeced",
|
||||||
|
drawerTitleText: "#ffffff",
|
||||||
|
drawerSubtitleBackground: "#f1f1f1",
|
||||||
|
drawerItemNameColor: "#727272",
|
||||||
|
drawerItemValueColor: "#555555",
|
||||||
|
clusterMenuBackground: "#d7d8da",
|
||||||
|
clusterMenuBorderColor: "#c9cfd3",
|
||||||
|
clusterMenuCellBackground: "#bbbbbb",
|
||||||
|
clusterSettingsBackground: "#ffffff",
|
||||||
|
addClusterIconColor: "#8d8d8d",
|
||||||
|
boxShadow: "#0000003a",
|
||||||
|
iconActiveColor: "#ffffff",
|
||||||
|
iconActiveBackground: "#a6a6a694",
|
||||||
|
filterAreaBackground: "#f7f7f7",
|
||||||
|
chartLiveBarBackground: "#00000033",
|
||||||
|
chartStripesColor: "#00000009",
|
||||||
|
chartCapacityColor: "#cccccc",
|
||||||
|
pieChartDefaultColor: "#efefef",
|
||||||
|
inputOptionHoverColor: "#ffffff",
|
||||||
|
inputControlBackground: "#f6f6f7",
|
||||||
|
inputControlBorder: "#cccdcf",
|
||||||
|
inputControlHoverBorder: "#b9bbbe",
|
||||||
|
lineProgressBackground: "#e8e8e8",
|
||||||
|
radioActiveBackground: "#f1f1f1",
|
||||||
|
menuActiveBackground: "#3d90ce",
|
||||||
|
menuSelectedOptionBgc: "#e8e8e8",
|
||||||
|
canvasBackground: "#24292e",
|
||||||
|
scrollBarColor: "#bbbbbb",
|
||||||
|
settingsBackground: "#ffffff",
|
||||||
|
settingsColor: "#555555",
|
||||||
|
navSelectedBackground: "#ffffff",
|
||||||
|
navHoverColor: "#2e3135",
|
||||||
|
hrColor: "#06060714",
|
||||||
|
tooltipBackground: "#ffffff",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export default lensLightTheme;
|
||||||
@ -3,7 +3,7 @@
|
|||||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||||
*/
|
*/
|
||||||
import { getInjectable } from "@ogre-tools/injectable";
|
import { getInjectable } from "@ogre-tools/injectable";
|
||||||
import { ThemeStore } from "./theme.store";
|
import { ThemeStore } from "./store";
|
||||||
|
|
||||||
const themeStoreInjectable = getInjectable({
|
const themeStoreInjectable = getInjectable({
|
||||||
id: "theme-store",
|
id: "theme-store",
|
||||||
177
src/renderer/themes/store.ts
Normal file
177
src/renderer/themes/store.ts
Normal file
@ -0,0 +1,177 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||||
|
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { comparer, computed, makeObservable, observable, reaction } from "mobx";
|
||||||
|
import { autoBind, entries, fromEntries, Singleton, startsWith } from "../utils";
|
||||||
|
import { UserStore } from "../../common/user-store";
|
||||||
|
import logger from "../../main/logger";
|
||||||
|
import lensDarkThemeJson from "./lens-dark";
|
||||||
|
import lensLightThemeJson from "./lens-light";
|
||||||
|
import { ipcRenderer } from "electron";
|
||||||
|
import { getNativeThemeChannel, setNativeThemeChannel } from "../../common/ipc/native-theme";
|
||||||
|
import { Theme, ThemeId, TerminalColors, ThemeType, terminalColorPrefix, PrefixedTerminalColorPair } from "./types";
|
||||||
|
import { camelCase } from "lodash/fp";
|
||||||
|
import assert from "assert";
|
||||||
|
|
||||||
|
const themeNameExtractor = /$(?<name>.+)-(dark|light)^/;
|
||||||
|
|
||||||
|
export const themeTypeOptions = [
|
||||||
|
{
|
||||||
|
value: "dark",
|
||||||
|
label: "Dark",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: "light",
|
||||||
|
label: "Light",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
export class ThemeStore extends Singleton {
|
||||||
|
private themes = observable.map<ThemeId, Theme>({
|
||||||
|
"lens-dark": lensDarkThemeJson,
|
||||||
|
"lens-light": lensLightThemeJson,
|
||||||
|
});
|
||||||
|
|
||||||
|
@computed get themeNames(): string[] {
|
||||||
|
const names = new Set<string>();
|
||||||
|
|
||||||
|
for (const themeId of this.themes.keys()) {
|
||||||
|
const match = themeId.match(themeNameExtractor);
|
||||||
|
|
||||||
|
assert(match, "All ThemeId's MUST have a suffix of '-dark' or '-light'");
|
||||||
|
|
||||||
|
names.add(match.groups.name);
|
||||||
|
}
|
||||||
|
|
||||||
|
return [...names];
|
||||||
|
}
|
||||||
|
|
||||||
|
@observable osNativeTheme: ThemeType = "dark";
|
||||||
|
|
||||||
|
@computed get activeThemeType(): ThemeType {
|
||||||
|
const { colorTheme } = UserStore.getInstance();
|
||||||
|
|
||||||
|
if (colorTheme.followSystemThemeType === true) {
|
||||||
|
return this.osNativeTheme;
|
||||||
|
}
|
||||||
|
|
||||||
|
return colorTheme.type;
|
||||||
|
}
|
||||||
|
|
||||||
|
@computed get activeThemeName(): string {
|
||||||
|
const { colorTheme } = UserStore.getInstance();
|
||||||
|
|
||||||
|
return colorTheme.name;
|
||||||
|
}
|
||||||
|
|
||||||
|
@computed get activeThemeId(): ThemeId {
|
||||||
|
return `${this.activeThemeName}-${this.activeThemeType}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
@computed get activeTheme(): Theme {
|
||||||
|
return this.themes.get(this.activeThemeId) ?? lensDarkThemeJson;
|
||||||
|
}
|
||||||
|
|
||||||
|
@computed get activeTerminalThemeType(): ThemeType {
|
||||||
|
const { terminalTheme } = UserStore.getInstance();
|
||||||
|
|
||||||
|
if (terminalTheme.isGlobalThemeType === true) {
|
||||||
|
return this.activeThemeType;
|
||||||
|
}
|
||||||
|
|
||||||
|
return terminalTheme.type;
|
||||||
|
}
|
||||||
|
|
||||||
|
@computed get activeTerminalThemeName(): string {
|
||||||
|
const { terminalTheme } = UserStore.getInstance();
|
||||||
|
|
||||||
|
if (terminalTheme.isGlobalTheme === true) {
|
||||||
|
return this.activeThemeName;
|
||||||
|
}
|
||||||
|
|
||||||
|
return terminalTheme.name;
|
||||||
|
}
|
||||||
|
|
||||||
|
@computed get terminalThemeId(): ThemeId {
|
||||||
|
return `${this.activeTerminalThemeName}-${this.activeTerminalThemeType}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
@computed get activeTerminalTheme(): Theme {
|
||||||
|
return this.themes.get(this.terminalThemeId) ?? lensDarkThemeJson;
|
||||||
|
}
|
||||||
|
|
||||||
|
@computed private get terminalThemeColors(): PrefixedTerminalColorPair[] {
|
||||||
|
const theme = this.activeTerminalTheme;
|
||||||
|
|
||||||
|
return entries(theme.colors)
|
||||||
|
.filter((value): value is PrefixedTerminalColorPair => (
|
||||||
|
startsWith(value[0], terminalColorPrefix)
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
@computed get xtermColors(): TerminalColors {
|
||||||
|
return fromEntries(
|
||||||
|
this.terminalThemeColors
|
||||||
|
.map(([name, color]) => [
|
||||||
|
camelCase(name.slice(terminalColorPrefix.length)) as keyof TerminalColors,
|
||||||
|
color,
|
||||||
|
]),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
makeObservable(this);
|
||||||
|
autoBind(this);
|
||||||
|
this.init();
|
||||||
|
}
|
||||||
|
|
||||||
|
async init() {
|
||||||
|
await this.setNativeTheme();
|
||||||
|
this.bindNativeThemeUpdateEvent();
|
||||||
|
|
||||||
|
// auto-apply active theme
|
||||||
|
reaction(() => ({
|
||||||
|
theme: this.activeTheme,
|
||||||
|
terminalTheme: this.terminalThemeColors,
|
||||||
|
}), (themes) => {
|
||||||
|
try {
|
||||||
|
this.applyTheme(themes);
|
||||||
|
} catch (err) {
|
||||||
|
logger.error(err);
|
||||||
|
UserStore.getInstance().resetThemeSettings();
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
fireImmediately: true,
|
||||||
|
equals: comparer.shallow,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
bindNativeThemeUpdateEvent() {
|
||||||
|
ipcRenderer.on(setNativeThemeChannel, (event, theme: ThemeType) => {
|
||||||
|
this.osNativeTheme = theme;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async setNativeTheme() {
|
||||||
|
const theme: "dark" | "light" = await ipcRenderer.invoke(getNativeThemeChannel);
|
||||||
|
|
||||||
|
this.osNativeTheme = theme;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected applyTheme({ theme, terminalTheme }: { theme: Theme; terminalTheme: PrefixedTerminalColorPair[] }) {
|
||||||
|
const colors = Object.entries({
|
||||||
|
...theme.colors,
|
||||||
|
...Object.fromEntries(terminalTheme),
|
||||||
|
});
|
||||||
|
|
||||||
|
colors.forEach(([name, value]) => {
|
||||||
|
document.documentElement.style.setProperty(`--${name}`, value);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Adding universal theme flag which can be used in component styles
|
||||||
|
document.body.classList.toggle("theme-light", theme.type === "light");
|
||||||
|
}
|
||||||
|
}
|
||||||
164
src/renderer/themes/types.ts
Normal file
164
src/renderer/themes/types.ts
Normal file
@ -0,0 +1,164 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||||
|
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import type { PrefixCamelCasedProperties } from "../../common/utils/types";
|
||||||
|
import type { MonacoTheme } from "../components/monaco-editor";
|
||||||
|
|
||||||
|
export type ThemeType = "dark" | "light";
|
||||||
|
export type ThemeId = `${string}-${ThemeType}`;
|
||||||
|
export type ThemeColor = `#${string}`;
|
||||||
|
export type ThemeLengthUnit = "px" | "ch" | "em" | "ex" | "rem" | "vh" | "vw" | "vmin" | "vmax" | "cm" | "mm" | "in" | "pc" | "pt";
|
||||||
|
export type ThemeLength = `${string}${ThemeLengthUnit}`;
|
||||||
|
|
||||||
|
export interface TerminalColors {
|
||||||
|
background: ThemeColor;
|
||||||
|
foreground: ThemeColor;
|
||||||
|
cursor: ThemeColor;
|
||||||
|
cursorAccent: ThemeColor;
|
||||||
|
selection: ThemeColor;
|
||||||
|
black: ThemeColor;
|
||||||
|
red: ThemeColor;
|
||||||
|
green: ThemeColor;
|
||||||
|
yellow: ThemeColor;
|
||||||
|
blue: ThemeColor;
|
||||||
|
magenta: ThemeColor;
|
||||||
|
cyan: ThemeColor;
|
||||||
|
white: ThemeColor;
|
||||||
|
brightBlack: ThemeColor;
|
||||||
|
brightRed: ThemeColor;
|
||||||
|
brightGreen: ThemeColor;
|
||||||
|
brightYellow: ThemeColor;
|
||||||
|
brightBlue: ThemeColor;
|
||||||
|
brightMagenta: ThemeColor;
|
||||||
|
brightCyan: ThemeColor;
|
||||||
|
brightWhite: ThemeColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const terminalColorPrefix = "terminal";
|
||||||
|
export type PrefixedTerminalColors = PrefixCamelCasedProperties<TerminalColors, typeof terminalColorPrefix>;
|
||||||
|
export type PrefixedTerminalColorPair = [keyof PrefixedTerminalColors, ThemeColor];
|
||||||
|
|
||||||
|
export interface ThemeColors extends PrefixedTerminalColors {
|
||||||
|
blue: ThemeColor;
|
||||||
|
magenta: ThemeColor;
|
||||||
|
golden: ThemeColor;
|
||||||
|
halfGray: ThemeColor;
|
||||||
|
primary: ThemeColor;
|
||||||
|
textColorPrimary: ThemeColor;
|
||||||
|
textColorSecondary: ThemeColor;
|
||||||
|
textColorTertiary: ThemeColor;
|
||||||
|
textColorAccent: ThemeColor;
|
||||||
|
textColorDimmed: ThemeColor;
|
||||||
|
borderColor: ThemeColor;
|
||||||
|
borderFaintColor: ThemeColor;
|
||||||
|
mainBackground: ThemeColor;
|
||||||
|
secondaryBackground: ThemeColor;
|
||||||
|
contentColor: ThemeColor;
|
||||||
|
layoutBackground: ThemeColor;
|
||||||
|
layoutTabsBackground: ThemeColor;
|
||||||
|
layoutTabsActiveColor: ThemeColor;
|
||||||
|
layoutTabsLineColor: ThemeColor;
|
||||||
|
sidebarLogoBackground: ThemeColor;
|
||||||
|
sidebarActiveColor: ThemeColor;
|
||||||
|
sidebarSubmenuActiveColor: ThemeColor;
|
||||||
|
sidebarBackground: ThemeColor;
|
||||||
|
sidebarItemHoverBackground: ThemeColor;
|
||||||
|
buttonPrimaryBackground: ThemeColor;
|
||||||
|
buttonDefaultBackground: ThemeColor;
|
||||||
|
buttonLightBackground: ThemeColor;
|
||||||
|
buttonAccentBackground: ThemeColor;
|
||||||
|
buttonDisabledBackground: ThemeColor;
|
||||||
|
tableBgcStripe: ThemeColor;
|
||||||
|
tableBgcSelected: ThemeColor;
|
||||||
|
tableHeaderBackground: ThemeColor;
|
||||||
|
tableHeaderBorderWidth: string;
|
||||||
|
tableHeaderBorderColor: ThemeColor;
|
||||||
|
tableHeaderColor: ThemeColor;
|
||||||
|
tableSelectedRowColor: ThemeColor;
|
||||||
|
helmLogoBackground: ThemeColor;
|
||||||
|
helmImgBackground: ThemeColor;
|
||||||
|
helmStableRepo: ThemeColor;
|
||||||
|
helmIncubatorRepo: ThemeColor;
|
||||||
|
helmDescriptionHr: ThemeColor;
|
||||||
|
helmDescriptionBlockquoteColor: ThemeColor;
|
||||||
|
helmDescriptionBlockquoteBorder: ThemeColor;
|
||||||
|
helmDescriptionBlockquoteBackground: ThemeColor;
|
||||||
|
helmDescriptionHeaders: ThemeColor;
|
||||||
|
helmDescriptionH6: ThemeColor;
|
||||||
|
helmDescriptionTdBorder: ThemeColor;
|
||||||
|
helmDescriptionTrBackground: ThemeColor;
|
||||||
|
helmDescriptionCodeBackground: ThemeColor;
|
||||||
|
helmDescriptionPreBackground: ThemeColor;
|
||||||
|
helmDescriptionPreColor: ThemeColor;
|
||||||
|
colorSuccess: ThemeColor;
|
||||||
|
colorOk: ThemeColor;
|
||||||
|
colorInfo: ThemeColor;
|
||||||
|
colorError: ThemeColor;
|
||||||
|
colorSoftError: ThemeColor;
|
||||||
|
colorWarning: ThemeColor;
|
||||||
|
colorVague: ThemeColor;
|
||||||
|
colorTerminated: ThemeColor;
|
||||||
|
dockHeadBackground: ThemeColor;
|
||||||
|
dockInfoBackground: ThemeColor;
|
||||||
|
dockInfoBorderColor: ThemeColor;
|
||||||
|
dockEditorBackground: ThemeColor;
|
||||||
|
dockEditorTag: ThemeColor;
|
||||||
|
dockEditorKeyword: ThemeColor;
|
||||||
|
dockEditorComment: ThemeColor;
|
||||||
|
dockEditorActiveLineBackground: ThemeColor;
|
||||||
|
dockBadgeBackground: ThemeColor;
|
||||||
|
dockTabBorderColor: ThemeColor;
|
||||||
|
dockTabActiveBackground: ThemeColor;
|
||||||
|
logsBackground: ThemeColor;
|
||||||
|
logsForeground: ThemeColor;
|
||||||
|
logRowHoverBackground: ThemeColor;
|
||||||
|
dialogTextColor: ThemeColor;
|
||||||
|
dialogBackground: ThemeColor;
|
||||||
|
dialogHeaderBackground: ThemeColor;
|
||||||
|
dialogFooterBackground: ThemeColor;
|
||||||
|
drawerTogglerBackground: ThemeColor;
|
||||||
|
drawerTitleText: ThemeColor;
|
||||||
|
drawerSubtitleBackground: ThemeColor;
|
||||||
|
drawerItemNameColor: ThemeColor;
|
||||||
|
drawerItemValueColor: ThemeColor;
|
||||||
|
clusterMenuBackground: ThemeColor;
|
||||||
|
clusterMenuBorderColor: ThemeColor;
|
||||||
|
clusterMenuCellBackground: ThemeColor;
|
||||||
|
clusterSettingsBackground: ThemeColor;
|
||||||
|
addClusterIconColor: ThemeColor;
|
||||||
|
boxShadow: ThemeColor;
|
||||||
|
iconActiveColor: ThemeColor;
|
||||||
|
iconActiveBackground: ThemeColor;
|
||||||
|
filterAreaBackground: ThemeColor;
|
||||||
|
chartLiveBarBackground: ThemeColor;
|
||||||
|
chartStripesColor: ThemeColor;
|
||||||
|
chartCapacityColor: ThemeColor;
|
||||||
|
pieChartDefaultColor: ThemeColor;
|
||||||
|
inputOptionHoverColor: ThemeColor;
|
||||||
|
inputControlBackground: ThemeColor;
|
||||||
|
inputControlBorder: ThemeColor;
|
||||||
|
inputControlHoverBorder: ThemeColor;
|
||||||
|
lineProgressBackground: ThemeColor;
|
||||||
|
radioActiveBackground: ThemeColor;
|
||||||
|
menuActiveBackground: ThemeColor;
|
||||||
|
menuSelectedOptionBgc: ThemeColor;
|
||||||
|
canvasBackground: ThemeColor;
|
||||||
|
scrollBarColor: ThemeColor;
|
||||||
|
settingsBackground: ThemeColor;
|
||||||
|
settingsColor: ThemeColor;
|
||||||
|
navSelectedBackground: ThemeColor;
|
||||||
|
navHoverColor: ThemeColor;
|
||||||
|
hrColor: ThemeColor;
|
||||||
|
tooltipBackground: ThemeColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Theme {
|
||||||
|
name: string;
|
||||||
|
type: ThemeType;
|
||||||
|
colors: ThemeColors;
|
||||||
|
description: string;
|
||||||
|
author: string;
|
||||||
|
monacoTheme: MonacoTheme;
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user