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

Make LensTheme fully injectable and runnable

Signed-off-by: Sebastian Malton <sebastian@malton.name>
This commit is contained in:
Sebastian Malton 2022-12-05 12:04:25 -05:00
parent 56c78c8c8b
commit 963651ef4b
48 changed files with 863 additions and 579 deletions

View File

@ -1,8 +0,0 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
export const setNativeThemeChannel = "theme:set-native-theme";
export const getNativeThemeChannel = "theme:get-native-theme";

View File

@ -0,0 +1,37 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectable } from "@ogre-tools/injectable";
import { computed } from "mobx";
import userStoreInjectable from "./user-store.injectable";
export type LensColorThemePreference = {
useSystemTheme: true;
} | {
useSystemTheme: false;
lensThemeId: string;
};
const lensColorThemePreferenceInjectable = getInjectable({
id: "lens-color-theme-preference",
instantiate: (di) => {
const userStore = di.inject(userStoreInjectable);
return computed((): LensColorThemePreference => {
// TODO: remove magic strings
if (userStore.colorTheme === "system") {
return {
useSystemTheme: true,
};
}
return {
useSystemTheme: false,
lensThemeId: userStore.colorTheme,
};
});
},
});
export default lensColorThemePreferenceInjectable;

View File

@ -0,0 +1,37 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectable } from "@ogre-tools/injectable";
import { computed } from "mobx";
import userStoreInjectable from "./user-store.injectable";
export type TerminalThemePreference = {
matchLensTheme: true;
} | {
matchLensTheme: false;
themeId: string;
};
const terminalThemePreferenceInjectable = getInjectable({
id: "terminal-theme-preference",
instantiate: (di) => {
const userStore = di.inject(userStoreInjectable);
return computed((): TerminalThemePreference => {
// NOTE: remove use of magic strings
if (!userStore.terminalTheme) {
return {
matchLensTheme: true,
};
}
return {
matchLensTheme: false,
themeId: userStore.terminalTheme,
};
});
},
});
export default terminalThemePreferenceInjectable;

View File

@ -4,7 +4,7 @@
*/ */
// App's common configuration for any process (main, renderer, build pipeline, etc.) // App's common configuration for any process (main, renderer, build pipeline, etc.)
import type { ThemeId } from "../renderer/themes/store"; import type { ThemeId } from "../renderer/themes/lens-theme";
/** /**
* @deprecated Switch to using isMacInjectable * @deprecated Switch to using isMacInjectable

View File

@ -4,7 +4,7 @@
*/ */
import activeThemeInjectable from "../../renderer/themes/active.injectable"; import activeThemeInjectable from "../../renderer/themes/active.injectable";
import type { LensTheme } from "../../renderer/themes/store"; import type { LensTheme } from "../../renderer/themes/lens-theme";
import { asLegacyGlobalForExtensionApi } from "../as-legacy-globals-for-extension-api/as-legacy-global-object-for-extension-api"; import { asLegacyGlobalForExtensionApi } from "../as-legacy-globals-for-extension-api/as-legacy-global-object-for-extension-api";
export const activeTheme = asLegacyGlobalForExtensionApi(activeThemeInjectable); export const activeTheme = asLegacyGlobalForExtensionApi(activeThemeInjectable);

View File

