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",
|
||||
"description": "OpenLens - Open Source IDE for Kubernetes",
|
||||
"homepage": "https://github.com/lensapp/lens",
|
||||
"version": "5.5.0-alpha.0",
|
||||
"version": "5.5.0-alpha.1",
|
||||
"main": "static/build/main.js",
|
||||
"copyright": "© 2021 OpenLens Authors",
|
||||
"license": "MIT",
|
||||
|
||||
@ -22,23 +22,21 @@ jest.mock("electron", () => ({
|
||||
}));
|
||||
|
||||
import { UserStore } from "../user-store";
|
||||
import { Console } from "console";
|
||||
import { SemVer } from "semver";
|
||||
import electron from "electron";
|
||||
import { stdout, stderr } from "process";
|
||||
import userStoreInjectable from "../user-store/user-store.injectable";
|
||||
import type { DiContainer } from "@ogre-tools/injectable";
|
||||
import directoryForUserDataInjectable from "../app-paths/directory-for-user-data/directory-for-user-data.injectable";
|
||||
import type { ClusterStoreModel } from "../cluster-store/cluster-store";
|
||||
import { defaultTheme } from "../vars";
|
||||
import writeFileInjectable from "../fs/write-file.injectable";
|
||||
import { getDiForUnitTesting } from "../../main/getDiForUnitTesting";
|
||||
import getConfigurationFileModelInjectable
|
||||
from "../get-configuration-file-model/get-configuration-file-model.injectable";
|
||||
import appVersionInjectable
|
||||
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", () => {
|
||||
let userStore: UserStore;
|
||||
@ -76,20 +74,16 @@ describe("user store tests", () => {
|
||||
expect(userStore.lastSeenAppVersion).toBe("1.2.3");
|
||||
});
|
||||
|
||||
it("allows setting and getting preferences", () => {
|
||||
it("allows setting preferences", () => {
|
||||
userStore.httpsProxy = "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 () => {
|
||||
userStore.colorTheme = "some other theme";
|
||||
userStore.resetTheme();
|
||||
expect(userStore.colorTheme).toBe(defaultTheme);
|
||||
(userStore.colorTheme as any) = "some other theme";
|
||||
userStore.resetThemeSettings();
|
||||
expect(userStore.colorTheme).toEqual(defaultColorThemeConf);
|
||||
});
|
||||
|
||||
it("correctly calculates if the last seen version is an old release", () => {
|
||||
@ -107,7 +101,6 @@ describe("user store tests", () => {
|
||||
"config.json": JSON.stringify({
|
||||
user: { username: "foobar" },
|
||||
preferences: { colorTheme: "light" },
|
||||
lastSeenAppVersion: "1.2.3",
|
||||
}),
|
||||
"lens-cluster-store.json": JSON.stringify({
|
||||
clusters: [
|
||||
@ -137,9 +130,148 @@ describe("user store tests", () => {
|
||||
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/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 merge from "lodash/merge";
|
||||
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 {
|
||||
filePath: string;
|
||||
@ -43,7 +45,7 @@ export const defaultEditorConfig: EditorConfiguration = {
|
||||
};
|
||||
interface PreferenceDescription<T, R = T> {
|
||||
fromStore(val: T | undefined): R;
|
||||
toStore(val: R): T | undefined;
|
||||
toStore(val: R | undefined): T | 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) {
|
||||
return val || defaultTheme;
|
||||
return val || defaultColorThemeConf;
|
||||
},
|
||||
toStore(val) {
|
||||
if (!val || val === defaultTheme) {
|
||||
if (!val || equals(val, defaultColorThemeConf)) {
|
||||
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) {
|
||||
return val || "";
|
||||
return val || defaultTerminalThemeConf;
|
||||
},
|
||||
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 { appEventBus } from "../app-event-bus/event-bus";
|
||||
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 logger from "../../main/logger";
|
||||
|
||||
@ -49,8 +49,8 @@ export class UserStore extends BaseStore<UserStoreModel> /* implements UserStore
|
||||
@observable allowTelemetry: boolean;
|
||||
@observable allowErrorReporting: boolean;
|
||||
@observable allowUntrustedCAs: boolean;
|
||||
@observable colorTheme: string;
|
||||
@observable terminalTheme: string;
|
||||
@observable colorTheme: ColorThemeConf;
|
||||
@observable terminalTheme: TerminalThemeConf;
|
||||
@observable localeTimezone: string;
|
||||
@observable downloadMirror: string;
|
||||
@observable httpsProxy?: string;
|
||||
@ -142,8 +142,9 @@ export class UserStore extends BaseStore<UserStoreModel> /* implements UserStore
|
||||
}
|
||||
|
||||
@action
|
||||
resetTheme() {
|
||||
resetThemeSettings() {
|
||||
this.colorTheme = DESCRIPTORS.colorTheme.fromStore(undefined);
|
||||
this.terminalTheme = DESCRIPTORS.terminalTheme.fromStore(undefined);
|
||||
}
|
||||
|
||||
@action
|
||||
|
||||
@ -3,6 +3,7 @@
|
||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* Narrows `val` to include the property `key` (if true is returned)
|
||||
* @param val The object to be tested
|
||||
@ -73,6 +74,20 @@ export function isString(val: unknown): val is 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
|
||||
* @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 { SemVer } from "semver";
|
||||
import packageInfo from "../../package.json";
|
||||
import type { ThemeType } from "../renderer/themes/types";
|
||||
import { defineGlobal } from "./utils/defineGlobal";
|
||||
import { lazyInitialized } from "./utils/lazy-initialized";
|
||||
|
||||
@ -26,7 +27,10 @@ export const isIntegrationTesting = process.argv.includes(integrationTestingArg)
|
||||
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 defaultThemeName = "lens";
|
||||
export const defaultThemeType: ThemeType = "dark";
|
||||
|
||||
export const defaultFontSize = 12;
|
||||
export const defaultTerminalFontFamily = "RobotoMono";
|
||||
export const defaultEditorFontFamily = "RobotoMono";
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
* 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() {
|
||||
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 version500Alpha3 from "./5.0.0-alpha.3";
|
||||
import version503Beta1 from "./5.0.3-beta.1";
|
||||
import v550alpha1Migration from "./5.5.0-alpha.1";
|
||||
import { fileNameMigration } from "./file-name-migration";
|
||||
|
||||
export {
|
||||
@ -20,4 +21,5 @@ export default joinMigrations(
|
||||
version210Beta4,
|
||||
version500Alpha3,
|
||||
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 { Router } from "react-router";
|
||||
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 addSyncEntriesInjectable from "./initializers/add-sync-entries.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 type { DiRender } 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 mockFs from "mock-fs";
|
||||
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 type { ItemObject } from "../../../common/item.store";
|
||||
import { Spinner } from "../spinner";
|
||||
import { ThemeStore } from "../../theme.store";
|
||||
import { ThemeStore } from "../../themes/store";
|
||||
import { kubeSelectedUrlParam, toggleDetails } from "../kube-detail-params";
|
||||
import { apiManager } from "../../../common/k8s-api/api-manager";
|
||||
import { KubeObjectAge } from "../kube-object/age";
|
||||
|
||||
@ -14,7 +14,7 @@ import { nodesStore } from "../+nodes/nodes.store";
|
||||
import { ChartData, PieChart } from "../chart";
|
||||
import { ClusterNoMetrics } from "./cluster-no-metrics";
|
||||
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 { withInjectables } from "@ogre-tools/injectable-react";
|
||||
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 { Button } from "../../button";
|
||||
import { Notifications } from "../../notifications";
|
||||
import { ThemeStore } from "../../../theme.store";
|
||||
import { ThemeStore } from "../../../themes/store";
|
||||
import { apiManager } from "../../../../common/k8s-api/api-manager";
|
||||
import { SubTitle } from "../../layout/sub-title";
|
||||
import { getDetailsUrl } from "../../kube-detail-params";
|
||||
|
||||
@ -11,7 +11,7 @@ import { NoMetrics } from "../resource-metrics/no-metrics";
|
||||
import { IResourceMetricsValue, ResourceMetricsContext } from "../resource-metrics";
|
||||
import { observer } from "mobx-react";
|
||||
import type { ChartOptions, ChartPoint } from "chart.js";
|
||||
import { ThemeStore } from "../../theme.store";
|
||||
import { ThemeStore } from "../../themes/store";
|
||||
import { mapValues } from "lodash";
|
||||
|
||||
type IContext = IResourceMetricsValue<Node, { metrics: IClusterMetrics }>;
|
||||
|
||||
@ -7,7 +7,7 @@ import React from "react";
|
||||
import { observer } from "mobx-react";
|
||||
import { SubTitle } from "../layout/sub-title";
|
||||
import { Select, SelectOption } from "../select";
|
||||
import type { ThemeStore } from "../../theme.store";
|
||||
import { themeTypeOptions } from "../../themes/store";
|
||||
import type { UserStore } from "../../../common/user-store";
|
||||
import { Input } from "../input";
|
||||
import { Switch } from "../switch";
|
||||
@ -21,7 +21,6 @@ import { withInjectables } from "@ogre-tools/injectable-react";
|
||||
import appPreferencesInjectable from "./app-preferences/app-preferences.injectable";
|
||||
import { Preferences } from "./preferences";
|
||||
import userStoreInjectable from "../../../common/user-store/user-store.injectable";
|
||||
import themeStoreInjectable from "../../theme-store.injectable";
|
||||
|
||||
const timezoneOptions: SelectOption<string>[] = moment.tz.names().map(zone => ({
|
||||
label: zone,
|
||||
@ -35,10 +34,9 @@ const updateChannelOptions: SelectOption<string>[] = Array.from(
|
||||
interface Dependencies {
|
||||
appPreferenceItems: IComputedValue<RegisteredAppPreference[]>;
|
||||
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 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>
|
||||
<section id="appearance">
|
||||
<SubTitle title="Theme" />
|
||||
<Select
|
||||
id="theme-input"
|
||||
options={[
|
||||
{ label: "Sync with computer", value: "system" },
|
||||
...themeStore.themeOptions,
|
||||
]}
|
||||
value={userStore.colorTheme}
|
||||
onChange={({ value }) => userStore.colorTheme = value}
|
||||
themeName="lens"
|
||||
/>
|
||||
<Switch
|
||||
checked={userStore.colorTheme.followSystemThemeType}
|
||||
onChange={() => userStore.colorTheme.followSystemThemeType = !userStore.colorTheme.followSystemThemeType}
|
||||
>
|
||||
Sync theme type with Operating System settings
|
||||
</Switch>
|
||||
|
||||
{!userStore.colorTheme.followSystemThemeType && (
|
||||
<>
|
||||
<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>
|
||||
|
||||
<hr />
|
||||
@ -135,16 +144,11 @@ const NonInjectedApplication: React.FC<Dependencies> = ({ appPreferenceItems, us
|
||||
</section>
|
||||
</Preferences>
|
||||
);
|
||||
};
|
||||
});
|
||||
|
||||
export const Application = withInjectables<Dependencies>(
|
||||
observer(NonInjectedApplication),
|
||||
|
||||
{
|
||||
getProps: (di) => ({
|
||||
appPreferenceItems: di.inject(appPreferencesInjectable),
|
||||
userStore: di.inject(userStoreInjectable),
|
||||
themeStore: di.inject(themeStoreInjectable),
|
||||
}),
|
||||
},
|
||||
);
|
||||
export const Application = withInjectables<Dependencies>(NonInjectedApplication, {
|
||||
getProps: (di) => ({
|
||||
appPreferenceItems: di.inject(appPreferencesInjectable),
|
||||
userStore: di.inject(userStoreInjectable),
|
||||
}),
|
||||
});
|
||||
|
||||
@ -10,20 +10,18 @@ import { SubTitle } from "../layout/sub-title";
|
||||
import { Input, InputValidators } from "../input";
|
||||
import { Switch } from "../switch";
|
||||
import { Select } from "../select";
|
||||
import type { ThemeStore } from "../../theme.store";
|
||||
import { themeTypeOptions } from "../../themes/store";
|
||||
import { Preferences } from "./preferences";
|
||||
import { withInjectables } from "@ogre-tools/injectable-react";
|
||||
import userStoreInjectable from "../../../common/user-store/user-store.injectable";
|
||||
import themeStoreInjectable from "../../theme-store.injectable";
|
||||
import defaultShellInjectable from "./default-shell.injectable";
|
||||
|
||||
interface Dependencies {
|
||||
userStore: UserStore;
|
||||
themeStore: ThemeStore;
|
||||
defaultShell: string;
|
||||
}
|
||||
|
||||
const NonInjectedTerminal = observer(({ userStore, themeStore, defaultShell }: Dependencies) => {
|
||||
const NonInjectedTerminal = observer(({ userStore, defaultShell }: Dependencies) => {
|
||||
return (
|
||||
<Preferences data-testid="terminal-preferences-page">
|
||||
<section>
|
||||
@ -51,18 +49,28 @@ const NonInjectedTerminal = observer(({ userStore, themeStore, defaultShell }: D
|
||||
|
||||
<section id="terminalTheme">
|
||||
<SubTitle title="Terminal theme" />
|
||||
<Select
|
||||
id="terminal-theme-input"
|
||||
themeName="lens"
|
||||
options={[
|
||||
{ label: "Match theme", value: "" },
|
||||
...themeStore.themeOptions,
|
||||
]}
|
||||
value={userStore.terminalTheme}
|
||||
onChange={({ value }) => userStore.terminalTheme = value}
|
||||
/>
|
||||
<Switch
|
||||
checked={userStore.terminalTheme.isGlobalThemeType}
|
||||
onChange={() => userStore.terminalTheme.isGlobalThemeType = !userStore.terminalTheme.isGlobalThemeType}
|
||||
>
|
||||
Sync terminal theme type with that of Lens
|
||||
</Switch>
|
||||
|
||||
{
|
||||
!userStore.terminalTheme.isGlobalThemeType && (
|
||||
<Select
|
||||
id="terminal-theme-input"
|
||||
themeName="lens"
|
||||
options={themeTypeOptions}
|
||||
value={userStore.terminalTheme.type}
|
||||
onChange={({ value }) => userStore.terminalTheme.type = value}
|
||||
/>
|
||||
)
|
||||
}
|
||||
</section>
|
||||
|
||||
{/* Once other themes are supported add an option to sync those as well */}
|
||||
|
||||
<section>
|
||||
<SubTitle title="Font size" />
|
||||
<Input
|
||||
@ -88,15 +96,10 @@ const NonInjectedTerminal = observer(({ userStore, themeStore, defaultShell }: D
|
||||
);
|
||||
});
|
||||
|
||||
export const Terminal = withInjectables<Dependencies>(
|
||||
NonInjectedTerminal,
|
||||
|
||||
{
|
||||
getProps: (di) => ({
|
||||
userStore: di.inject(userStoreInjectable),
|
||||
themeStore: di.inject(themeStoreInjectable),
|
||||
defaultShell: di.inject(defaultShellInjectable),
|
||||
}),
|
||||
},
|
||||
);
|
||||
export const Terminal = withInjectables<Dependencies>(NonInjectedTerminal, {
|
||||
getProps: (di) => ({
|
||||
userStore: di.inject(userStoreInjectable),
|
||||
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 { NoMetrics } from "../resource-metrics/no-metrics";
|
||||
import { IResourceMetricsValue, ResourceMetricsContext } from "../resource-metrics";
|
||||
import { ThemeStore } from "../../theme.store";
|
||||
import { ThemeStore } from "../../themes/store";
|
||||
|
||||
type IContext = IResourceMetricsValue<PersistentVolumeClaim, { metrics: IPvcMetrics }>;
|
||||
|
||||
|
||||
@ -11,7 +11,7 @@ import { observer } from "mobx-react";
|
||||
import { PieChart } from "../chart";
|
||||
import { cssVar } from "../../utils";
|
||||
import type { ChartData } from "chart.js";
|
||||
import { ThemeStore } from "../../theme.store";
|
||||
import { ThemeStore } from "../../themes/store";
|
||||
|
||||
export interface OverviewWorkloadStatusProps {
|
||||
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 { NoMetrics } from "../resource-metrics/no-metrics";
|
||||
import { IResourceMetricsValue, ResourceMetricsContext } from "../resource-metrics";
|
||||
import { ThemeStore } from "../../theme.store";
|
||||
import { ThemeStore } from "../../themes/store";
|
||||
import { mapValues } from "lodash";
|
||||
|
||||
type IContext = IResourceMetricsValue<any, { metrics: IPodMetrics }>;
|
||||
|
||||
@ -12,7 +12,7 @@ import type { ChartData, ChartOptions, ChartPoint, ChartTooltipItem, Scriptable
|
||||
import { Chart, ChartKind, ChartProps } from "./chart";
|
||||
import { bytesToUnits, cssNames } from "../../utils";
|
||||
import { ZebraStripes } from "./zebra-stripes.plugin";
|
||||
import { ThemeStore } from "../../theme.store";
|
||||
import { ThemeStore } from "../../themes/store";
|
||||
import { NoMetrics } from "../resource-metrics/no-metrics";
|
||||
|
||||
export interface BarChartProps extends ChartProps {
|
||||
|
||||
@ -9,7 +9,7 @@ import { observer } from "mobx-react";
|
||||
import ChartJS, { ChartOptions } from "chart.js";
|
||||
import { Chart, ChartProps } from "./chart";
|
||||
import { cssNames } from "../../utils";
|
||||
import { ThemeStore } from "../../theme.store";
|
||||
import { ThemeStore } from "../../themes/store";
|
||||
|
||||
export interface PieChartProps extends ChartProps {
|
||||
}
|
||||
|
||||
@ -10,7 +10,7 @@ import fse from "fs-extra";
|
||||
import { DockTabs } from "../dock-tabs";
|
||||
import { DockStore, DockTab, TabKind } from "../dock/store";
|
||||
import { noop } from "../../../utils";
|
||||
import { ThemeStore } from "../../../theme.store";
|
||||
import { ThemeStore } from "../../../themes/store";
|
||||
import { UserStore } from "../../../../common/user-store";
|
||||
import { getDiForUnitTesting } from "../../../getDiForUnitTesting";
|
||||
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 { LogResourceSelector } from "../resource-selector";
|
||||
import { dockerPod, deploymentPod1, deploymentPod2 } from "./pod.mock";
|
||||
import { ThemeStore } from "../../../../theme.store";
|
||||
import { ThemeStore } from "../../../../themes/store";
|
||||
import { UserStore } from "../../../../../common/user-store";
|
||||
import mockFs from "mock-fs";
|
||||
import { getDiForUnitTesting } from "../../../../getDiForUnitTesting";
|
||||
|
||||
@ -9,7 +9,7 @@ import { Terminal as XTerm } from "xterm";
|
||||
import { FitAddon } from "xterm-addon-fit";
|
||||
import type { TabId } from "../dock/store";
|
||||
import { TerminalApi, TerminalChannels } from "../../../api/terminal-api";
|
||||
import { ThemeStore } from "../../../theme.store";
|
||||
import { ThemeStore } from "../../../themes/store";
|
||||
import { disposer } from "../../../utils";
|
||||
import { isMac } from "../../../../common/vars";
|
||||
import { once } from "lodash";
|
||||
|
||||
@ -10,7 +10,7 @@ import { disposeOnUnmount, observer } from "mobx-react";
|
||||
import { cssNames } from "../../../utils";
|
||||
import type { Terminal } from "./terminal";
|
||||
import type { TerminalStore } from "./store";
|
||||
import { ThemeStore } from "../../../theme.store";
|
||||
import { ThemeStore } from "../../../themes/store";
|
||||
import type { DockTab, DockStore } from "../dock/store";
|
||||
import { withInjectables } from "@ogre-tools/injectable-react";
|
||||
import dockStoreInjectable from "../dock/store.injectable";
|
||||
|
||||
@ -11,7 +11,7 @@ import type { DiContainer } from "@ogre-tools/injectable";
|
||||
import { getDiForUnitTesting } from "../../../getDiForUnitTesting";
|
||||
import { DiRender, renderFor } from "../../test-utils/renderFor";
|
||||
import hotbarStoreInjectable from "../../../../common/hotbar-store.injectable";
|
||||
import { ThemeStore } from "../../../theme.store";
|
||||
import { ThemeStore } from "../../../themes/store";
|
||||
import { ConfirmDialog } from "../../confirm-dialog";
|
||||
import { UserStore } from "../../../../common/user-store";
|
||||
import mockFs from "mock-fs";
|
||||
|
||||
@ -16,7 +16,7 @@ import { NoItems } from "../no-items";
|
||||
import { Spinner } from "../spinner";
|
||||
import type { ItemObject, ItemStore } from "../../../common/item.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 { MenuItem } from "../menu";
|
||||
import { Checkbox } from "../checkbox";
|
||||
|
||||
@ -13,7 +13,7 @@ import { MonacoValidator, monacoValidators } from "./monaco-validators";
|
||||
import { debounce, merge } from "lodash";
|
||||
import { cssNames, disposer } from "../../utils";
|
||||
import { UserStore } from "../../../common/user-store";
|
||||
import { ThemeStore } from "../../theme.store";
|
||||
import { ThemeStore } from "../../themes/store";
|
||||
|
||||
export type MonacoEditorId = string;
|
||||
|
||||
|
||||
@ -6,7 +6,7 @@ import React from "react";
|
||||
import "@testing-library/jest-dom/extend-expect";
|
||||
import { Select } from "./select";
|
||||
import { UserStore } from "../../../common/user-store";
|
||||
import { ThemeStore } from "../../theme.store";
|
||||
import { ThemeStore } from "../../themes/store";
|
||||
import { getDiForUnitTesting } from "../../getDiForUnitTesting";
|
||||
import type { DiContainer } from "@ogre-tools/injectable";
|
||||
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 { CreatableProps } from "react-select/creatable";
|
||||
|
||||
import { ThemeStore } from "../../theme.store";
|
||||
import { ThemeStore } from "../../themes/store";
|
||||
import { boundMethod, cssNames } from "../../utils";
|
||||
|
||||
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",
|
||||
"type": "dark",
|
||||
"description": "Original Lens dark theme",
|
||||
@ -136,6 +143,8 @@
|
||||
"navSelectedBackground": "#262b2e",
|
||||
"navHoverColor": "#dcddde",
|
||||
"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.
|
||||
*/
|
||||
import { getInjectable } from "@ogre-tools/injectable";
|
||||
import { ThemeStore } from "./theme.store";
|
||||
import { ThemeStore } from "./store";
|
||||
|
||||
const themeStoreInjectable = getInjectable({
|
||||
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