diff --git a/src/main/initializers/init-ipc-main-handlers/init-ipc-main-handlers.injectable.ts b/src/main/initializers/init-ipc-main-handlers/init-ipc-main-handlers.injectable.ts deleted file mode 100644 index d92897bb50..0000000000 --- a/src/main/initializers/init-ipc-main-handlers/init-ipc-main-handlers.injectable.ts +++ /dev/null @@ -1,21 +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 directoryForLensLocalStorageInjectable from "../../../common/directory-for-lens-local-storage/directory-for-lens-local-storage.injectable"; -import { initIpcMainHandlers } from "./init-ipc-main-handlers"; -import getAbsolutePathInjectable from "../../../common/path/get-absolute-path.injectable"; -import applicationMenuItemsInjectable from "../../menu/application-menu-items.injectable"; - -const initIpcMainHandlersInjectable = getInjectable({ - id: "init-ipc-main-handlers", - - instantiate: (di) => initIpcMainHandlers({ - applicationMenuItems: di.inject(applicationMenuItemsInjectable), - directoryForLensLocalStorage: di.inject(directoryForLensLocalStorageInjectable), - getAbsolutePath: di.inject(getAbsolutePathInjectable), - }), -}); - -export default initIpcMainHandlersInjectable; diff --git a/src/main/start-main-application/on-application-is-ready/implementations/emit-service-start-to-command-bus.injectable.ts b/src/main/start-main-application/on-application-is-ready/implementations/emit-service-start-to-command-bus.injectable.ts new file mode 100644 index 0000000000..3aab82fe05 --- /dev/null +++ b/src/main/start-main-application/on-application-is-ready/implementations/emit-service-start-to-command-bus.injectable.ts @@ -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 { onApplicationIsReadyInjectionToken } from "../on-application-is-ready-injection-token"; +import appEventBusInjectable from "../../../../common/app-event-bus/app-event-bus.injectable"; + +const emitServiceStartToCommandBusInjectable = getInjectable({ + id: "emit-service-start-to-command-bus", + + instantiate: (di) => { + const appEventBus = di.inject(appEventBusInjectable); + + return { + run: () => { + appEventBus.emit({ name: "service", action: "start" }); + }, + }; + }, + + injectionToken: onApplicationIsReadyInjectionToken, +}); + +export default emitServiceStartToCommandBusInjectable; diff --git a/src/main/start-main-application/on-application-is-ready/implementations/initialize-extensions.injectable.ts b/src/main/start-main-application/on-application-is-ready/implementations/initialize-extensions.injectable.ts new file mode 100644 index 0000000000..d8cee1927c --- /dev/null +++ b/src/main/start-main-application/on-application-is-ready/implementations/initialize-extensions.injectable.ts @@ -0,0 +1,62 @@ +/** + * 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 { onApplicationIsReadyInjectionToken } from "../on-application-is-ready-injection-token"; +import type { InstalledExtension } from "../../../../extensions/extension-discovery/extension-discovery"; +import type { LensExtensionId } from "../../../../extensions/lens-extension"; +import loggerInjectable from "../../../../common/logger.injectable"; +import extensionDiscoveryInjectable from "../../../../extensions/extension-discovery/extension-discovery.injectable"; +import extensionLoaderInjectable from "../../../../extensions/extension-loader/extension-loader.injectable"; +import { dialog } from "electron"; + +const initializeExtensionsInjectable = getInjectable({ + id: "initialize-extensions", + + instantiate: (di) => { + const logger = di.inject(loggerInjectable); + const extensionDiscovery = di.inject(extensionDiscoveryInjectable); + const extensionLoader = di.inject(extensionLoaderInjectable); + + return { + run: async () => { + logger.info("🧩 Initializing extensions"); + + // call after windowManager to see splash earlier + try { + const extensions = await extensionDiscovery.load(); + + // Start watching after bundled extensions are loaded + extensionDiscovery.watchExtensions(); + + // Subscribe to extensions that are copied or deleted to/from the extensions folder + extensionDiscovery.events + .on("add", (extension: InstalledExtension) => { + extensionLoader.addExtension(extension); + }) + .on("remove", (lensExtensionId: LensExtensionId) => { + extensionLoader.removeExtension(lensExtensionId); + }); + + extensionLoader.initExtensions(extensions); + } catch (error) { + dialog.showErrorBox( + "Lens Error", + `Could not load extensions${ + error?.message ? `: ${error.message}` : "" + }`, + ); + console.error(error); + console.trace(); + } + }, + }; + }, + + causesSideEffects: true, + + injectionToken: onApplicationIsReadyInjectionToken, +}); + +export default initializeExtensionsInjectable; diff --git a/src/main/start-main-application/on-application-is-ready/implementations/setup-detector-registry.injectable.ts b/src/main/start-main-application/on-application-is-ready/implementations/setup-detector-registry.injectable.ts new file mode 100644 index 0000000000..f52372c5b1 --- /dev/null +++ b/src/main/start-main-application/on-application-is-ready/implementations/setup-detector-registry.injectable.ts @@ -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 { onApplicationIsReadyInjectionToken } from "../on-application-is-ready-injection-token"; +import { ClusterIdDetector } from "../../../cluster-detectors/cluster-id-detector"; +import { LastSeenDetector } from "../../../cluster-detectors/last-seen-detector"; +import { VersionDetector } from "../../../cluster-detectors/version-detector"; +import { DistributionDetector } from "../../../cluster-detectors/distribution-detector"; +import { NodesCountDetector } from "../../../cluster-detectors/nodes-count-detector"; +import detectorRegistryInjectable from "../../../cluster-detectors/detector-registry.injectable"; + +const setupDetectorRegistryInjectable = getInjectable({ + id: "setup-detector-registry", + + instantiate: (di) => { + const detectorRegistry = di.inject(detectorRegistryInjectable); + + return { + run: () => { + detectorRegistry + .add(ClusterIdDetector) + .add(LastSeenDetector) + .add(VersionDetector) + .add(DistributionDetector) + .add(NodesCountDetector); + }, + }; + }, + + injectionToken: onApplicationIsReadyInjectionToken, +}); + +export default setupDetectorRegistryInjectable; diff --git a/src/main/start-main-application/on-application-is-ready/implementations/setup-developer-tools-in-development-environment.injectable.ts b/src/main/start-main-application/on-application-is-ready/implementations/setup-developer-tools-in-development-environment.injectable.ts new file mode 100644 index 0000000000..331237192a --- /dev/null +++ b/src/main/start-main-application/on-application-is-ready/implementations/setup-developer-tools-in-development-environment.injectable.ts @@ -0,0 +1,40 @@ +/** + * 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 { onApplicationIsReadyInjectionToken } from "../on-application-is-ready-injection-token"; +import loggerInjectable from "../../../../common/logger.injectable"; + +const setupDeveloperToolsInDevelopmentEnvironmentInjectable = getInjectable({ + id: "setup-developer-tools-in-development-environment", + + instantiate: (di) => { + const logger = di.inject(loggerInjectable); + + return { + run: () => { + if (process.env.NODE_ENV !== "development") { + return; + } + + logger.info("🤓 Installing developer tools"); + + import("electron-devtools-installer") + .then(({ default: devToolsInstaller, REACT_DEVELOPER_TOOLS }) => + devToolsInstaller([REACT_DEVELOPER_TOOLS]), + ) + .then((name) => + logger.info(`[DEVTOOLS-INSTALLER]: installed ${name}`), + ) + .catch((error) => + logger.error(`[DEVTOOLS-INSTALLER]: failed`, { error }), + ); + }, + }; + }, + + injectionToken: onApplicationIsReadyInjectionToken, +}); + +export default setupDeveloperToolsInDevelopmentEnvironmentInjectable; diff --git a/src/main/start-main-application/on-application-is-ready/implementations/setup-file-protocol.injectable.ts b/src/main/start-main-application/on-application-is-ready/implementations/setup-file-protocol.injectable.ts new file mode 100644 index 0000000000..858cafd69e --- /dev/null +++ b/src/main/start-main-application/on-application-is-ready/implementations/setup-file-protocol.injectable.ts @@ -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 { onApplicationIsReadyInjectionToken } from "../on-application-is-ready-injection-token"; +import { registerFileProtocol } from "../../../../common/register-protocol"; + +// TODO: Remove side effect on import defining __static +import "../../../../common/vars"; + +const setupFileProtocolInjectable = getInjectable({ + + id: "setup-file-protocol", + + instantiate: () => ({ + run: () => { + registerFileProtocol("static", __static); + }, + }), + + causesSideEffects: true, + + injectionToken: onApplicationIsReadyInjectionToken, +}); + +export default setupFileProtocolInjectable; diff --git a/src/main/start-main-application/on-application-is-ready/implementations/setup-hardware-acceleration.injectable.ts b/src/main/start-main-application/on-application-is-ready/implementations/setup-hardware-acceleration.injectable.ts new file mode 100644 index 0000000000..5bd357de29 --- /dev/null +++ b/src/main/start-main-application/on-application-is-ready/implementations/setup-hardware-acceleration.injectable.ts @@ -0,0 +1,29 @@ +/** + * 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 { onApplicationIsReadyInjectionToken } from "../on-application-is-ready-injection-token"; +import electronAppInjectable from "../../../app-paths/get-electron-app-path/electron-app/electron-app.injectable"; + +const setupHardwareAccelerationInjectable = getInjectable({ + id: "setup-hardware-acceleration", + + instantiate: (di) => { + const app = di.inject(electronAppInjectable); + + return { + run: async () => { + if (process.env.LENS_DISABLE_GPU) { + app.disableHardwareAcceleration(); + } + }, + }; + }, + + causesSideEffects: true, + + injectionToken: onApplicationIsReadyInjectionToken, +}); + +export default setupHardwareAccelerationInjectable; diff --git a/src/main/start-main-application/on-application-is-ready/implementations/setup-ipc-main-handlers/setup-ipc-main-handlers.injectable.ts b/src/main/start-main-application/on-application-is-ready/implementations/setup-ipc-main-handlers/setup-ipc-main-handlers.injectable.ts new file mode 100644 index 0000000000..11a330aa39 --- /dev/null +++ b/src/main/start-main-application/on-application-is-ready/implementations/setup-ipc-main-handlers/setup-ipc-main-handlers.injectable.ts @@ -0,0 +1,45 @@ +/** + * 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 directoryForLensLocalStorageInjectable from "../../../../../common/directory-for-lens-local-storage/directory-for-lens-local-storage.injectable"; +import { setupIpcMainHandlers } from "./setup-ipc-main-handlers"; +import loggerInjectable from "../../../../../common/logger.injectable"; +import clusterManagerInjectable from "../../../../cluster-manager.injectable"; +import applicationMenuItemsInjectable from "../../../../menu/application-menu-items.injectable"; +import getAbsolutePathInjectable from "../../../../../common/path/get-absolute-path.injectable"; +import { onApplicationIsReadyInjectionToken } from "../../on-application-is-ready-injection-token"; + +const setupIpcMainHandlersInjectable = getInjectable({ + id: "setup-ipc-main-handlers", + + instantiate: (di) => { + const logger = di.inject(loggerInjectable); + + const directoryForLensLocalStorage = di.inject( + directoryForLensLocalStorageInjectable, + ); + + const clusterManager = di.inject(clusterManagerInjectable); + const applicationMenuItems = di.inject(applicationMenuItemsInjectable); + const getAbsolutePath = di.inject(getAbsolutePathInjectable); + + return { + run: () => { + logger.debug("[APP-MAIN] initializing ipc main handlers"); + + setupIpcMainHandlers({ + applicationMenuItems, + getAbsolutePath, + directoryForLensLocalStorage, + clusterManager, + }); + }, + }; + }, + + injectionToken: onApplicationIsReadyInjectionToken, +}); + +export default setupIpcMainHandlersInjectable; diff --git a/src/main/initializers/init-ipc-main-handlers/init-ipc-main-handlers.ts b/src/main/start-main-application/on-application-is-ready/implementations/setup-ipc-main-handlers/setup-ipc-main-handlers.ts similarity index 75% rename from src/main/initializers/init-ipc-main-handlers/init-ipc-main-handlers.ts rename to src/main/start-main-application/on-application-is-ready/implementations/setup-ipc-main-handlers/setup-ipc-main-handlers.ts index 1a657b78be..5466175c5b 100644 --- a/src/main/initializers/init-ipc-main-handlers/init-ipc-main-handlers.ts +++ b/src/main/start-main-application/on-application-is-ready/implementations/setup-ipc-main-handlers/setup-ipc-main-handlers.ts @@ -2,37 +2,37 @@ * Copyright (c) OpenLens Authors. All rights reserved. * Licensed under MIT License. See LICENSE in root directory for more information. */ - import type { IpcMainInvokeEvent } from "electron"; import { BrowserWindow, Menu } from "electron"; -import { clusterFrameMap } from "../../../common/cluster-frames"; -import { clusterActivateHandler, clusterSetFrameIdHandler, clusterVisibilityHandler, clusterRefreshHandler, clusterDisconnectHandler, clusterKubectlApplyAllHandler, clusterKubectlDeleteAllHandler, clusterDeleteHandler, clusterSetDeletingHandler, clusterClearDeletingHandler } from "../../../common/ipc/cluster"; -import type { ClusterId } from "../../../common/cluster-types"; -import { ClusterStore } from "../../../common/cluster-store/cluster-store"; -import { appEventBus } from "../../../common/app-event-bus/event-bus"; -import { broadcastMainChannel, broadcastMessage, ipcMainHandle, ipcMainOn } from "../../../common/ipc"; -import { catalogEntityRegistry } from "../../catalog"; -import { pushCatalogToRenderer } from "../../catalog-pusher"; -import { ClusterManager } from "../../cluster-manager"; -import { ResourceApplier } from "../../resource-applier"; +import { clusterFrameMap } from "../../../../../common/cluster-frames"; +import { clusterActivateHandler, clusterSetFrameIdHandler, clusterVisibilityHandler, clusterRefreshHandler, clusterDisconnectHandler, clusterKubectlApplyAllHandler, clusterKubectlDeleteAllHandler, clusterDeleteHandler, clusterSetDeletingHandler, clusterClearDeletingHandler } from "../../../../../common/ipc/cluster"; +import type { ClusterId } from "../../../../../common/cluster-types"; +import { ClusterStore } from "../../../../../common/cluster-store/cluster-store"; +import { appEventBus } from "../../../../../common/app-event-bus/event-bus"; +import { broadcastMainChannel, broadcastMessage, ipcMainHandle, ipcMainOn } from "../../../../../common/ipc"; +import { catalogEntityRegistry } from "../../../../catalog"; +import { pushCatalogToRenderer } from "../../../../catalog-pusher"; +import type { ClusterManager } from "../../../../cluster-manager"; +import { ResourceApplier } from "../../../../resource-applier"; import { remove } from "fs-extra"; -import { onLocationChange, handleWindowAction } from "../../ipc/window"; -import { openFilePickingDialogChannel } from "../../../common/ipc/dialog"; -import { showOpenDialog } from "../../ipc/dialog"; -import { windowActionHandleChannel, windowLocationChangedChannel, windowOpenAppMenuAsContextMenuChannel } from "../../../common/ipc/window"; -import { getNativeColorTheme } from "../../native-theme"; -import { getNativeThemeChannel } from "../../../common/ipc/native-theme"; -import type { GetAbsolutePath } from "../../../common/path/get-absolute-path.injectable"; import type { IComputedValue } from "mobx"; -import type { MenuItemOpts } from "../../menu/application-menu-items.injectable"; +import type { GetAbsolutePath } from "../../../../../common/path/get-absolute-path.injectable"; +import type { MenuItemOpts } from "../../../../menu/application-menu-items.injectable"; +import { windowActionHandleChannel, windowLocationChangedChannel, windowOpenAppMenuAsContextMenuChannel } from "../../../../../common/ipc/window"; +import { handleWindowAction, onLocationChange } from "../../../../ipc/window"; +import { openFilePickingDialogChannel } from "../../../../../common/ipc/dialog"; +import { showOpenDialog } from "../../../../ipc/dialog"; +import { getNativeThemeChannel } from "../../../../../common/ipc/native-theme"; +import { getNativeColorTheme } from "../../../../native-theme"; interface Dependencies { directoryForLensLocalStorage: string; getAbsolutePath: GetAbsolutePath; applicationMenuItems: IComputedValue; + clusterManager: ClusterManager; } -export const initIpcMainHandlers = ({ applicationMenuItems, directoryForLensLocalStorage, getAbsolutePath }: Dependencies) => () => { +export const setupIpcMainHandlers = ({ applicationMenuItems, directoryForLensLocalStorage, getAbsolutePath, clusterManager }: Dependencies) => { ipcMainHandle(clusterActivateHandler, (event, clusterId: ClusterId, force = false) => { return ClusterStore.getInstance() .getById(clusterId) @@ -51,7 +51,7 @@ export const initIpcMainHandlers = ({ applicationMenuItems, directoryForLensLoca }); ipcMainOn(clusterVisibilityHandler, (event, clusterId?: ClusterId) => { - ClusterManager.getInstance().visibleCluster = clusterId; + clusterManager.visibleCluster = clusterId; }); ipcMainHandle(clusterRefreshHandler, (event, clusterId: ClusterId) => { @@ -97,11 +97,11 @@ export const initIpcMainHandlers = ({ applicationMenuItems, directoryForLensLoca }); ipcMainHandle(clusterSetDeletingHandler, (event, clusterId: string) => { - ClusterManager.getInstance().deleting.add(clusterId); + clusterManager.deleting.add(clusterId); }); ipcMainHandle(clusterClearDeletingHandler, (event, clusterId: string) => { - ClusterManager.getInstance().deleting.delete(clusterId); + clusterManager.deleting.delete(clusterId); }); ipcMainHandle(clusterKubectlApplyAllHandler, async (event, clusterId: ClusterId, resources: string[], extraArgs: string[]) => { diff --git a/src/main/start-main-application/on-application-is-ready/implementations/setup-lens-proxy.injectable.ts b/src/main/start-main-application/on-application-is-ready/implementations/setup-lens-proxy.injectable.ts new file mode 100644 index 0000000000..ae0d897c34 --- /dev/null +++ b/src/main/start-main-application/on-application-is-ready/implementations/setup-lens-proxy.injectable.ts @@ -0,0 +1,79 @@ +/** + * 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 { onApplicationIsReadyInjectionToken } from "../on-application-is-ready-injection-token"; +import { + getAppVersion, + getAppVersionFromProxyServer, +} from "../../../../common/utils"; +import exitAppInjectable from "../../../app-paths/get-electron-app-path/electron-app/exit-app.injectable"; +import lensProxyInjectable from "../../../lens-proxy.injectable"; +import loggerInjectable from "../../../../common/logger.injectable"; +import { dialog } from "electron"; +import lensProxyPortNumberStateInjectable from "../../../lens-proxy-port-number-state.injectable"; +import isWindowsInjectable from "../../../../common/vars/is-windows.injectable"; + +const setupLensProxyInjectable = getInjectable({ + id: "setup-lens-proxy", + + instantiate: (di) => { + const lensProxy = di.inject(lensProxyInjectable); + const exitApp = di.inject(exitAppInjectable); + const logger = di.inject(loggerInjectable); + const lensProxyPortNumberState = di.inject(lensProxyPortNumberStateInjectable); + const isWindows = di.inject(isWindowsInjectable); + + return { + run: async () => { + try { + logger.info("🔌 Starting LensProxy"); + await lensProxy.listen(); // lensProxy.port available + } catch (error) { + dialog.showErrorBox("Lens Error", `Could not start proxy: ${error?.message || "unknown error"}`); + + return exitApp(); + } + + // test proxy connection + try { + logger.info("🔎 Testing LensProxy connection ..."); + const versionFromProxy = await getAppVersionFromProxyServer( + lensProxyPortNumberState.get(), + ); + + if (getAppVersion() !== versionFromProxy) { + logger.error("Proxy server responded with invalid response"); + + return exitApp(); + } + + logger.info("⚡ LensProxy connection OK"); + } catch (error) { + logger.error(`🛑 LensProxy: failed connection test: ${error}`); + + const hostsPath = isWindows + ? "C:\\windows\\system32\\drivers\\etc\\hosts" + : "/etc/hosts"; + const message = [ + `Failed connection test: ${error}`, + "Check to make sure that no other versions of Lens are running", + `Check ${hostsPath} to make sure that it is clean and that the localhost loopback is at the top and set to 127.0.0.1`, + "If you have HTTP_PROXY or http_proxy set in your environment, make sure that the localhost and the ipv4 loopback address 127.0.0.1 are added to the NO_PROXY environment variable.", + ]; + + dialog.showErrorBox("Lens Proxy Error", message.join("\n\n")); + + return exitApp(); + } + }, + }; + }, + + causesSideEffects: true, + + injectionToken: onApplicationIsReadyInjectionToken, +}); + +export default setupLensProxyInjectable; diff --git a/src/main/start-main-application/on-application-is-ready/implementations/setup-listener-for-initial-state-of-cluster-store.injectable.ts b/src/main/start-main-application/on-application-is-ready/implementations/setup-listener-for-initial-state-of-cluster-store.injectable.ts new file mode 100644 index 0000000000..1294e726a1 --- /dev/null +++ b/src/main/start-main-application/on-application-is-ready/implementations/setup-listener-for-initial-state-of-cluster-store.injectable.ts @@ -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 { onApplicationIsReadyInjectionToken } from "../on-application-is-ready-injection-token"; +import clusterStoreInjectable from "../../../../common/cluster-store/cluster-store.injectable"; + +const setupListenerForInitialStateOfClusterStoreInjectable = getInjectable({ + id: "setup-listener-for-initial-state-of-cluster-store", + + instantiate: (di) => { + const clusterStore = di.inject(clusterStoreInjectable); + + return { + run: () => { + clusterStore.provideInitialFromMain(); + }, + }; + }, + + injectionToken: onApplicationIsReadyInjectionToken, +}); + +export default setupListenerForInitialStateOfClusterStoreInjectable; diff --git a/src/main/start-main-application/on-application-is-ready/implementations/setup-listener-for-root-frame-rendering.injectable.ts b/src/main/start-main-application/on-application-is-ready/implementations/setup-listener-for-root-frame-rendering.injectable.ts new file mode 100644 index 0000000000..15ac3a009d --- /dev/null +++ b/src/main/start-main-application/on-application-is-ready/implementations/setup-listener-for-root-frame-rendering.injectable.ts @@ -0,0 +1,42 @@ +/** + * 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 { ipcMainOn } from "../../../../common/ipc"; +import { IpcRendererNavigationEvents } from "../../../../renderer/navigation/events"; +import lensProtocolRouterMainInjectable from "../../../protocol-handler/lens-protocol-router-main/lens-protocol-router-main.injectable"; +import { onRootFrameRenderInjectionToken } from "../../on-root-frame-render/on-root-frame-render-injection-token"; +import { onApplicationIsReadyInjectionToken } from "../on-application-is-ready-injection-token"; +import { runManyFor } from "../../run-many-for"; + +const setupListenerForRootFrameRenderingInjectable = getInjectable({ + id: "setup-listener-for-root-frame-rendering", + + instantiate: (di) => { + const lensProtocolRouterMain = di.inject(lensProtocolRouterMainInjectable); + const runMany = runManyFor(di); + + const runOnRootFrameRender = runMany( + onRootFrameRenderInjectionToken, + ); + + return { + run: () => { + ipcMainOn(IpcRendererNavigationEvents.LOADED, async () => { + + await runOnRootFrameRender(); + + lensProtocolRouterMain.rendererLoaded = true; + }); + }, + }; + }, + + // Direct usage of IPC + causesSideEffects: true, + + injectionToken: onApplicationIsReadyInjectionToken, +}); + +export default setupListenerForRootFrameRenderingInjectable; diff --git a/src/main/start-main-application/on-application-is-ready/implementations/setup-os-theme-updates.injectable.ts b/src/main/start-main-application/on-application-is-ready/implementations/setup-os-theme-updates.injectable.ts new file mode 100644 index 0000000000..00dfd5a94c --- /dev/null +++ b/src/main/start-main-application/on-application-is-ready/implementations/setup-os-theme-updates.injectable.ts @@ -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 { broadcastNativeThemeOnUpdate } from "../../../native-theme"; +import { onApplicationIsReadyInjectionToken } from "../on-application-is-ready-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: onApplicationIsReadyInjectionToken, +}); + +export default setupOsThemeUpdatesInjectable; diff --git a/src/main/start-main-application/on-application-is-ready/implementations/setup-prometheus-registry.injectable.ts b/src/main/start-main-application/on-application-is-ready/implementations/setup-prometheus-registry.injectable.ts new file mode 100644 index 0000000000..0486b002f2 --- /dev/null +++ b/src/main/start-main-application/on-application-is-ready/implementations/setup-prometheus-registry.injectable.ts @@ -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 { onApplicationIsReadyInjectionToken } from "../on-application-is-ready-injection-token"; +import { PrometheusLens } from "../../../prometheus/lens"; +import { PrometheusHelm } from "../../../prometheus/helm"; +import { PrometheusOperator } from "../../../prometheus/operator"; +import { PrometheusStacklight } from "../../../prometheus/stacklight"; +import prometheusProviderRegistryInjectable from "../../../prometheus/prometheus-provider-registry.injectable"; + +const setupPrometheusRegistryInjectable = getInjectable({ + id: "setup-prometheus-registry", + + instantiate: (di) => { + const prometheusProviderRegistry = di.inject(prometheusProviderRegistryInjectable); + + return { + run: () => { + prometheusProviderRegistry + .registerProvider(new PrometheusLens()) + .registerProvider(new PrometheusHelm()) + .registerProvider(new PrometheusOperator()) + .registerProvider(new PrometheusStacklight()); + }, + }; + }, + + injectionToken: onApplicationIsReadyInjectionToken, +}); + +export default setupPrometheusRegistryInjectable; diff --git a/src/main/start-main-application/on-application-is-ready/implementations/setup-reactions-in-user-store.injectable.ts b/src/main/start-main-application/on-application-is-ready/implementations/setup-reactions-in-user-store.injectable.ts new file mode 100644 index 0000000000..1dde6988e6 --- /dev/null +++ b/src/main/start-main-application/on-application-is-ready/implementations/setup-reactions-in-user-store.injectable.ts @@ -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 { onApplicationIsReadyInjectionToken } from "../on-application-is-ready-injection-token"; +import userStoreInjectable from "../../../../common/user-store/user-store.injectable"; + +const setupReactionsInUserStoreInjectable = getInjectable({ + id: "setup-reactions-in-user-store", + + instantiate: (di) => { + const userStore = di.inject(userStoreInjectable); + + return { + run: () => { + userStore.startMainReactions(); + }, + }; + }, + + injectionToken: onApplicationIsReadyInjectionToken, +}); + +export default setupReactionsInUserStoreInjectable; diff --git a/src/main/start-main-application/on-application-is-ready/implementations/setup-sentry.injectable.ts b/src/main/start-main-application/on-application-is-ready/implementations/setup-sentry.injectable.ts new file mode 100644 index 0000000000..679e251e33 --- /dev/null +++ b/src/main/start-main-application/on-application-is-ready/implementations/setup-sentry.injectable.ts @@ -0,0 +1,23 @@ +/** + * 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 { onApplicationIsReadyInjectionToken } from "../on-application-is-ready-injection-token"; +import { SentryInit } from "../../../../common/sentry"; + +const setupSentryInjectable = getInjectable({ + id: "setup-sentry", + + instantiate: () => ({ + run: () => { + SentryInit(); + }, + }), + + causesSideEffects: true, + + injectionToken: onApplicationIsReadyInjectionToken, +}); + +export default setupSentryInjectable; diff --git a/src/main/start-main-application/on-application-is-ready/implementations/setup-shell.injectable.ts b/src/main/start-main-application/on-application-is-ready/implementations/setup-shell.injectable.ts new file mode 100644 index 0000000000..aa8b318bd5 --- /dev/null +++ b/src/main/start-main-application/on-application-is-ready/implementations/setup-shell.injectable.ts @@ -0,0 +1,29 @@ +/** + * 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 { onApplicationIsReadyInjectionToken } from "../on-application-is-ready-injection-token"; +import { shellSync } from "../../../shell-sync"; +import loggerInjectable from "../../../../common/logger.injectable"; + +const setupShellInjectable = getInjectable({ + id: "setup-shell", + + instantiate: (di) => { + const logger = di.inject(loggerInjectable); + + return { + run: async () => { + logger.info("🐚 Syncing shell environment"); + + await shellSync(); + }, + }; + }, + + injectionToken: onApplicationIsReadyInjectionToken, + causesSideEffects: true, +}); + +export default setupShellInjectable; diff --git a/src/main/start-main-application/on-application-is-ready/implementations/setup-syncing-of-general-catalog-entities.injectable.ts b/src/main/start-main-application/on-application-is-ready/implementations/setup-syncing-of-general-catalog-entities.injectable.ts new file mode 100644 index 0000000000..34218e649a --- /dev/null +++ b/src/main/start-main-application/on-application-is-ready/implementations/setup-syncing-of-general-catalog-entities.injectable.ts @@ -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 { onApplicationIsReadyInjectionToken } from "../on-application-is-ready-injection-token"; +import syncGeneralCatalogEntitiesInjectable from "../../../catalog-sources/sync-general-catalog-entities.injectable"; + +const setupSyncingOfGeneralCatalogEntitiesInjectable = getInjectable({ + id: "setup-syncing-of-general-catalog-entities", + + instantiate: (di) => { + const syncGeneralCatalogEntities = di.inject( + syncGeneralCatalogEntitiesInjectable, + ); + + return { + run: () => { + syncGeneralCatalogEntities(); + }, + }; + }, + + injectionToken: onApplicationIsReadyInjectionToken, +}); + +export default setupSyncingOfGeneralCatalogEntitiesInjectable; diff --git a/src/main/start-main-application/on-application-is-ready/implementations/setup-syncing-of-weblinks.injectable.ts b/src/main/start-main-application/on-application-is-ready/implementations/setup-syncing-of-weblinks.injectable.ts new file mode 100644 index 0000000000..9a45d5ea72 --- /dev/null +++ b/src/main/start-main-application/on-application-is-ready/implementations/setup-syncing-of-weblinks.injectable.ts @@ -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 { onApplicationIsReadyInjectionToken } from "../on-application-is-ready-injection-token"; +import { syncWeblinks } from "../../../catalog-sources"; +import weblinkStoreInjectable from "../../../../common/weblink-store.injectable"; + +const setupSyncingOfWeblinksInjectable = getInjectable({ + id: "setup-syncing-of-weblinks", + + instantiate: (di) => { + const weblinkStore = di.inject(weblinkStoreInjectable); + + return { + run: () => { + syncWeblinks(weblinkStore); + }, + }; + }, + + injectionToken: onApplicationIsReadyInjectionToken, +}); + +export default setupSyncingOfWeblinksInjectable; diff --git a/src/main/start-main-application/on-application-is-ready/implementations/start-main-window.injectable.ts b/src/main/start-main-application/on-application-is-ready/implementations/start-main-window.injectable.ts new file mode 100644 index 0000000000..41db28c798 --- /dev/null +++ b/src/main/start-main-application/on-application-is-ready/implementations/start-main-window.injectable.ts @@ -0,0 +1,41 @@ +/** + * 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 windowManagerInjectable from "../../../window-manager.injectable"; +import electronAppInjectable from "../../../app-paths/get-electron-app-path/electron-app/electron-app.injectable"; +import loggerInjectable from "../../../../common/logger.injectable"; +import isMacInjectable from "../../../../common/vars/is-mac.injectable"; +import { onApplicationIsReadyInjectionToken } from "../on-application-is-ready-injection-token"; + +const startMainWindowInjectable = getInjectable({ + id: "start-main-window", + + instantiate: (di) => { + const windowManager = di.inject(windowManagerInjectable); + const app = di.inject(electronAppInjectable); + const logger = di.inject(loggerInjectable); + const isMac = di.inject(isMacInjectable); + + return { + run: async () => { + // Start the app without showing the main window when auto starting on login + // (On Windows and Linux, we get a flag. On MacOS, we get special API.) + const startHidden = + process.argv.includes("--hidden") || + (isMac && app.getLoginItemSettings().wasOpenedAsHidden); + + logger.info("🖥️ Starting WindowManager"); + + if (!startHidden) { + await windowManager.ensureMainWindow(); + } + }, + }; + }, + + injectionToken: onApplicationIsReadyInjectionToken, +}); + +export default startMainWindowInjectable;