@ -8,25 +8,30 @@ import { Select } from "../../../../../../renderer/components/select";
import { withInjectables } from "@ogre-tools/injectable-react"; import { withInjectables } from "@ogre-tools/injectable-react";
import { observer } from "mobx-react"; import { observer } from "mobx-react";
import type { UserStore } from "../../../../../../common/user-store"; import type { UserStore } from "../../../../../../common/user-store";
import type { ThemeStore } from "../../../../../../renderer/themes/store"; import type { LensTheme } from "../../../../../../renderer/themes/lens-theme";
import { defaultThemeId } from "../../../../../../common/vars";
import userStoreInjectable from "../../../../../../common/user-store/user-store.injectable"; import userStoreInjectable from "../../../../../../common/user-store/user-store.injectable";
import themeStoreInjectable from "../../../../../../renderer/themes/store.injectable"; import defaultLensThemeInjectable from "../../../../../../renderer/themes/default-theme.injectable";
import { lensThemeDeclarationInjectionToken } from "../../../../../../renderer/themes/declaration";
interface Dependencies { interface Dependencies {
userStore: UserStore; userStore: UserStore;
themeStore: ThemeStore; defaultTheme: LensTheme;
themes: LensTheme[];
} }
const NonInjectedTheme = observer(({ userStore, themeStore }: Dependencies) => { const NonInjectedTheme = observer(({
userStore,
themes,
defaultTheme,
}: Dependencies) => {
const themeOptions = [ const themeOptions = [
{ {
value: "system", // TODO: replace with a sentinal value that isn't string (and serialize it differently) value: "system", // TODO: replace with a sentinal value that isn't string (and serialize it differently)
label: "Sync with computer", label: "Sync with computer",
}, },
...Array.from(themeStore.themes, ([themeId, { name }]) => ({ ...themes.map(theme => ({
value: themeId, value: theme.name,
label: name, label: theme.name,
})), })),
]; ];
@ -38,7 +43,7 @@ const NonInjectedTheme = observer(({ userStore, themeStore }: Dependencies) => {
options={themeOptions} options={themeOptions}
value={userStore.colorTheme} value={userStore.colorTheme}
onChange={(value) => onChange={(value) =>
(userStore.colorTheme = value?.value ?? defaultThemeId) (userStore.colorTheme = value?.value ?? defaultTheme.name)
} }
themeName="lens" themeName="lens"
/> />
@ -46,13 +51,10 @@ const NonInjectedTheme = observer(({ userStore, themeStore }: Dependencies) => {
); );
}); });
export const Theme = withInjectables<Dependencies>( export const Theme = withInjectables<Dependencies>(NonInjectedTheme, {
NonInjectedTheme, getProps: (di) => ({
userStore: di.inject(userStoreInjectable),
{ defaultTheme: di.inject(defaultLensThemeInjectable),
getProps: (di) => ({ themes: di.injectMany(lensThemeDeclarationInjectionToken),
userStore: di.inject(userStoreInjectable), }),
themeStore: di.inject(themeStoreInjectable), });
}),
},
);

View File

@ -9,50 +9,48 @@ import type { UserStore } from "../../../../../../common/user-store";
import userStoreInjectable from "../../../../../../common/user-store/user-store.injectable"; import userStoreInjectable from "../../../../../../common/user-store/user-store.injectable";
import { observer } from "mobx-react"; import { observer } from "mobx-react";
import { Select } from "../../../../../../renderer/components/select"; import { Select } from "../../../../../../renderer/components/select";
import themeStoreInjectable from "../../../../../../renderer/themes/store.injectable"; import type { LensTheme } from "../../../../../../renderer/themes/lens-theme";
import type { ThemeStore } from "../../../../../../renderer/themes/store"; import { lensThemeDeclarationInjectionToken } from "../../../../../../renderer/themes/declaration";
interface Dependencies { interface Dependencies {
userStore: UserStore; userStore: UserStore;
themeStore: ThemeStore; themes: LensTheme[];
} }
const NonInjectedTerminalTheme = observer( const NonInjectedTerminalTheme = observer(({
({ userStore, themeStore }: Dependencies) => { userStore,
themes,
}: Dependencies) => {
const themeOptions = [ const themeOptions = [
{ {
value: "", // TODO: replace with a sentinal value that isn't string (and serialize it differently) value: "", // TODO: replace with a sentinal value that isn't string (and serialize it differently)
label: "Match Lens Theme", label: "Match Lens Theme",
}, },
...Array.from(themeStore.themes, ([themeId, { name }]) => ({ ...themes.map(theme => ({
value: themeId, value: theme.name,
label: name, label: theme.name,
})), })),
]; ];
return ( return (
<section id="terminalTheme"> <section id="terminalTheme">
<SubTitle title="Terminal theme" /> <SubTitle title="Terminal theme" />
<Select <Select
id="terminal-theme-input" id="terminal-theme-input"
themeName="lens" themeName="lens"
options={themeOptions} options={themeOptions}
value={userStore.terminalTheme} value={userStore.terminalTheme}
onChange={option => userStore.terminalTheme = option?.value ?? ""} onChange={option => userStore.terminalTheme = option?.value ?? ""}
/> />
</section> </section>
); );
}, },
); );
export const TerminalTheme = withInjectables<Dependencies>( export const TerminalTheme = withInjectables<Dependencies>(NonInjectedTerminalTheme, {
NonInjectedTerminalTheme, getProps: (di) => ({
userStore: di.inject(userStoreInjectable),
{ themes: di.injectMany(lensThemeDeclarationInjectionToken),
getProps: (di) => ({ }),
userStore: di.inject(userStoreInjectable), });
themeStore: di.inject(themeStoreInjectable),
}),
},
);

View File

@ -0,0 +1,17 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import type { MessageChannel } from "../../../../common/utils/channel/message-channel-listener-injection-token";
import type { RequestChannel } from "../../../../common/utils/channel/request-channel-listener-injection-token";
export type SystemThemeType = "dark" | "light";
export const initialSystemThemeTypeChannel: RequestChannel<void, SystemThemeType> = {
id: "initial-system-theme-type",
};
export const systemThemeTypeUpdateChannel: MessageChannel<SystemThemeType> = {
id: "system-theme-type-update",
};

View File

@ -0,0 +1,21 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectable } from "@ogre-tools/injectable";
import type { MessageChannelHandler } from "../../../../common/utils/channel/message-channel-listener-injection-token";
import { sendMessageToChannelInjectionToken } from "../../../../common/utils/channel/message-to-channel-injection-token";
import { systemThemeTypeUpdateChannel } from "../common/channels";
export type EmitSystemThemeTypeUpdate = MessageChannelHandler<typeof systemThemeTypeUpdateChannel>;
const emitSystemThemeTypeUpdateInjectable = getInjectable({
id: "emit-system-theme-type-update",
instantiate: (di): EmitSystemThemeTypeUpdate => {
const sendMessageToChannel = di.inject(sendMessageToChannelInjectionToken);
return (type) => sendMessageToChannel(systemThemeTypeUpdateChannel, type);
},
});
export default emitSystemThemeTypeUpdateInjectable;

View File

@ -0,0 +1,19 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import operatingSystemThemeInjectable from "../../../../main/theme/operating-system-theme.injectable";
import { getRequestChannelListenerInjectable } from "../../../../main/utils/channel/channel-listeners/listener-tokens";
import { initialSystemThemeTypeChannel } from "../common/channels";
const initialSystemThemeTypeHandler = getRequestChannelListenerInjectable({
channel: initialSystemThemeTypeChannel,
handler: (di) => {
const operatingSystemTheme = di.inject(operatingSystemThemeInjectable);
return () => operatingSystemTheme.get();
},
});
export default initialSystemThemeTypeHandler;

View File

@ -0,0 +1,33 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectable } from "@ogre-tools/injectable";
import { reaction } from "mobx";
import { onLoadOfApplicationInjectionToken } from "../../../../main/start-main-application/runnable-tokens/on-load-of-application-injection-token";
import operatingSystemThemeInjectable from "../../../../main/theme/operating-system-theme.injectable";
import emitSystemThemeTypeUpdateInjectable from "./emit-update.injectable";
const setupSystemThemeTypeUpdaterEmitterInjectable = getInjectable({
id: "setup-system-theme-type-updater-emitter",
instantiate: (di) => {
const operatingSystemTheme = di.inject(operatingSystemThemeInjectable);
const emitSystemThemeTypeUpdate = di.inject(emitSystemThemeTypeUpdateInjectable);
return {
id: "setup-system-theme-type-updater-emitter",
run: () => {
reaction(
() => operatingSystemTheme.get(),
emitSystemThemeTypeUpdate,
{
fireImmediately: true,
},
);
},
};
},
injectionToken: onLoadOfApplicationInjectionToken,
});
export default setupSystemThemeTypeUpdaterEmitterInjectable;

View File

@ -0,0 +1,28 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectable } from "@ogre-tools/injectable";
import { beforeFrameStartsInjectionToken } from "../../../../renderer/before-frame-starts/tokens";
import initUserStoreInjectable from "../../../../renderer/stores/init-user-store.injectable";
import systemThemeConfigurationInjectable from "../../../../renderer/themes/system-theme.injectable";
import requestInitialSystemThemeTypeInjectable from "./request-initial.injectable";
const initializeSystemThemeTypeInjectable = getInjectable({
id: "initialize-system-theme-type",
instantiate: (di) => {
const systemThemeConfiguration = di.inject(systemThemeConfigurationInjectable);
const requestInitialSystemThemeType = di.inject(requestInitialSystemThemeTypeInjectable);
return {
id: "initialize-system-theme-type",
run: async () => {
systemThemeConfiguration.set(await requestInitialSystemThemeType());
},
runAfter: di.inject(initUserStoreInjectable),
};
},
injectionToken: beforeFrameStartsInjectionToken,
});
export default initializeSystemThemeTypeInjectable;

View File

@ -0,0 +1,21 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectable } from "@ogre-tools/injectable";
import type { RequestChannelHandler } from "../../../../main/utils/channel/channel-listeners/listener-tokens";
import requestFromChannelInjectable from "../../../../renderer/utils/channel/request-from-channel.injectable";
import { initialSystemThemeTypeChannel } from "../common/channels";
export type RequestInitialSystemThemeType = RequestChannelHandler<typeof initialSystemThemeTypeChannel>;
const requestInitialSystemThemeTypeInjectable = getInjectable({
id: "request-initial-system-theme-type",
instantiate: (di): RequestInitialSystemThemeType => {
const requestFromChannel = di.inject(requestFromChannelInjectable);
return () => requestFromChannel(initialSystemThemeTypeChannel);
},
});
export default requestInitialSystemThemeTypeInjectable;

View File

@ -0,0 +1,19 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getMessageChannelListenerInjectable } from "../../../../common/utils/channel/message-channel-listener-injection-token";
import systemThemeConfigurationInjectable from "../../../../renderer/themes/system-theme.injectable";
import { systemThemeTypeUpdateChannel } from "../common/channels";
const systemThemeTypeUpdateListenerInjectable = getMessageChannelListenerInjectable({
channel: systemThemeTypeUpdateChannel,
id: "main",
handler: (di) => {
const systemThemeConfiguration = di.inject(systemThemeConfigurationInjectable);
return (type) => systemThemeConfiguration.set(type);
},
});
export default systemThemeTypeUpdateListenerInjectable;

