From fcb214001fac799b6e60ccd7e34ad945cd632060 Mon Sep 17 00:00:00 2001 From: Sebastian Malton Date: Thu, 16 Feb 2023 09:15:24 -0500 Subject: [PATCH] Move rootElement into injectable Signed-off-by: Sebastian Malton --- .../setup-root-mac-class.injectable.ts | 5 ++- packages/core/src/renderer/bootstrap.tsx | 41 +++++++++---------- .../init-cluster-frame.injectable.ts | 6 ++- .../root-frame/init-root-frame.injectable.ts | 7 ++-- packages/core/src/renderer/template.html | 16 ++++---- .../window/root-element.injectable.ts | 20 +++++++++ ...omponent.global-override-for-injectable.ts | 9 ++++ .../unmount-root-component.injectable.ts | 24 +++++++++++ 8 files changed, 92 insertions(+), 36 deletions(-) create mode 100644 packages/core/src/renderer/window/root-element.injectable.ts create mode 100644 packages/core/src/renderer/window/unmount-root-component.global-override-for-injectable.ts create mode 100644 packages/core/src/renderer/window/unmount-root-component.injectable.ts 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;