diff --git a/packages/core/src/common/ipc/extension-handling.ts b/packages/core/src/common/ipc/extension-handling.ts index 1474a6d18d..0a07a56a29 100644 --- a/packages/core/src/common/ipc/extension-handling.ts +++ b/packages/core/src/common/ipc/extension-handling.ts @@ -4,6 +4,5 @@ */ export const extensionDiscoveryStateChannel = "extension-discovery:state"; -export const bundledExtensionsLoaded = "extension-loader:bundled-extensions-loaded"; export const extensionLoaderFromMainChannel = "extension-loader:main:state"; export const extensionLoaderFromRendererChannel = "extension-loader:renderer:state"; diff --git a/packages/core/src/features/extensions/loader/common/channels.ts b/packages/core/src/features/extensions/loader/common/channels.ts new file mode 100644 index 0000000000..72375f1695 --- /dev/null +++ b/packages/core/src/features/extensions/loader/common/channels.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 type { MessageChannel } from "../../../../common/utils/channel/message-channel-listener-injection-token"; +import type { RequestChannel } from "../../../../common/utils/channel/request-channel-listener-injection-token"; +import type { InstalledExtension } from "../../../../extensions/common-api"; +import type { LensExtensionId } from "../../../../extensions/lens-extension"; + +export const loadedExtensionsChannel: RequestChannel = { + id: "loaded-extensions", +}; + +export const extensionStateUpdateChannel: MessageChannel<[LensExtensionId, InstalledExtension]> = { + id: "add-extension", +}; + +export const removeExtensionChannel: MessageChannel = { + id: "remove-extension", +}; + +export const bundledExtensionsLoadedChannel: MessageChannel = { + id: "bundled-extensions-loaded", +}; diff --git a/packages/core/src/features/extensions/loader/main/bundled-loaded-listener.injectable.ts b/packages/core/src/features/extensions/loader/main/bundled-loaded-listener.injectable.ts new file mode 100644 index 0000000000..60fb9f0ef3 --- /dev/null +++ b/packages/core/src/features/extensions/loader/main/bundled-loaded-listener.injectable.ts @@ -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 { bundledExtensionsLoadedChannel } from "../common/channels"; +import extensionEventsInjectable from "./extension-events.injectable"; + +const bundledExtensionsLoadedListenerInjectable = getMessageChannelListenerInjectable({ + channel: bundledExtensionsLoadedChannel, + id: "main", + handler: (di) => { + const extensionEvents = di.inject(extensionEventsInjectable); + + return () => extensionEvents.emit("bundled-loaded"); + }, +}); + +export default bundledExtensionsLoadedListenerInjectable; diff --git a/packages/core/src/features/extensions/loader/main/extension-events.injectable.ts b/packages/core/src/features/extensions/loader/main/extension-events.injectable.ts new file mode 100644 index 0000000000..8a8f91b9be --- /dev/null +++ b/packages/core/src/features/extensions/loader/main/extension-events.injectable.ts @@ -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 EventEmitter from "events"; +import type TypedEventEmitter from "typed-emitter"; + +export interface ExtensionEvents { + "bundled-loaded": () => void; +} + +const extensionEventsInjectable = getInjectable({ + id: "extension-events", + instantiate: () => new EventEmitter() as TypedEventEmitter, +}); + +export default extensionEventsInjectable; diff --git a/packages/core/src/features/extensions/loader/main/wait-for-bundled-loaded.injectable.ts b/packages/core/src/features/extensions/loader/main/wait-for-bundled-loaded.injectable.ts new file mode 100644 index 0000000000..8ad5fa70fc --- /dev/null +++ b/packages/core/src/features/extensions/loader/main/wait-for-bundled-loaded.injectable.ts @@ -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 extensionEventsInjectable from "./extension-events.injectable"; + +const waitForBundledExtensionsToBeLoadedInjectable = getInjectable({ + id: "wait-for-bundled-extensions-to-be-loaded", + instantiate: (di) => { + const extensionEvents = di.inject(extensionEventsInjectable); + + return () => new Promise(resolve => extensionEvents.once("bundled-loaded", resolve)); + }, +}); + +export default waitForBundledExtensionsToBeLoadedInjectable; diff --git a/packages/core/src/features/extensions/loader/renderer/send-bundled-extensions-loaded.injectable.ts b/packages/core/src/features/extensions/loader/renderer/send-bundled-extensions-loaded.injectable.ts new file mode 100644 index 0000000000..3c64c80e6d --- /dev/null +++ b/packages/core/src/features/extensions/loader/renderer/send-bundled-extensions-loaded.injectable.ts @@ -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 { sendMessageToChannelInjectionToken } from "../../../../common/utils/channel/message-to-channel-injection-token"; +import { bundledExtensionsLoadedChannel } from "../common/channels"; + +const sendBundledExtensionsLoadedInjectable = getInjectable({ + id: "send-bundled-extensions-loaded", + instantiate: (di) => { + const sendMessageToChannel = di.inject(sendMessageToChannelInjectionToken); + + return () => sendMessageToChannel(bundledExtensionsLoadedChannel); + }, +}); + +export default sendBundledExtensionsLoadedInjectable; diff --git a/packages/core/src/main/getDiForUnitTesting.ts b/packages/core/src/main/getDiForUnitTesting.ts index 1e4c3291b9..1d06e42d61 100644 --- a/packages/core/src/main/getDiForUnitTesting.ts +++ b/packages/core/src/main/getDiForUnitTesting.ts @@ -23,7 +23,6 @@ import broadcastMessageInjectable from "../common/ipc/broadcast-message.injectab import electronQuitAndInstallUpdateInjectable from "./electron-app/features/electron-quit-and-install-update.injectable"; import electronUpdaterIsActiveInjectable from "./electron-app/features/electron-updater-is-active.injectable"; import setUpdateOnQuitInjectable from "./electron-app/features/set-update-on-quit.injectable"; -import waitUntilBundledExtensionsAreLoadedInjectable from "./start-main-application/lens-window/application-window/wait-until-bundled-extensions-are-loaded.injectable"; import electronInjectable from "./utils/resolve-system-proxy/electron.injectable"; import initializeClusterManagerInjectable from "./cluster/initialize-manager.injectable"; import type { GlobalOverride } from "../common/test-utils/get-global-override"; @@ -58,7 +57,6 @@ export function getDiForUnitTesting(opts: { doGeneralOverrides?: boolean } = {}) } di.override(electronInjectable, () => ({})); - di.override(waitUntilBundledExtensionsAreLoadedInjectable, () => async () => {}); overrideRunnablesHavingSideEffects(di); overrideElectronFeatures(di); diff --git a/packages/core/src/main/start-main-application/lens-window/application-window/wait-until-bundled-extensions-are-loaded.injectable.ts b/packages/core/src/main/start-main-application/lens-window/application-window/wait-until-bundled-extensions-are-loaded.injectable.ts index 4046db5d9d..84a2f52aff 100644 --- a/packages/core/src/main/start-main-application/lens-window/application-window/wait-until-bundled-extensions-are-loaded.injectable.ts +++ b/packages/core/src/main/start-main-application/lens-window/application-window/wait-until-bundled-extensions-are-loaded.injectable.ts @@ -3,27 +3,20 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import { getInjectable } from "@ogre-tools/injectable"; -import ipcMainInjectionToken from "../../../../common/ipc/ipc-main-injection-token"; -import { bundledExtensionsLoaded } from "../../../../common/ipc/extension-handling"; import { delay } from "../../../../common/utils"; +import waitForBundledExtensionsToBeLoadedInjectable from "../../../../features/extensions/loader/main/wait-for-bundled-loaded.injectable"; const waitUntilBundledExtensionsAreLoadedInjectable = getInjectable({ id: "wait-until-bundled-extensions-are-loaded", instantiate: (di) => { - const ipcMain = di.inject(ipcMainInjectionToken); + const waitForBundledExtensionsToBeLoaded = di.inject(waitForBundledExtensionsToBeLoadedInjectable); return async () => { - const viewHasLoaded = new Promise((resolve) => { - ipcMain.once(bundledExtensionsLoaded, () => resolve()); - }); - - await viewHasLoaded; + await waitForBundledExtensionsToBeLoaded(); await delay(50); // wait just a bit longer to let the first round of rendering happen }; }, - - causesSideEffects: true, }); export default waitUntilBundledExtensionsAreLoadedInjectable; diff --git a/packages/core/src/renderer/frames/root-frame/init-root-frame.injectable.ts b/packages/core/src/renderer/frames/root-frame/init-root-frame.injectable.ts index 8d2c3a43be..52c8bc1ffb 100644 --- a/packages/core/src/renderer/frames/root-frame/init-root-frame.injectable.ts +++ b/packages/core/src/renderer/frames/root-frame/init-root-frame.injectable.ts @@ -3,7 +3,6 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import { getInjectable } from "@ogre-tools/injectable"; -import ipcRendererInjectable from "../../utils/channel/ipc-renderer.injectable"; import bindProtocolAddRouteHandlersInjectable from "../../protocol-handler/bind-protocol-add-route-handlers/bind-protocol-add-route-handlers.injectable"; import lensProtocolRouterRendererInjectable from "../../protocol-handler/lens-protocol-router-renderer/lens-protocol-router-renderer.injectable"; import catalogEntityRegistryInjectable from "../../api/catalog/entity/registry.injectable"; @@ -12,18 +11,18 @@ import loadExtensionsInjectable from "../load-extensions.injectable"; import loggerInjectable from "../../../common/logger.injectable"; import { delay } from "../../../common/utils"; import { broadcastMessage } from "../../../common/ipc"; -import { bundledExtensionsLoaded } from "../../../common/ipc/extension-handling"; +import sendBundledExtensionsLoadedInjectable from "../../../features/extensions/loader/renderer/send-bundled-extensions-loaded.injectable"; const initRootFrameInjectable = getInjectable({ id: "init-root-frame", instantiate: (di) => { const loadExtensions = di.inject(loadExtensionsInjectable); const registerIpcListeners = di.inject(registerIpcListenersInjectable); - const ipcRenderer = di.inject(ipcRendererInjectable); const bindProtocolAddRouteHandlers = di.inject(bindProtocolAddRouteHandlersInjectable); const lensProtocolRouterRenderer = di.inject(lensProtocolRouterRendererInjectable); const catalogEntityRegistry = di.inject(catalogEntityRegistryInjectable); const logger = di.inject(loggerInjectable); + const sendBundledExtensionsLoaded = di.inject(sendBundledExtensionsLoadedInjectable); return async (unmountRoot: () => void) => { catalogEntityRegistry.init(); @@ -42,7 +41,7 @@ const initRootFrameInjectable = getInjectable({ await Promise.race([bundledExtensionsFinished, timeout]); } finally { - ipcRenderer.send(bundledExtensionsLoaded); + sendBundledExtensionsLoaded(); } lensProtocolRouterRenderer.init();