View File

@ -14,8 +14,6 @@ import { pushCatalogToRenderer } from "../../../catalog-pusher";
import type { IComputedValue } from "mobx"; import type { IComputedValue } from "mobx";
import { windowActionHandleChannel, windowLocationChangedChannel, windowOpenAppMenuAsContextMenuChannel } from "../../../../common/ipc/window"; import { windowActionHandleChannel, windowLocationChangedChannel, windowOpenAppMenuAsContextMenuChannel } from "../../../../common/ipc/window";
import { handleWindowAction, onLocationChange } from "../../../ipc/window"; import { handleWindowAction, onLocationChange } from "../../../ipc/window";
import { getNativeThemeChannel } from "../../../../common/ipc/native-theme";
import type { Theme } from "../../../theme/operating-system-theme-state.injectable";
import type { ApplicationMenuItemTypes } from "../../../../features/application-menu/main/menu-items/application-menu-item-injection-token"; import type { ApplicationMenuItemTypes } from "../../../../features/application-menu/main/menu-items/application-menu-item-injection-token";
import type { Composite } from "../../../../common/utils/composite/get-composite/get-composite"; import type { Composite } from "../../../../common/utils/composite/get-composite/get-composite";
import { getApplicationMenuTemplate } from "../../../../features/application-menu/main/populate-application-menu.injectable"; import { getApplicationMenuTemplate } from "../../../../features/application-menu/main/populate-application-menu.injectable";
@ -26,7 +24,6 @@ interface Dependencies {
applicationMenuItemComposite: IComputedValue<Composite<ApplicationMenuItemTypes | MenuItemRoot>>; applicationMenuItemComposite: IComputedValue<Composite<ApplicationMenuItemTypes | MenuItemRoot>>;
catalogEntityRegistry: CatalogEntityRegistry; catalogEntityRegistry: CatalogEntityRegistry;
clusterStore: ClusterStore; clusterStore: ClusterStore;
operatingSystemTheme: IComputedValue<Theme>;
emitAppEvent: EmitAppEvent; emitAppEvent: EmitAppEvent;
getClusterById: GetClusterById; getClusterById: GetClusterById;
} }
@ -35,7 +32,6 @@ export const setupIpcMainHandlers = ({
applicationMenuItemComposite, applicationMenuItemComposite,
catalogEntityRegistry, catalogEntityRegistry,
clusterStore, clusterStore,
operatingSystemTheme,
emitAppEvent, emitAppEvent,
getClusterById, getClusterById,
}: Dependencies) => { }: Dependencies) => {
@ -83,10 +79,6 @@ export const setupIpcMainHandlers = ({
}); });
}); });
ipcMainHandle(getNativeThemeChannel, () => {
return operatingSystemTheme.get();
});
ipcMainHandle(clusterStates, () => ( ipcMainHandle(clusterStates, () => (
clusterStore.clustersList.map(cluster => ({ clusterStore.clustersList.map(cluster => ({
id: cluster.id, id: cluster.id,

View File

@ -24,7 +24,6 @@ import initRootFrameInjectable from "./frames/root-frame/init-root-frame/init-ro
import initClusterFrameInjectable from "./frames/cluster-frame/init-cluster-frame/init-cluster-frame.injectable"; import initClusterFrameInjectable from "./frames/cluster-frame/init-cluster-frame/init-cluster-frame.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 "./themes/store.injectable";
import assert from "assert"; import assert from "assert";
import startFrameInjectable from "./start-frame/start-frame.injectable"; import startFrameInjectable from "./start-frame/start-frame.injectable";
@ -45,10 +44,6 @@ export async function bootstrap(di: DiContainer) {
extensionDiscovery.init(); extensionDiscovery.init();
// ThemeStore depends on: UserStore
// TODO: Remove temporal dependencies
di.inject(themeStoreInjectable);
const extensionInstallationStateStore = di.inject(extensionInstallationStateStoreInjectable); const extensionInstallationStateStore = di.inject(extensionInstallationStateStoreInjectable);
extensionInstallationStateStore.bindIpcListeners(); extensionInstallationStateStore.bindIpcListeners();

View File

@ -27,7 +27,7 @@ import type { PageParam } from "../../navigation";
import type { ToggleKubeDetailsPane } from "../kube-detail-params/toggle-details.injectable"; import type { ToggleKubeDetailsPane } from "../kube-detail-params/toggle-details.injectable";
import kubeSelectedUrlParamInjectable from "../kube-detail-params/kube-selected-url.injectable"; import kubeSelectedUrlParamInjectable from "../kube-detail-params/kube-selected-url.injectable";
import toggleKubeDetailsPaneInjectable from "../kube-detail-params/toggle-details.injectable"; import toggleKubeDetailsPaneInjectable from "../kube-detail-params/toggle-details.injectable";
import type { LensTheme } from "../../themes/store"; import type { LensTheme } from "../../themes/lens-theme";
import activeThemeInjectable from "../../themes/active.injectable"; import activeThemeInjectable from "../../themes/active.injectable";
export interface ClusterIssuesProps { export interface ClusterIssuesProps {

View File

@ -16,7 +16,7 @@ import type { PieChartData } from "../chart";
import { PieChart } from "../chart"; import { 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 type { LensTheme } from "../../themes/store"; import type { LensTheme } from "../../themes/lens-theme";
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";

View File

@ -8,7 +8,7 @@ import { runInAction, action, observable, computed } from "mobx";
import type { TargetHelmRelease } from "../target-helm-release.injectable"; import type { TargetHelmRelease } from "../target-helm-release.injectable";
import type { RequestDetailedHelmRelease, DetailedHelmRelease } from "./request-detailed-helm-release.injectable"; import type { RequestDetailedHelmRelease, DetailedHelmRelease } from "./request-detailed-helm-release.injectable";
import requestDetailedHelmReleaseInjectable from "./request-detailed-helm-release.injectable"; import requestDetailedHelmReleaseInjectable from "./request-detailed-helm-release.injectable";
import type { LensTheme } from "../../../../themes/store"; import type { LensTheme } from "../../../../themes/lens-theme";
import type { RequestHelmReleaseConfiguration } from "../../../../../common/k8s-api/endpoints/helm-releases.api/request-configuration.injectable"; import type { RequestHelmReleaseConfiguration } from "../../../../../common/k8s-api/endpoints/helm-releases.api/request-configuration.injectable";
import requestHelmReleaseConfigurationInjectable from "../../../../../common/k8s-api/endpoints/helm-releases.api/request-configuration.injectable"; import requestHelmReleaseConfigurationInjectable from "../../../../../common/k8s-api/endpoints/helm-releases.api/request-configuration.injectable";
import { pipeline } from "@ogre-tools/fp"; import { pipeline } from "@ogre-tools/fp";

View File

@ -12,7 +12,7 @@ import { ResourceMetricsContext } from "../resource-metrics";
import { observer } from "mobx-react"; import { observer } from "mobx-react";
import { mapValues } from "lodash"; import { mapValues } from "lodash";
import { type MetricsTab, metricTabOptions } from "../chart/options"; import { type MetricsTab, metricTabOptions } from "../chart/options";
import type { LensTheme } from "../../themes/store"; import type { LensTheme } from "../../themes/lens-theme";
import { withInjectables } from "@ogre-tools/injectable-react"; import { withInjectables } from "@ogre-tools/injectable-react";
import type { IComputedValue } from "mobx"; import type { IComputedValue } from "mobx";
import activeThemeInjectable from "../../themes/active.injectable"; import activeThemeInjectable from "../../themes/active.injectable";

View File

@ -10,7 +10,7 @@ import { BarChart, 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 { ResourceMetricsContext } from "../resource-metrics"; import { ResourceMetricsContext } from "../resource-metrics";
import type { LensTheme } from "../../themes/store"; import type { LensTheme } from "../../themes/lens-theme";
import { withInjectables } from "@ogre-tools/injectable-react"; import { withInjectables } from "@ogre-tools/injectable-react";
import type { IComputedValue } from "mobx"; import type { IComputedValue } from "mobx";
import activeThemeInjectable from "../../themes/active.injectable"; import activeThemeInjectable from "../../themes/active.injectable";

View File

@ -11,7 +11,7 @@ import { observer } from "mobx-react";
import type { PieChartData } from "../chart"; import type { PieChartData } from "../chart";
import { PieChart } from "../chart"; import { PieChart } from "../chart";
import { object } from "../../utils"; import { object } from "../../utils";
import type { LensTheme } from "../../themes/store"; import type { LensTheme } from "../../themes/lens-theme";
import { withInjectables } from "@ogre-tools/injectable-react"; import { withInjectables } from "@ogre-tools/injectable-react";
import type { PascalCase } from "type-fest"; import type { PascalCase } from "type-fest";
import type { IComputedValue } from "mobx"; import type { IComputedValue } from "mobx";

View File

@ -10,7 +10,7 @@ import { BarChart } 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 { ResourceMetricsContext } from "../resource-metrics"; import { ResourceMetricsContext } from "../resource-metrics";
import type { LensTheme } from "../../themes/store"; import type { LensTheme } from "../../themes/lens-theme";
import { mapValues } from "lodash"; import { mapValues } from "lodash";
import { type MetricsTab, metricTabOptions } from "../chart/options"; import { type MetricsTab, metricTabOptions } from "../chart/options";
import { withInjectables } from "@ogre-tools/injectable-react"; import { withInjectables } from "@ogre-tools/injectable-react";

View File

@ -13,7 +13,7 @@ import type { ChartProps } from "./chart";
import { Chart, ChartKind } from "./chart"; import { Chart, ChartKind } from "./chart";
import { bytesToUnits, cssNames, isObject } from "../../utils"; import { bytesToUnits, cssNames, isObject } from "../../utils";
import { ZebraStripesPlugin } from "./zebra-stripes.plugin"; import { ZebraStripesPlugin } from "./zebra-stripes.plugin";
import type { LensTheme } from "../../themes/store"; import type { LensTheme } from "../../themes/lens-theme";
import { NoMetrics } from "../resource-metrics/no-metrics"; import { NoMetrics } from "../resource-metrics/no-metrics";
import assert from "assert"; import assert from "assert";
import { withInjectables } from "@ogre-tools/injectable-react"; import { withInjectables } from "@ogre-tools/injectable-react";

View File

@ -11,7 +11,7 @@ import ChartJS from "chart.js";
import type { ChartProps } from "./chart"; import type { ChartProps } from "./chart";
import { Chart } from "./chart"; import { Chart } from "./chart";
import { cssNames } from "../../utils"; import { cssNames } from "../../utils";
import type { LensTheme } from "../../themes/store"; import type { LensTheme } from "../../themes/lens-theme";
import { withInjectables } from "@ogre-tools/injectable-react"; import { withInjectables } from "@ogre-tools/injectable-react";
import type { IComputedValue } from "mobx"; import type { IComputedValue } from "mobx";
import activeThemeInjectable from "../../themes/active.injectable"; import activeThemeInjectable from "../../themes/active.injectable";

View File

@ -10,9 +10,9 @@ import type { TerminalApi } from "../../../api/terminal-api";
import terminalSpawningPoolInjectable from "./terminal-spawning-pool.injectable"; import terminalSpawningPoolInjectable from "./terminal-spawning-pool.injectable";
import terminalConfigInjectable from "../../../../common/user-store/terminal-config.injectable"; import terminalConfigInjectable from "../../../../common/user-store/terminal-config.injectable";
import terminalCopyOnSelectInjectable from "../../../../common/user-store/terminal-copy-on-select.injectable"; import terminalCopyOnSelectInjectable from "../../../../common/user-store/terminal-copy-on-select.injectable";
import themeStoreInjectable from "../../../themes/store.injectable";
import isMacInjectable from "../../../../common/vars/is-mac.injectable"; import isMacInjectable from "../../../../common/vars/is-mac.injectable";
import openLinkInBrowserInjectable from "../../../../common/utils/open-link-in-browser.injectable"; import openLinkInBrowserInjectable from "../../../../common/utils/open-link-in-browser.injectable";
import xtermColorThemeInjectable from "../../../themes/terminal-colors.injectable";
export type CreateTerminal = (tabId: TabId, api: TerminalApi) => Terminal; export type CreateTerminal = (tabId: TabId, api: TerminalApi) => Terminal;
@ -23,9 +23,9 @@ const createTerminalInjectable = getInjectable({
spawningPool: di.inject(terminalSpawningPoolInjectable), spawningPool: di.inject(terminalSpawningPoolInjectable),
terminalConfig: di.inject(terminalConfigInjectable), terminalConfig: di.inject(terminalConfigInjectable),
terminalCopyOnSelect: di.inject(terminalCopyOnSelectInjectable), terminalCopyOnSelect: di.inject(terminalCopyOnSelectInjectable),
themeStore: di.inject(themeStoreInjectable),
isMac: di.inject(isMacInjectable), isMac: di.inject(isMacInjectable),
openLinkInBrowser: di.inject(openLinkInBrowserInjectable), openLinkInBrowser: di.inject(openLinkInBrowserInjectable),
xtermColorTheme: di.inject(xtermColorThemeInjectable),
}; };
return (tabId, api) => new Terminal(dependencies, { tabId, api }); return (tabId, api) => new Terminal(dependencies, { tabId, api });

View File

@ -10,7 +10,6 @@ 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 type { TerminalApi } from "../../../api/terminal-api"; import type { TerminalApi } from "../../../api/terminal-api";
import type { ThemeStore } from "../../../themes/store";
import { disposer } from "../../../utils"; import { disposer } from "../../../utils";
import { once } from "lodash"; import { once } from "lodash";
import { clipboard } from "electron"; import { clipboard } from "electron";
@ -25,8 +24,8 @@ export interface TerminalDependencies {
readonly spawningPool: HTMLElement; readonly spawningPool: HTMLElement;
readonly terminalConfig: IComputedValue<TerminalConfig>; readonly terminalConfig: IComputedValue<TerminalConfig>;
readonly terminalCopyOnSelect: IComputedValue<boolean>; readonly terminalCopyOnSelect: IComputedValue<boolean>;
readonly themeStore: ThemeStore;
readonly isMac: boolean; readonly isMac: boolean;
readonly xtermColorTheme: IComputedValue<Record<string, string>>;
openLinkInBrowser: OpenLinkInBrowser; openLinkInBrowser: OpenLinkInBrowser;
} }
@ -75,10 +74,6 @@ export class Terminal {
return this.dependencies.terminalConfig.get().fontSize; return this.dependencies.terminalConfig.get().fontSize;
} }
get theme(): Record<string/*paramName*/, string/*color*/> {
return this.dependencies.themeStore.xtermColors;
}
constructor(protected readonly dependencies: TerminalDependencies, { constructor(protected readonly dependencies: TerminalDependencies, {
tabId, tabId,
api, api,
@ -120,9 +115,12 @@ export class Terminal {
this.disposer.push( this.disposer.push(
this.xterm.registerLinkProvider(linkProvider), this.xterm.registerLinkProvider(linkProvider),
reaction(() => this.theme, colors => this.xterm.setOption("theme", colors), { reaction(() => this.dependencies.xtermColorTheme.get(),
fireImmediately: true, colors => this.xterm.options.theme = colors,
}), {
fireImmediately: true,
},
),
reaction(() => this.fontSize, this.setFontSize, { fireImmediately: true }), reaction(() => this.fontSize, this.setFontSize, { fireImmediately: true }),
reaction(() => this.fontFamily, this.setFontFamily, { fireImmediately: true }), reaction(() => this.fontFamily, this.setFontFamily, { fireImmediately: true }),
() => onDataHandler.dispose(), () => onDataHandler.dispose(),

View File

@ -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 type { LensTheme } from "../../../themes/store"; import type { LensTheme } from "../../../themes/lens-theme";
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";

View File

@ -21,7 +21,7 @@ import { NoItems } from "../no-items";
import { Spinner } from "../spinner"; import { Spinner } from "../spinner";
import type { ItemObject } from "../../../common/item.store"; import type { ItemObject } from "../../../common/item.store";
import type { Filter, PageFiltersStore } from "./page-filters/store"; import type { Filter, PageFiltersStore } from "./page-filters/store";
import type { LensTheme } from "../../themes/store"; import type { LensTheme } from "../../themes/lens-theme";
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";

View File

@ -14,7 +14,7 @@ import { type MonacoValidator, monacoValidators } from "./monaco-validators";
import { debounce, merge } from "lodash"; import { debounce, merge } from "lodash";
import { autoBind, cssNames, disposer } from "../../utils"; import { autoBind, cssNames, disposer } from "../../utils";
import type { UserStore } from "../../../common/user-store"; import type { UserStore } from "../../../common/user-store";
import type { LensTheme } from "../../themes/store"; import type { LensTheme } from "../../themes/lens-theme";
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 activeThemeInjectable from "../../themes/active.injectable"; import activeThemeInjectable from "../../themes/active.injectable";

View File

@ -13,7 +13,7 @@ import { action, computed, makeObservable } from "mobx";
import { observer } from "mobx-react"; import { observer } from "mobx-react";
import ReactSelect, { components, createFilter } from "react-select"; import ReactSelect, { components, createFilter } from "react-select";
import type { Props as ReactSelectProps, GroupBase, MultiValue, OptionsOrGroups, PropsValue, SingleValue } from "react-select"; import type { Props as ReactSelectProps, GroupBase, MultiValue, OptionsOrGroups, PropsValue, SingleValue } from "react-select";
import type { LensTheme } from "../../themes/store"; import type { LensTheme } from "../../themes/lens-theme";
import { autoBind, cssNames } from "../../utils"; import { autoBind, cssNames } from "../../utils";
import { withInjectables } from "@ogre-tools/injectable-react"; import { withInjectables } from "@ogre-tools/injectable-react";
import activeThemeInjectable from "../../themes/active.injectable"; import activeThemeInjectable from "../../themes/active.injectable";

View File

@ -5,8 +5,8 @@
import { getInjectable } from "@ogre-tools/injectable"; import { getInjectable } from "@ogre-tools/injectable";
import type { IComputedValue } from "mobx"; import type { IComputedValue } from "mobx";
import { computed } from "mobx"; import { computed } from "mobx";
import type { LensThemeType } from "./store"; import activeThemeInjectable from "./active.injectable";
import themeStoreInjectable from "./store.injectable"; import type { LensThemeType } from "./lens-theme";
export type ActiveThemeType = IComputedValue<LensThemeType>; export type ActiveThemeType = IComputedValue<LensThemeType>;
@ -14,9 +14,9 @@ const activeThemeTypeInjectable = getInjectable({
id: "active-theme-type", id: "active-theme-type",
instantiate: (di) => { instantiate: (di) => {
const store = di.inject(themeStoreInjectable); const activeTheme = di.inject(activeThemeInjectable);
return computed(() => store.activeTheme.type); return computed(() => activeTheme.get().type);
}, },
}); });

View File

@ -3,15 +3,37 @@
* 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 assert from "assert";
import { computed } from "mobx"; import { computed } from "mobx";
import themeStoreInjectable from "./store.injectable"; import lensColorThemePreferenceInjectable from "../../common/user-store/lens-color-theme.injectable";
import { lensThemeDeclarationInjectionToken } from "./declaration";
import defaultLensThemeInjectable from "./default-theme.injectable";
import systemThemeConfigurationInjectable from "./system-theme.injectable";
import lensThemesInjectable from "./themes.injectable";
const activeThemeInjectable = getInjectable({ const activeThemeInjectable = getInjectable({
id: "active-theme", id: "active-theme",
instantiate: (di) => { instantiate: (di) => {
const store = di.inject(themeStoreInjectable); const lensThemes = di.inject(lensThemesInjectable);
const themeDecls = di.injectMany(lensThemeDeclarationInjectionToken);
const lensColorThemePreference = di.inject(lensColorThemePreferenceInjectable);
const systemThemeConfiguration = di.inject(systemThemeConfigurationInjectable);
const defaultLensTheme = di.inject(defaultLensThemeInjectable);
return computed(() => store.activeTheme); return computed(() => {
const pref = lensColorThemePreference.get();
if (pref.useSystemTheme) {
const systemThemeType = systemThemeConfiguration.get();
const matchingTheme = themeDecls.find(theme => theme.type === systemThemeType);
assert(matchingTheme, `Missing theme declaration for system theme "${systemThemeType}"`);
return matchingTheme;
}
return lensThemes.get(pref.lensThemeId) ?? defaultLensTheme;
});
}, },
}); });

View File

@ -0,0 +1,38 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectable } from "@ogre-tools/injectable";
import loggerInjectable from "../../common/logger.injectable";
import userStoreInjectable from "../../common/user-store/user-store.injectable";
import { object } from "../utils";
import type { LensTheme } from "./lens-theme";
export type ApplyLensTheme = (theme: LensTheme) => void;
const applyLensThemeInjectable = getInjectable({
id: "apply-lens-theme",
instantiate: (di): ApplyLensTheme => {
const logger = di.inject(loggerInjectable);
const userStore = di.inject(userStoreInjectable);
return (theme) => {
try {
const colors = object.entries(theme.colors);
for (const [name, value] of colors) {
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");
} catch (error) {
logger.error("[THEME]: Failed to apply active theme", error);
userStore.resetTheme();
}
};
},
causesSideEffects: true,
});
export default applyLensThemeInjectable;

View File

@ -0,0 +1,9 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getGlobalOverride } from "../../common/test-utils/get-global-override";
import applyLensThemeInjectable from "./apply-lens-theme.injectable";
export default getGlobalOverride(applyLensThemeInjectable, () => () => {});

View File

@ -0,0 +1,12 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectionToken } from "@ogre-tools/injectable";
import type { ReadonlyDeep } from "type-fest";
import type { LensTheme } from "./lens-theme";
export const lensThemeDeclarationInjectionToken = getInjectionToken<ReadonlyDeep<LensTheme>>({
id: "lens-theme-declaration",
});

View File

@ -0,0 +1,26 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectable } from "@ogre-tools/injectable";
import { lensThemeDeclarationInjectionToken } from "./declaration";
const defaultLensThemeInjectable = getInjectable({
id: "default-lens-theme",
instantiate: (di) => {
const themes = di.injectMany(lensThemeDeclarationInjectionToken);
const [defaultTheme, ...rest] = themes.filter(theme => theme.isDefault);
if (rest.length > 0) {
throw new Error("Multiple LensTheme's are declared as the default");
}
if (!defaultTheme) {
throw new Error("No LensTheme is declared as the default");
}
return defaultTheme;
},
});
export default defaultLensThemeInjectable;

View File

@ -0,0 +1,156 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectable } from "@ogre-tools/injectable";
import { lensThemeDeclarationInjectionToken } from "./declaration";
const lensDarkThemeInjectable = getInjectable({
id: "lens-dark-theme",
instantiate: () => ({
"name": "Dark",
"type": "dark" as const,
"description": "Original Lens dark theme",
"author": "Mirantis",
"monacoTheme": "clouds-midnight" as const,
"colors": {
"blue": "#3d90ce",
"magenta": "#c93dce",
"golden": "#ffc63d",
"halfGray": "#87909c80",
"primary": "#3d90ce",
"textColorPrimary": "#8e9297",
"textColorSecondary": "#a0a0a0",
"textColorTertiary": "#909ba6",
"textColorAccent": "#ffffff",
"textColorDimmed": "#8e92978c",
"borderColor": "#4c5053",
"borderFaintColor": "#373a3e",
"mainBackground": "#1e2124",
"secondaryBackground": "#1e2125",
"contentColor": "#262b2f",
"layoutBackground": "#2e3136",
"layoutTabsBackground": "#252729",
"layoutTabsActiveColor": "#ffffff",
"layoutTabsLineColor": "#87909c80",
"sidebarBackground": "#36393e",
"sidebarLogoBackground": "#414448",
"sidebarActiveColor": "#ffffff",
"sidebarSubmenuActiveColor": "#ffffff",
"sidebarItemHoverBackground": "#3a3e44",
"badgeBackgroundColor": "#ffba44",
"buttonPrimaryBackground": "#3d90ce",
"buttonDefaultBackground": "#414448",
"buttonLightBackground": "#f1f1f1",
"buttonAccentBackground": "#e85555",
"buttonDisabledBackground": "#808080",
"tableBgcStripe": "#2a2d33",
"tableBgcSelected": "#383c42",
"tableHeaderBackground": "#262b2f",
"tableHeaderBorderWidth": "1px",
"tableHeaderBorderColor": "#36393e",
"tableHeaderColor": "#ffffff",
"tableSelectedRowColor": "#ffffff",
"helmLogoBackground": "#ffffff",
"helmStableRepo": "#3d90ce",
"helmIncubatorRepo": "#ff7043",
"helmDescriptionHr": "#41474a",
"helmDescriptionBlockquoteColor": "#bbb",
"helmDescriptionBlockquoteBorder": "#8a8f93",
"helmDescriptionBlockquoteBackground": "#3b4348",
"helmDescriptionHeaders": "#3e4147",
"helmDescriptionH6": "#6a737d",
"helmDescriptionTdBorder": "#47494a",
"helmDescriptionTrBackground": "#1c2125",
"helmDescriptionCodeBackground": "#ffffff1a",
"helmDescriptionPreBackground": "#1b1f21",
"helmDescriptionPreColor": "#b4b5b4",
"colorSuccess": "#43a047",
"colorOk": "#4caf50",
"colorInfo": "#3d90ce",
"colorError": "#ce3933",
"colorSoftError": "#e85555",
"colorWarning": "#ff9800",
"colorVague": "#36393e",
"colorTerminated": "#4c5053",
"dockHeadBackground": "#2e3136",
"dockInfoBackground": "#1e2125",
"dockInfoBorderColor": "#303136",
"dockEditorBackground": "#000000",
"dockEditorTag": "#8e97a3",
"dockEditorKeyword": "#ffffff",
"dockEditorComment": "#808080",
"dockEditorActiveLineBackground": "#3a3d41",
"dockBadgeBackground": "#36393e",
"dockTabBorderColor": "#43424d",
"dockTabActiveBackground": "#3a3e45",
"logsBackground": "#000000",
"logsForeground": "#ffffff",
"logRowHoverBackground": "#35373a",
"terminalBackground": "#000000",
"terminalForeground": "#ffffff",
"terminalCursor": "#ffffff",
"terminalCursorAccent": "#000000",
"terminalSelection": "#ffffff77",
"terminalBlack": "#2e3436",
"terminalRed": "#cc0000",
"terminalGreen": "#4e9a06",
"terminalYellow": "#c4a000",
"terminalBlue": "#3465a4",
"terminalMagenta": "#75507b",
"terminalCyan": "#06989a",
"terminalWhite": "#d3d7cf",
"terminalBrightBlack": "#555753",
"terminalBrightRed": "#ef2929",
"terminalBrightGreen": "#8ae234",
"terminalBrightYellow": "#fce94f",
"terminalBrightBlue": "#729fcf",
"terminalBrightMagenta": "#ad7fa8",
"terminalBrightCyan": "#34e2e2",
"terminalBrightWhite": "#eeeeec",
"dialogTextColor": "#87909c",
"dialogBackground": "#ffffff",
"dialogHeaderBackground": "#36393e",
"dialogFooterBackground": "#f4f4f4",
"drawerTogglerBackground": "#2f343a",
"drawerTitleText": "#ffffff",
"drawerSubtitleBackground": "#373a3e",
"drawerItemNameColor": "#87909c",
"drawerItemValueColor": "#a0a0a0",
"clusterMenuBackground": "#252729",
"clusterMenuBorderColor": "#252729",
"clusterMenuCellBackground": "#2e3136",
"clusterSettingsBackground": "#1e2124",
"addClusterIconColor": "#252729",
"boxShadow": "#0000003a",
"iconActiveColor": "#ffffff",
"iconActiveBackground": "#ffffff18",
"filterAreaBackground": "#23272b",
"chartLiveBarBackground": "#00000033",
"chartStripesColor": "#ffffff08",
"chartCapacityColor": "#4c545f",
"pieChartDefaultColor": "#30353a",
"inputOptionHoverColor": "#87909c",
"inputControlBackground": "#1e2125",
"inputControlBorder": "#414448",
"inputControlHoverBorder": "#474a4f",
"lineProgressBackground": "#414448",
"radioActiveBackground": "#36393e",
"menuActiveBackground": "#3d90ce",
"menuSelectedOptionBgc": "#36393e",
"canvasBackground": "#24292e",
"scrollBarColor": "#5f6064",
"settingsBackground": "#262b2e",
"settingsColor": "#909ba6",
"navSelectedBackground": "#262b2e",
"navHoverColor": "#dcddde",
"hrColor": "#ffffff0f",
"tooltipBackground": "#18191c",
},
isDefault: true,
}),
injectionToken: lensThemeDeclarationInjectionToken,
});
export default lensDarkThemeInjectable;

View File

@ -1,150 +0,0 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import type { LensTheme } from "./store";
const lensDarkTheme: LensTheme = {
"name": "Dark",
"type": "dark",
"description": "Original Lens dark theme",
"author": "Mirantis",
"monacoTheme": "clouds-midnight",
"colors": {
"blue": "#3d90ce",
"magenta": "#c93dce",
"golden": "#ffc63d",
"halfGray": "#87909c80",
"primary": "#3d90ce",
"textColorPrimary": "#8e9297",
"textColorSecondary": "#a0a0a0",
"textColorTertiary": "#909ba6",
"textColorAccent": "#ffffff",
"textColorDimmed": "#8e92978c",
"borderColor": "#4c5053",
"borderFaintColor": "#373a3e",
"mainBackground": "#1e2124",
"secondaryBackground": "#1e2125",
"contentColor": "#262b2f",
"layoutBackground": "#2e3136",
"layoutTabsBackground": "#252729",
"layoutTabsActiveColor": "#ffffff",
"layoutTabsLineColor": "#87909c80",
"sidebarBackground": "#36393e",
"sidebarLogoBackground": "#414448",
"sidebarActiveColor": "#ffffff",
"sidebarSubmenuActiveColor": "#ffffff",
"sidebarItemHoverBackground": "#3a3e44",
"badgeBackgroundColor": "#ffba44",
"buttonPrimaryBackground": "#3d90ce",
"buttonDefaultBackground": "#414448",
"buttonLightBackground": "#f1f1f1",
"buttonAccentBackground": "#e85555",
"buttonDisabledBackground": "#808080",
"tableBgcStripe": "#2a2d33",
"tableBgcSelected": "#383c42",
"tableHeaderBackground": "#262b2f",
"tableHeaderBorderWidth": "1px",
"tableHeaderBorderColor": "#36393e",
"tableHeaderColor": "#ffffff",
"tableSelectedRowColor": "#ffffff",
"helmLogoBackground": "#ffffff",
"helmStableRepo": "#3d90ce",
"helmIncubatorRepo": "#ff7043",
"helmDescriptionHr": "#41474a",
"helmDescriptionBlockquoteColor": "#bbb",
"helmDescriptionBlockquoteBorder": "#8a8f93",
"helmDescriptionBlockquoteBackground": "#3b4348",
"helmDescriptionHeaders": "#3e4147",
"helmDescriptionH6": "#6a737d",
"helmDescriptionTdBorder": "#47494a",
"helmDescriptionTrBackground": "#1c2125",
"helmDescriptionCodeBackground": "#ffffff1a",
"helmDescriptionPreBackground": "#1b1f21",
"helmDescriptionPreColor": "#b4b5b4",
"colorSuccess": "#43a047",
"colorOk": "#4caf50",
"colorInfo": "#3d90ce",
"colorError": "#ce3933",
"colorSoftError": "#e85555",
"colorWarning": "#ff9800",
"colorVague": "#36393e",
"colorTerminated": "#4c5053",
"dockHeadBackground": "#2e3136",
"dockInfoBackground": "#1e2125",
"dockInfoBorderColor": "#303136",
"dockEditorBackground": "#000000",
"dockEditorTag": "#8e97a3",
"dockEditorKeyword": "#ffffff",
"dockEditorComment": "#808080",
"dockEditorActiveLineBackground": "#3a3d41",
"dockBadgeBackground": "#36393e",
"dockTabBorderColor": "#43424d",
"dockTabActiveBackground": "#3a3e45",
"logsBackground": "#000000",
"logsForeground": "#ffffff",
"logRowHoverBackground": "#35373a",
"terminalBackground": "#000000",
"terminalForeground": "#ffffff",
"terminalCursor": "#ffffff",
"terminalCursorAccent": "#000000",
"terminalSelection": "#ffffff77",
"terminalBlack": "#2e3436",
"terminalRed": "#cc0000",
"terminalGreen": "#4e9a06",
"terminalYellow": "#c4a000",
"terminalBlue": "#3465a4",
"terminalMagenta": "#75507b",
"terminalCyan": "#06989a",
"terminalWhite": "#d3d7cf",
"terminalBrightBlack": "#555753",
"terminalBrightRed": "#ef2929",
"terminalBrightGreen": "#8ae234",
"terminalBrightYellow": "#fce94f",
"terminalBrightBlue": "#729fcf",
"terminalBrightMagenta": "#ad7fa8",
"terminalBrightCyan": "#34e2e2",
"terminalBrightWhite": "#eeeeec",
"dialogTextColor": "#87909c",
"dialogBackground": "#ffffff",
"dialogHeaderBackground": "#36393e",
"dialogFooterBackground": "#f4f4f4",
"drawerTogglerBackground": "#2f343a",
"drawerTitleText": "#ffffff",
"drawerSubtitleBackground": "#373a3e",
"drawerItemNameColor": "#87909c",
"drawerItemValueColor": "#a0a0a0",
"clusterMenuBackground": "#252729",
"clusterMenuBorderColor": "#252729",
"clusterMenuCellBackground": "#2e3136",
"clusterSettingsBackground": "#1e2124",
"addClusterIconColor": "#252729",
"boxShadow": "#0000003a",
"iconActiveColor": "#ffffff",
"iconActiveBackground": "#ffffff18",
"filterAreaBackground": "#23272b",
"chartLiveBarBackground": "#00000033",
"chartStripesColor": "#ffffff08",
"chartCapacityColor": "#4c545f",
"pieChartDefaultColor": "#30353a",
"inputOptionHoverColor": "#87909c",
"inputControlBackground": "#1e2125",
"inputControlBorder": "#414448",
"inputControlHoverBorder": "#474a4f",
"lineProgressBackground": "#414448",
"radioActiveBackground": "#36393e",
"menuActiveBackground": "#3d90ce",
"menuSelectedOptionBgc": "#36393e",
"canvasBackground": "#24292e",
"scrollBarColor": "#5f6064",
"settingsBackground": "#262b2e",
"settingsColor": "#909ba6",
"navSelectedBackground": "#262b2e",
"navHoverColor": "#dcddde",
"hrColor": "#ffffff0f",
"tooltipBackground": "#18191c",
},
};
export default lensDarkTheme;

View File

@ -0,0 +1,154 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectable } from "@ogre-tools/injectable";
import { lensThemeDeclarationInjectionToken } from "./declaration";
const lensLightThemeInjectable = getInjectable({
id: "lens-light-theme",
instantiate: () => ({
"name": "Light",
"type": "light" as const,
"description": "Original Lens light theme",
"author": "Mirantis",
"monacoTheme": "vs" as const,
"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",
"badgeBackgroundColor": "#ffba44",
"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",
"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",
},
}),
injectionToken: lensThemeDeclarationInjectionToken,
});
export default lensLightThemeInjectable;

View File

@ -1,149 +0,0 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import type { LensTheme } from "./store";
const lensLightTheme: LensTheme = {
"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",
"badgeBackgroundColor": "#ffba44",
"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",
"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;

View File

@ -0,0 +1,18 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import type { MonacoTheme } from "../components/monaco-editor";
export type ThemeId = string;
export type LensThemeType = "dark" | "light";
export interface LensTheme {
name: string;
type: LensThemeType;
colors: Record<string, string>;
description: string;
author: string;
monacoTheme: MonacoTheme;
isDefault?: boolean;
}

View File

@ -0,0 +1,35 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectable } from "@ogre-tools/injectable";
import { reaction } from "mobx";
import initializeSystemThemeTypeInjectable from "../../features/theme/system-type/renderer/initialize.injectable";
import { beforeFrameStartsInjectionToken } from "../before-frame-starts/tokens";
import activeThemeInjectable from "./active.injectable";
import applyLensThemeInjectable from "./apply-lens-theme.injectable";
const setupApplyActiveThemeInjectable = getInjectable({
id: "setup-apply-active-theme",
instantiate: (di) => {
const activeTheme = di.inject(activeThemeInjectable);
const applyLensTheme = di.inject(applyLensThemeInjectable);
return {
id: "setup-apply-active-theme",
run: () => {
reaction(
() => activeTheme.get(),
applyLensTheme,
{
fireImmediately: true,
},
);
},
runAfter: di.inject(initializeSystemThemeTypeInjectable),
};
},
injectionToken: beforeFrameStartsInjectionToken,
});
export default setupApplyActiveThemeInjectable;

View File

@ -1,19 +0,0 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectable } from "@ogre-tools/injectable";
import userStoreInjectable from "../../common/user-store/user-store.injectable";
import ipcRendererInjectable from "../utils/channel/ipc-renderer.injectable";
import { ThemeStore } from "./store";
const themeStoreInjectable = getInjectable({
id: "theme-store",
instantiate: (di) => new ThemeStore({
ipcRenderer: di.inject(ipcRendererInjectable),
userStore: di.inject(userStoreInjectable),
}),
});
export default themeStoreInjectable;

View File

@ -1,150 +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 } from "../utils";
import logger from "../../main/logger";
import lensDarkTheme from "./lens-dark";
import lensLightTheme from "./lens-light";
import type { MonacoTheme } from "../components/monaco-editor";
import { defaultThemeId } from "../../common/vars";
import { camelCase } from "lodash";
import type { IpcRenderer } from "electron";
import { getNativeThemeChannel, setNativeThemeChannel } from "../../common/ipc/native-theme";
import type { ReadonlyDeep } from "type-fest/source/readonly-deep";
import assert from "assert";
export type ThemeId = string;
export type LensThemeType = "dark" | "light";
export interface LensTheme {
name: string;
type: LensThemeType;
colors: Record<string, string>;
description: string;
author: string;
monacoTheme: MonacoTheme;
}
interface Dependencies {
readonly userStore: {
colorTheme: string;
terminalTheme: ThemeId;
resetTheme(): void;
};
readonly ipcRenderer: IpcRenderer;
}
export class ThemeStore {
private terminalColorPrefix = "terminal";
#themes = observable.map<ThemeId, LensTheme>({
"lens-dark": lensDarkTheme,
"lens-light": lensLightTheme,
});
@observable private osNativeThemeType: "dark" | "light" | undefined;
@computed private get colorThemePreference(): ThemeId | "system" {
return this.dependencies.userStore.colorTheme;
}
@computed private get activeThemeId(): ThemeId {
if (this.colorThemePreference === "system") {
if (this.osNativeThemeType) {
return `lens-${this.osNativeThemeType}`;
} else {
return defaultThemeId;
}
} else {
return this.colorThemePreference;
}
}
@computed private get terminalThemeId(): ThemeId {
return this.dependencies.userStore.terminalTheme;
}
private readonly defaultTheme: LensTheme;
@computed get activeTheme(): LensTheme {
return this.themes.get(this.activeThemeId) ?? this.defaultTheme;
}
@computed private 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,
]),
);
}
get themes() {
return this.#themes as ReadonlyDeep<Map<string, LensTheme>>;
}
constructor(protected readonly dependencies: Dependencies) {
makeObservable(this);
autoBind(this);
this.init();
const defaultTheme = this.#themes.get(defaultThemeId);
assert(defaultTheme, `${defaultThemeId} is invalid as there is no corresponding theme`);
this.defaultTheme = defaultTheme;
}
async init() {
this.osNativeThemeType = await this.dependencies.ipcRenderer.invoke(getNativeThemeChannel);
this.dependencies.ipcRenderer.on(setNativeThemeChannel, (event, theme: "dark" | "light") => {
this.osNativeThemeType = theme;
});
// auto-apply active theme
reaction(() => ({
themeId: this.activeThemeId,
terminalThemeId: this.terminalThemeId,
}), () => {
try {
this.applyActiveTheme();
} catch (err) {
logger.error(`Failed to apply active theme: ${err}`);
this.dependencies.userStore.resetTheme();
}
}, {
fireImmediately: true,
equals: comparer.shallow,
});
}
getThemeById(themeId: ThemeId): LensTheme | undefined {
return this.themes.get(themeId);
}
protected applyActiveTheme() {
const colors = Object.entries({
...this.activeTheme.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", this.activeTheme.type === "light");
}
}

View File

@ -0,0 +1,13 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectable } from "@ogre-tools/injectable";
import { observable } from "mobx";
const systemThemeConfigurationInjectable = getInjectable({
id: "system-theme-configuration",
instantiate: () => observable.box<"dark" | "light">("dark"),
});
export default systemThemeConfigurationInjectable;

View File

@ -0,0 +1,43 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectable } from "@ogre-tools/injectable";
import { camelCase } from "lodash";
import { computed } from "mobx";
import terminalThemePreferenceInjectable from "../../common/user-store/terminal-theme.injectable";
import { object } from "../utils";
import activeThemeInjectable from "./active.injectable";
import lensThemesInjectable from "./themes.injectable";
const terminalColorPrefix = "terminal";
const xtermColorThemeInjectable = getInjectable({
id: "terminal-colors",
instantiate: (di) => {
const activeTheme = di.inject(activeThemeInjectable);
const terminalThemePreference = di.inject(terminalThemePreferenceInjectable);
const themes = di.inject(lensThemesInjectable);
const terminalTheme = computed(() => {
const themePref = terminalThemePreference.get();
if (themePref.matchLensTheme) {
return activeTheme.get();
}
return themes.get(themePref.themeId) ?? activeTheme.get();
});
return computed(() => object.fromEntries(
object.entries(terminalTheme.get().colors)
.filter(([name]) => name.startsWith(terminalColorPrefix))
.map(([name, color]) => [
camelCase(name.replace(terminalColorPrefix, "")),
color,
]),
));
},
});
export default xtermColorThemeInjectable;

View File

@ -0,0 +1,17 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectable } from "@ogre-tools/injectable";
import { lensThemeDeclarationInjectionToken } from "./declaration";
const lensThemesInjectable = getInjectable({
id: "lens-themes",
instantiate: (di) => {
const themes = di.injectMany(lensThemeDeclarationInjectionToken);
return new Map(themes.map(theme => [theme.name, theme]));
},
});
export default lensThemesInjectable;