mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
Introduce reactive way to get theme from operating system
Co-authored-by: Mikko Aspiala <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi>
This commit is contained in:
parent
c7dba52cd0
commit
32bc853279
@ -0,0 +1,18 @@
|
|||||||
|
/**
|
||||||
|
* 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 nativeThemeInjectable from "./native-theme.injectable";
|
||||||
|
|
||||||
|
const getElectronThemeInjectable = getInjectable({
|
||||||
|
id: "get-electron-theme",
|
||||||
|
|
||||||
|
instantiate: (di) => {
|
||||||
|
const nativeTheme = di.inject(nativeThemeInjectable);
|
||||||
|
|
||||||
|
return () => nativeTheme.shouldUseDarkColors ? "dark" : "light";
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export default getElectronThemeInjectable;
|
||||||
14
src/main/electron-app/features/native-theme.injectable.ts
Normal file
14
src/main/electron-app/features/native-theme.injectable.ts
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
/**
|
||||||
|
* 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 { nativeTheme } from "electron";
|
||||||
|
|
||||||
|
const nativeThemeInjectable = getInjectable({
|
||||||
|
id: "native-theme",
|
||||||
|
instantiate: () => nativeTheme,
|
||||||
|
causesSideEffects: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
export default nativeThemeInjectable;
|
||||||
@ -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 { getStartableStoppable } from "../../../common/utils/get-startable-stoppable";
|
||||||
|
import currentOperatingSystemThemeStateInjectable from "../../theme/current-operating-system-theme-state.injectable";
|
||||||
|
import nativeThemeInjectable from "./native-theme.injectable";
|
||||||
|
import getElectronThemeInjectable from "./get-electron-theme.injectable";
|
||||||
|
|
||||||
|
const syncThemeFromOperatingSystemInjectable = getInjectable({
|
||||||
|
id: "sync-theme-from-operating-system",
|
||||||
|
|
||||||
|
instantiate: (di) => {
|
||||||
|
const currentThemeState = di.inject(currentOperatingSystemThemeStateInjectable);
|
||||||
|
const nativeTheme = di.inject(nativeThemeInjectable);
|
||||||
|
const getElectronTheme = di.inject(getElectronThemeInjectable);
|
||||||
|
|
||||||
|
return getStartableStoppable("sync-theme-from-operating-system", () => {
|
||||||
|
const updateThemeState = () => {
|
||||||
|
const newTheme = getElectronTheme();
|
||||||
|
|
||||||
|
currentThemeState.set(newTheme);
|
||||||
|
};
|
||||||
|
|
||||||
|
nativeTheme.on("updated", updateThemeState);
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
nativeTheme.off("updated", updateThemeState);
|
||||||
|
};
|
||||||
|
});
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export default syncThemeFromOperatingSystemInjectable;
|
||||||
@ -1,24 +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 { broadcastNativeThemeOnUpdate } from "../../native-theme";
|
|
||||||
import { whenApplicationIsLoadingInjectionToken } from "../../start-main-application/runnable-tokens/when-application-is-loading-injection-token";
|
|
||||||
|
|
||||||
const setupOsThemeUpdatesInjectable = getInjectable({
|
|
||||||
id: "setup-os-theme-updates",
|
|
||||||
|
|
||||||
instantiate: () => ({
|
|
||||||
run: () => {
|
|
||||||
broadcastNativeThemeOnUpdate();
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
|
|
||||||
// Todo: remove explicit usage of IPC to get rid of this.
|
|
||||||
causesSideEffects: true,
|
|
||||||
|
|
||||||
injectionToken: whenApplicationIsLoadingInjectionToken,
|
|
||||||
});
|
|
||||||
|
|
||||||
export default setupOsThemeUpdatesInjectable;
|
|
||||||
@ -47,7 +47,6 @@ import catalogCategoryRegistryInjectable from "../common/catalog/catalog-categor
|
|||||||
import setupIpcMainHandlersInjectable from "./electron-app/runnables/setup-ipc-main-handlers/setup-ipc-main-handlers.injectable";
|
import setupIpcMainHandlersInjectable from "./electron-app/runnables/setup-ipc-main-handlers/setup-ipc-main-handlers.injectable";
|
||||||
import setupLensProxyInjectable from "./start-main-application/runnables/setup-lens-proxy.injectable";
|
import setupLensProxyInjectable from "./start-main-application/runnables/setup-lens-proxy.injectable";
|
||||||
import setupRunnablesForAfterRootFrameIsReadyInjectable from "./start-main-application/runnables/setup-runnables-for-after-root-frame-is-ready.injectable";
|
import setupRunnablesForAfterRootFrameIsReadyInjectable from "./start-main-application/runnables/setup-runnables-for-after-root-frame-is-ready.injectable";
|
||||||
import setupOsThemeUpdatesInjectable from "./electron-app/runnables/setup-os-theme-updates.injectable";
|
|
||||||
import setupSentryInjectable from "./start-main-application/runnables/setup-sentry.injectable";
|
import setupSentryInjectable from "./start-main-application/runnables/setup-sentry.injectable";
|
||||||
import setupShellInjectable from "./start-main-application/runnables/setup-shell.injectable";
|
import setupShellInjectable from "./start-main-application/runnables/setup-shell.injectable";
|
||||||
import setupSyncingOfWeblinksInjectable from "./start-main-application/runnables/setup-syncing-of-weblinks.injectable";
|
import setupSyncingOfWeblinksInjectable from "./start-main-application/runnables/setup-syncing-of-weblinks.injectable";
|
||||||
@ -79,6 +78,8 @@ import createElectronWindowForInjectable from "./start-main-application/lens-win
|
|||||||
import setupRunnablesAfterWindowIsOpenedInjectable from "./electron-app/runnables/setup-runnables-after-window-is-opened.injectable";
|
import setupRunnablesAfterWindowIsOpenedInjectable from "./electron-app/runnables/setup-runnables-after-window-is-opened.injectable";
|
||||||
import sendToChannelInElectronBrowserWindowInjectable from "./start-main-application/lens-window/application-window/send-to-channel-in-electron-browser-window.injectable";
|
import sendToChannelInElectronBrowserWindowInjectable from "./start-main-application/lens-window/application-window/send-to-channel-in-electron-browser-window.injectable";
|
||||||
import broadcastMessageInjectable from "../common/ipc/broadcast-message.injectable";
|
import broadcastMessageInjectable from "../common/ipc/broadcast-message.injectable";
|
||||||
|
import getElectronThemeInjectable from "./electron-app/features/get-electron-theme.injectable";
|
||||||
|
import syncThemeFromOperatingSystemInjectable from "./electron-app/features/sync-theme-from-operating-system.injectable";
|
||||||
|
|
||||||
export const getDiForUnitTesting = (
|
export const getDiForUnitTesting = (
|
||||||
{ doGeneralOverrides } = { doGeneralOverrides: false },
|
{ doGeneralOverrides } = { doGeneralOverrides: false },
|
||||||
@ -136,8 +137,8 @@ export const getDiForUnitTesting = (
|
|||||||
di.override(registerChannelInjectable, () => () => undefined);
|
di.override(registerChannelInjectable, () => () => undefined);
|
||||||
di.override(directoryForBundledBinariesInjectable, () => "some-bin-directory");
|
di.override(directoryForBundledBinariesInjectable, () => "some-bin-directory");
|
||||||
|
|
||||||
di.override(broadcastMessageInjectable, () => {
|
di.override(broadcastMessageInjectable, () => (channel) => {
|
||||||
throw new Error("Tried to broadcast message over IPC without explicit override.");
|
throw new Error(`Tried to broadcast message to channel "${channel}" over IPC without explicit override.`);
|
||||||
});
|
});
|
||||||
|
|
||||||
di.override(spawnInjectable, () => () => {
|
di.override(spawnInjectable, () => () => {
|
||||||
@ -184,7 +185,6 @@ const overrideRunnablesHavingSideEffects = (di: DiContainer) => {
|
|||||||
setupIpcMainHandlersInjectable,
|
setupIpcMainHandlersInjectable,
|
||||||
setupLensProxyInjectable,
|
setupLensProxyInjectable,
|
||||||
setupRunnablesForAfterRootFrameIsReadyInjectable,
|
setupRunnablesForAfterRootFrameIsReadyInjectable,
|
||||||
setupOsThemeUpdatesInjectable,
|
|
||||||
setupSentryInjectable,
|
setupSentryInjectable,
|
||||||
setupShellInjectable,
|
setupShellInjectable,
|
||||||
setupSyncingOfWeblinksInjectable,
|
setupSyncingOfWeblinksInjectable,
|
||||||
@ -224,6 +224,8 @@ const overrideElectronFeatures = (di: DiContainer) => {
|
|||||||
di.override(showMessagePopupInjectable, () => () => {});
|
di.override(showMessagePopupInjectable, () => () => {});
|
||||||
di.override(waitForElectronToBeReadyInjectable, () => () => Promise.resolve());
|
di.override(waitForElectronToBeReadyInjectable, () => () => Promise.resolve());
|
||||||
di.override(ipcMainInjectable, () => ({}));
|
di.override(ipcMainInjectable, () => ({}));
|
||||||
|
di.override(getElectronThemeInjectable, () => () => "dark");
|
||||||
|
di.override(syncThemeFromOperatingSystemInjectable, () => ({ start: () => {}, stop: () => {} }));
|
||||||
|
|
||||||
di.override(createElectronWindowForInjectable, () => () => async () => ({
|
di.override(createElectronWindowForInjectable, () => () => async () => ({
|
||||||
show: () => {},
|
show: () => {},
|
||||||
|
|||||||
@ -0,0 +1,27 @@
|
|||||||
|
/**
|
||||||
|
* 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 { getStartableStoppable } from "../../../common/utils/get-startable-stoppable";
|
||||||
|
import { setNativeThemeChannel } from "../../../common/ipc/native-theme";
|
||||||
|
import currentOperatingSystemThemeInjectable from "../current-operating-system-theme.injectable";
|
||||||
|
import broadcastMessageInjectable from "../../../common/ipc/broadcast-message.injectable";
|
||||||
|
|
||||||
|
const broadcastThemeChangeInjectable = getInjectable({
|
||||||
|
id: "broadcast-theme-change",
|
||||||
|
|
||||||
|
instantiate: (di) => {
|
||||||
|
const currentTheme = di.inject(currentOperatingSystemThemeInjectable);
|
||||||
|
const broadcastMessage = di.inject(broadcastMessageInjectable);
|
||||||
|
|
||||||
|
return getStartableStoppable("broadcast-theme-change", () =>
|
||||||
|
reaction(() => currentTheme.get(), (theme) => {
|
||||||
|
broadcastMessage(setNativeThemeChannel, theme);
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export default broadcastThemeChangeInjectable;
|
||||||
@ -0,0 +1,25 @@
|
|||||||
|
/**
|
||||||
|
* 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 { whenApplicationIsLoadingInjectionToken } from "../../start-main-application/runnable-tokens/when-application-is-loading-injection-token";
|
||||||
|
import broadcastThemeChangeInjectable from "./broadcast-theme-change.injectable";
|
||||||
|
|
||||||
|
const startBroadcastingThemeChangeInjectable = getInjectable({
|
||||||
|
id: "start-broadcasting-theme-change",
|
||||||
|
|
||||||
|
instantiate: (di) => {
|
||||||
|
const broadcastThemeChange = di.inject(broadcastThemeChangeInjectable);
|
||||||
|
|
||||||
|
return {
|
||||||
|
run: async () => {
|
||||||
|
await broadcastThemeChange.start();
|
||||||
|
},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
injectionToken: whenApplicationIsLoadingInjectionToken,
|
||||||
|
});
|
||||||
|
|
||||||
|
export default startBroadcastingThemeChangeInjectable;
|
||||||
@ -0,0 +1,25 @@
|
|||||||
|
/**
|
||||||
|
* 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 broadcastThemeChangeInjectable from "./broadcast-theme-change.injectable";
|
||||||
|
import { beforeQuitOfBackEndInjectionToken } from "../../start-main-application/runnable-tokens/before-quit-of-back-end-injection-token";
|
||||||
|
|
||||||
|
const stopBroadcastingThemeChangeInjectable = getInjectable({
|
||||||
|
id: "stop-broadcasting-theme-change",
|
||||||
|
|
||||||
|
instantiate: (di) => {
|
||||||
|
const broadcastThemeChange = di.inject(broadcastThemeChangeInjectable);
|
||||||
|
|
||||||
|
return {
|
||||||
|
run: async () => {
|
||||||
|
await broadcastThemeChange.stop();
|
||||||
|
},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
injectionToken: beforeQuitOfBackEndInjectionToken,
|
||||||
|
});
|
||||||
|
|
||||||
|
export default stopBroadcastingThemeChangeInjectable;
|
||||||
@ -0,0 +1,24 @@
|
|||||||
|
/**
|
||||||
|
* 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";
|
||||||
|
import getElectronThemeInjectable from "../electron-app/features/get-electron-theme.injectable";
|
||||||
|
|
||||||
|
export type Theme = "dark" | "light";
|
||||||
|
|
||||||
|
const currentOperatingSystemThemeStateInjectable = getInjectable({
|
||||||
|
id: "current-operating-system-theme-state",
|
||||||
|
|
||||||
|
instantiate: (di) => {
|
||||||
|
const getElectronTheme = di.inject(getElectronThemeInjectable);
|
||||||
|
const defaultTheme = getElectronTheme();
|
||||||
|
|
||||||
|
return observable.box<Theme>(
|
||||||
|
defaultTheme,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export default currentOperatingSystemThemeStateInjectable;
|
||||||
19
src/main/theme/current-operating-system-theme.injectable.ts
Normal file
19
src/main/theme/current-operating-system-theme.injectable.ts
Normal 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 { getInjectable } from "@ogre-tools/injectable";
|
||||||
|
import { computed } from "mobx";
|
||||||
|
import currentOperatingSystemThemeStateInjectable from "./current-operating-system-theme-state.injectable";
|
||||||
|
|
||||||
|
const currentOperatingSystemThemeInjectable = getInjectable({
|
||||||
|
id: "current-operating-system-theme",
|
||||||
|
|
||||||
|
instantiate: (di) => {
|
||||||
|
const currentThemeState = di.inject(currentOperatingSystemThemeStateInjectable);
|
||||||
|
|
||||||
|
return computed(() => currentThemeState.get());
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export default currentOperatingSystemThemeInjectable;
|
||||||
@ -0,0 +1,25 @@
|
|||||||
|
/**
|
||||||
|
* 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 syncThemeFromOperatingSystemInjectable from "../../electron-app/features/sync-theme-from-operating-system.injectable";
|
||||||
|
import { whenApplicationIsLoadingInjectionToken } from "../../start-main-application/runnable-tokens/when-application-is-loading-injection-token";
|
||||||
|
|
||||||
|
const startSyncingThemeFromOperatingSystemInjectable = getInjectable({
|
||||||
|
id: "start-syncing-theme-from-operating-system",
|
||||||
|
|
||||||
|
instantiate: (di) => {
|
||||||
|
const syncTheme = di.inject(syncThemeFromOperatingSystemInjectable);
|
||||||
|
|
||||||
|
return {
|
||||||
|
run: async () => {
|
||||||
|
await syncTheme.start();
|
||||||
|
},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
injectionToken: whenApplicationIsLoadingInjectionToken,
|
||||||
|
});
|
||||||
|
|
||||||
|
export default startSyncingThemeFromOperatingSystemInjectable;
|
||||||
@ -0,0 +1,25 @@
|
|||||||
|
/**
|
||||||
|
* 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 syncThemeFromOperatingSystemInjectable from "../../electron-app/features/sync-theme-from-operating-system.injectable";
|
||||||
|
import { beforeQuitOfBackEndInjectionToken } from "../../start-main-application/runnable-tokens/before-quit-of-back-end-injection-token";
|
||||||
|
|
||||||
|
const stopSyncingThemeFromOperatingSystemInjectable = getInjectable({
|
||||||
|
id: "stop-syncing-theme-from-operating-system",
|
||||||
|
|
||||||
|
instantiate: (di) => {
|
||||||
|
const syncTheme = di.inject(syncThemeFromOperatingSystemInjectable);
|
||||||
|
|
||||||
|
return {
|
||||||
|
run: async () => {
|
||||||
|
await syncTheme.stop();
|
||||||
|
},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
injectionToken: beforeQuitOfBackEndInjectionToken,
|
||||||
|
});
|
||||||
|
|
||||||
|
export default stopSyncingThemeFromOperatingSystemInjectable;
|
||||||
Loading…
Reference in New Issue
Block a user