diff --git a/packages/core/src/renderer/before-frame-starts/runnables/setup-root-mac-class.injectable.ts b/packages/core/src/renderer/before-frame-starts/runnables/setup-root-mac-class.injectable.ts
index 56b9ce66fa..c35959fbfe 100644
--- a/packages/core/src/renderer/before-frame-starts/runnables/setup-root-mac-class.injectable.ts
+++ b/packages/core/src/renderer/before-frame-starts/runnables/setup-root-mac-class.injectable.ts
@@ -4,6 +4,7 @@
*/
import { getInjectable } from "@ogre-tools/injectable";
import isMacInjectable from "../../../common/vars/is-mac.injectable";
+import rootElementInjectable from "../../window/root-element.injectable";
import { beforeFrameStartsSecondInjectionToken } from "../tokens";
const setupRootMacClassnameInjectable = getInjectable({
@@ -12,9 +13,9 @@ const setupRootMacClassnameInjectable = getInjectable({
id: "setup-root-mac-classname",
run: () => {
const isMac = di.inject(isMacInjectable);
- const rootElem = document.getElementById("app");
+ const rootElem = di.inject(rootElementInjectable);
- rootElem?.classList.toggle("is-mac", isMac);
+ rootElem.classList.toggle("is-mac", isMac);
},
}),
injectionToken: beforeFrameStartsSecondInjectionToken,
diff --git a/packages/core/src/renderer/bootstrap.tsx b/packages/core/src/renderer/bootstrap.tsx
index 9931fbed3a..949e10e687 100644
--- a/packages/core/src/renderer/bootstrap.tsx
+++ b/packages/core/src/renderer/bootstrap.tsx
@@ -6,7 +6,7 @@
import "./components/app.scss";
import React from "react";
-import { render, unmountComponentAtNode } from "react-dom";
+import { render } from "react-dom";
import { DefaultProps } from "./mui-base-theme";
import { DiContextProvider } from "@ogre-tools/injectable-react";
import type { DiContainer } from "@ogre-tools/injectable";
@@ -14,32 +14,27 @@ import initRootFrameInjectable from "./frames/root-frame/init-root-frame.injecta
import initClusterFrameInjectable from "./frames/cluster-frame/init-cluster-frame.injectable";
import { Router } from "react-router";
import historyInjectable from "./navigation/history.injectable";
-import assert from "assert";
import startFrameInjectable from "./start-frame/start-frame.injectable";
+import rootElementInjectable from "./window/root-element.injectable";
+import { RootFrame } from "./frames/root-frame/root-frame";
+import { ClusterFrame } from "./frames/cluster-frame/cluster-frame";
export async function bootstrap(di: DiContainer) {
const startFrame = di.inject(startFrameInjectable);
await startFrame();
- const rootElem = document.getElementById("app");
-
- assert(rootElem, "#app MUST exist");
-
- let App;
- let initializeApp;
-
- // TODO: Introduce proper architectural boundaries between root and cluster iframes
- if (process.isMainFrame) {
- initializeApp = di.inject(initRootFrameInjectable);
- App = (await import("./frames/root-frame/root-frame")).RootFrame;
- } else {
- initializeApp = di.inject(initClusterFrameInjectable);
- App = (await import("./frames/cluster-frame/cluster-frame")).ClusterFrame;
- }
-
try {
- await initializeApp(() => unmountComponentAtNode(rootElem));
+ // TODO: Introduce proper architectural boundaries between root and cluster iframes
+ if (process.isMainFrame) {
+ const initRootFrame = di.inject(initRootFrameInjectable);
+
+ await initRootFrame();
+ } else {
+ const initClusterFrame = di.inject(initClusterFrameInjectable);
+
+ await initClusterFrame();
+ }
} catch (error) {
console.error(`[BOOTSTRAP]: view initialization error: ${error}`, {
origin: location.href,
@@ -47,14 +42,16 @@ export async function bootstrap(di: DiContainer) {
});
}
- const history = di.inject(historyInjectable);
+ const App = process.isMainFrame
+ ? RootFrame
+ : ClusterFrame;
render(
-
+
{DefaultProps(App)}
,
- rootElem,
+ di.inject(rootElementInjectable),
);
}
diff --git a/packages/core/src/renderer/frames/cluster-frame/init-cluster-frame.injectable.ts b/packages/core/src/renderer/frames/cluster-frame/init-cluster-frame.injectable.ts
index f5a53b555b..8342c2528b 100644
--- a/packages/core/src/renderer/frames/cluster-frame/init-cluster-frame.injectable.ts
+++ b/packages/core/src/renderer/frames/cluster-frame/init-cluster-frame.injectable.ts
@@ -13,6 +13,7 @@ import autoInitExtensionsInjectable from "../../../features/extensions/loader/co
import prefixedLoggerInjectable from "../../../common/logger/prefixed-logger.injectable";
import { when } from "mobx";
import requestSetClusterFrameIdInjectable from "../../../features/cluster/frame-id/renderer/request-set-frame-id.injectable";
+import unmountRootComponentInjectable from "../../window/unmount-root-component.injectable";
const initClusterFrameInjectable = getInjectable({
id: "init-cluster-frame",
@@ -29,8 +30,9 @@ const initClusterFrameInjectable = getInjectable({
const logger = di.inject(prefixedLoggerInjectable, "CLUSTER-FRAME");
const showErrorNotification = di.inject(showErrorNotificationInjectable);
const requestSetClusterFrameId = di.inject(requestSetClusterFrameIdInjectable);
+ const unmountRootComponent = di.inject(unmountRootComponentInjectable);
- return async (unmountRoot: () => void) => {
+ return async () => {
logger.info(`Init dashboard, clusterId=${hostedCluster.id}, frameId=${frameRoutingId}`);
await requestSetClusterFrameId(hostedCluster.id);
@@ -69,7 +71,7 @@ const initClusterFrameInjectable = getInjectable({
window.addEventListener("beforeunload", () => {
logger.info(`Unload dashboard, clusterId=${(hostedCluster.id)}, frameId=${frameRoutingId}`);
- unmountRoot();
+ unmountRootComponent();
});
};
},
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 68daaec708..6cadcb3f7c 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
@@ -11,6 +11,7 @@ import { delay } from "../../../common/utils";
import { broadcastMessage } from "../../../common/ipc";
import sendBundledExtensionsLoadedInjectable from "../../../features/extensions/loader/renderer/send-bundled-extensions-loaded.injectable";
import autoInitExtensionsInjectable from "../../../features/extensions/loader/common/auto-init-extensions.injectable";
+import unmountRootComponentInjectable from "../../window/unmount-root-component.injectable";
const initRootFrameInjectable = getInjectable({
id: "init-root-frame",
@@ -21,8 +22,9 @@ const initRootFrameInjectable = getInjectable({
const lensProtocolRouterRenderer = di.inject(lensProtocolRouterRendererInjectable);
const logger = di.inject(loggerInjectable);
const sendBundledExtensionsLoaded = di.inject(sendBundledExtensionsLoadedInjectable);
+ const unmountRootComponent = di.inject(unmountRootComponentInjectable);
- return async (unmountRoot: () => void) => {
+ return async () => {
try {
// maximum time to let bundled extensions finish loading
const timeout = delay(10000);
@@ -54,8 +56,7 @@ const initRootFrameInjectable = getInjectable({
window.addEventListener("beforeunload", () => {
logger.info("[ROOT-FRAME]: Unload app");
-
- unmountRoot();
+ unmountRootComponent();
});
};
},
diff --git a/packages/core/src/renderer/template.html b/packages/core/src/renderer/template.html
index 87ea5dca3d..5f1f7eeacd 100755
--- a/packages/core/src/renderer/template.html
+++ b/packages/core/src/renderer/template.html
@@ -1,10 +1,12 @@
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
diff --git a/packages/core/src/renderer/window/root-element.injectable.ts b/packages/core/src/renderer/window/root-element.injectable.ts
new file mode 100644
index 0000000000..6dddcc3c36
--- /dev/null
+++ b/packages/core/src/renderer/window/root-element.injectable.ts
@@ -0,0 +1,20 @@
+/**
+ * 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";
+
+const rootElementInjectable = getInjectable({
+ id: "root-element",
+ instantiate: () => {
+ const rootElement = document.createElement("div");
+
+ rootElement.id = "app";
+
+ document.getElementsByTagName("body")[0].append(rootElement);
+
+ return rootElement;
+ },
+});
+
+export default rootElementInjectable;
diff --git a/packages/core/src/renderer/window/unmount-root-component.global-override-for-injectable.ts b/packages/core/src/renderer/window/unmount-root-component.global-override-for-injectable.ts
new file mode 100644
index 0000000000..5d769b8724
--- /dev/null
+++ b/packages/core/src/renderer/window/unmount-root-component.global-override-for-injectable.ts
@@ -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 unmountRootComponentInjectable from "./unmount-root-component.injectable";
+
+export default getGlobalOverride(unmountRootComponentInjectable, () => () => {});
diff --git a/packages/core/src/renderer/window/unmount-root-component.injectable.ts b/packages/core/src/renderer/window/unmount-root-component.injectable.ts
new file mode 100644
index 0000000000..9a59f5ba3c
--- /dev/null
+++ b/packages/core/src/renderer/window/unmount-root-component.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 assert from "assert";
+import { unmountComponentAtNode } from "react-dom";
+import rootElementInjectable from "./root-element.injectable";
+
+export type UnmountRootComponent = () => void;
+
+const unmountRootComponentInjectable = getInjectable({
+ id: "unmount-root-component",
+ instantiate: (di): UnmountRootComponent => {
+ const rootElement = di.inject(rootElementInjectable);
+
+ assert(rootElement, "#app MUST exist");
+
+ return () => unmountComponentAtNode(rootElement);
+ },
+ causesSideEffects: true,
+});
+
+export default unmountRootComponentInjectable;