mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
Make loading contents of a window unit testable
Co-authored-by: Janne Savolainen <janne.savolainen@live.fi> Signed-off-by: Iku-turso <mikko.aspiala@gmail.com> Signed-off-by: Janne Savolainen <janne.savolainen@live.fi>
This commit is contained in:
parent
7b043afe42
commit
700eb324a2
@ -7,7 +7,7 @@ import type { ApplicationBuilder } from "../../renderer/components/test-utils/ge
|
|||||||
import { getApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder";
|
import { getApplicationBuilder } from "../../renderer/components/test-utils/get-application-builder";
|
||||||
import { lensWindowInjectionToken } from "../../main/start-main-application/lens-window/application-window/lens-window-injection-token";
|
import { lensWindowInjectionToken } from "../../main/start-main-application/lens-window/application-window/lens-window-injection-token";
|
||||||
import applicationWindowInjectable from "../../main/start-main-application/lens-window/application-window/application-window.injectable";
|
import applicationWindowInjectable from "../../main/start-main-application/lens-window/application-window/application-window.injectable";
|
||||||
import createElectronWindowForInjectable from "../../main/start-main-application/lens-window/application-window/create-electron-window-for.injectable";
|
import createElectronWindowForInjectable from "../../main/start-main-application/lens-window/application-window/create-electron-window.injectable";
|
||||||
import type { AsyncFnMock } from "@async-fn/jest";
|
import type { AsyncFnMock } from "@async-fn/jest";
|
||||||
import asyncFn from "@async-fn/jest";
|
import asyncFn from "@async-fn/jest";
|
||||||
|
|
||||||
@ -16,37 +16,57 @@ import type {
|
|||||||
LensWindowConfiguration,
|
LensWindowConfiguration,
|
||||||
} from "../../main/start-main-application/lens-window/application-window/create-lens-window.injectable";
|
} from "../../main/start-main-application/lens-window/application-window/create-lens-window.injectable";
|
||||||
|
|
||||||
import { flushPromises } from "../../common/test-utils/flush-promises";
|
|
||||||
import type { DiContainer } from "@ogre-tools/injectable";
|
import type { DiContainer } from "@ogre-tools/injectable";
|
||||||
|
import { flushPromises } from "../../common/test-utils/flush-promises";
|
||||||
|
import lensProxyPortInjectable from "../../main/lens-proxy/lens-proxy-port.injectable";
|
||||||
|
import lensResourcesDirInjectable from "../../common/vars/lens-resources-dir.injectable";
|
||||||
|
|
||||||
describe("opening application window using tray", () => {
|
describe("opening application window using tray", () => {
|
||||||
describe("given application has started", () => {
|
describe("given application has started", () => {
|
||||||
let applicationBuilder: ApplicationBuilder;
|
let applicationBuilder: ApplicationBuilder;
|
||||||
|
let createElectronWindowMock: jest.Mock;
|
||||||
let createElectronWindowMock: AsyncFnMock<
|
|
||||||
(configuration: LensWindowConfiguration) => ElectronWindow
|
|
||||||
>;
|
|
||||||
|
|
||||||
let expectWindowsToBeOpen: (windowIds: string[]) => void;
|
let expectWindowsToBeOpen: (windowIds: string[]) => void;
|
||||||
let resolveOpeningOfWindow: (windowId: string) => Promise<void>;
|
let callForSplashWindowHtmlMock: AsyncFnMock<() => void>;
|
||||||
|
let callForApplicationWindowHtmlMock: AsyncFnMock<() => void>;
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
applicationBuilder = getApplicationBuilder().beforeApplicationStart(
|
applicationBuilder = getApplicationBuilder().beforeApplicationStart(
|
||||||
({ mainDi }) => {
|
({ mainDi }) => {
|
||||||
createElectronWindowMock = asyncFn();
|
mainDi.override(lensResourcesDirInjectable, () => "some-lens-resources-directory");
|
||||||
|
|
||||||
|
createElectronWindowMock = jest.fn((configuration: LensWindowConfiguration) =>
|
||||||
|
({
|
||||||
|
splash: {
|
||||||
|
send: () => {},
|
||||||
|
close: () => {},
|
||||||
|
show: () => {},
|
||||||
|
loadFile: callForSplashWindowHtmlMock,
|
||||||
|
loadUrl: () => { throw new Error("Should never come here"); },
|
||||||
|
},
|
||||||
|
|
||||||
|
"only-application-window": {
|
||||||
|
send: () => {},
|
||||||
|
close: () => {},
|
||||||
|
show: () => {},
|
||||||
|
loadFile: () => { throw new Error("Should never come here"); },
|
||||||
|
loadUrl: callForApplicationWindowHtmlMock,
|
||||||
|
},
|
||||||
|
}[configuration.id] as ElectronWindow));
|
||||||
|
|
||||||
mainDi.override(
|
mainDi.override(
|
||||||
createElectronWindowForInjectable,
|
createElectronWindowForInjectable,
|
||||||
|
|
||||||
() => (configuration) => () =>
|
() => createElectronWindowMock,
|
||||||
createElectronWindowMock(configuration),
|
|
||||||
);
|
);
|
||||||
|
|
||||||
expectWindowsToBeOpen = expectWindowsToBeOpenFor(mainDi);
|
expectWindowsToBeOpen = expectWindowsToBeOpenFor(mainDi);
|
||||||
|
|
||||||
resolveOpeningOfWindow = resolveOpeningOfWindowFor(
|
callForSplashWindowHtmlMock = asyncFn();
|
||||||
createElectronWindowMock,
|
callForApplicationWindowHtmlMock = asyncFn();
|
||||||
);
|
|
||||||
|
const lensProxyPort = mainDi.inject(lensProxyPortInjectable);
|
||||||
|
|
||||||
|
lensProxyPort.set(42);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -54,8 +74,8 @@ describe("opening application window using tray", () => {
|
|||||||
|
|
||||||
await flushPromises();
|
await flushPromises();
|
||||||
|
|
||||||
await resolveOpeningOfWindow("splash");
|
await callForSplashWindowHtmlMock.resolve();
|
||||||
await resolveOpeningOfWindow("only-application-window");
|
await callForApplicationWindowHtmlMock.resolve();
|
||||||
|
|
||||||
await renderPromise;
|
await renderPromise;
|
||||||
});
|
});
|
||||||
@ -64,6 +84,16 @@ describe("opening application window using tray", () => {
|
|||||||
expectWindowsToBeOpen(["only-application-window"]);
|
expectWindowsToBeOpen(["only-application-window"]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe("when an attempt to reopen the already started application is made using tray", () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
applicationBuilder.tray.click("open-app");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("still shows only the application window", () => {
|
||||||
|
expectWindowsToBeOpen(["only-application-window"]);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe("when the application window is closed", () => {
|
describe("when the application window is closed", () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
const applicationWindow = applicationBuilder.dis.mainDi.inject(
|
const applicationWindow = applicationBuilder.dis.mainDi.inject(
|
||||||
@ -79,6 +109,9 @@ describe("opening application window using tray", () => {
|
|||||||
|
|
||||||
describe("when an application window is reopened using tray", () => {
|
describe("when an application window is reopened using tray", () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
|
callForSplashWindowHtmlMock.mockClear();
|
||||||
|
callForApplicationWindowHtmlMock.mockClear();
|
||||||
|
|
||||||
applicationBuilder.tray.click("open-app");
|
applicationBuilder.tray.click("open-app");
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -86,6 +119,55 @@ describe("opening application window using tray", () => {
|
|||||||
expectWindowsToBeOpen([]);
|
expectWindowsToBeOpen([]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("starts loading static HTML of splash window", () => {
|
||||||
|
expect(callForSplashWindowHtmlMock).toHaveBeenCalledWith("/some-absolute-root-directory/some-lens-resources-directory/static/splash.html");
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("when loading of splash window HTML resolves", () => {
|
||||||
|
beforeEach(async () => {
|
||||||
|
await callForSplashWindowHtmlMock.resolve();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("shows just the splash window", () => {
|
||||||
|
expectWindowsToBeOpen(["splash"]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("starts loading of content for the application window", () => {
|
||||||
|
expect(callForApplicationWindowHtmlMock).toHaveBeenCalledWith("http://localhost:42");
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("when static HTML of application window resolves", () => {
|
||||||
|
beforeEach(async () => {
|
||||||
|
await callForApplicationWindowHtmlMock.resolve();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("shows just the application window", () => {
|
||||||
|
expectWindowsToBeOpen(["only-application-window"]);
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("when reopening the application using tray", () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
callForSplashWindowHtmlMock.mockClear();
|
||||||
|
callForApplicationWindowHtmlMock.mockClear();
|
||||||
|
|
||||||
|
applicationBuilder.tray.click("open-app");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("still shows just the application window", () => {
|
||||||
|
expectWindowsToBeOpen(["only-application-window"]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("does not load HTML for splash window again", () => {
|
||||||
|
expect(callForSplashWindowHtmlMock).not.toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("does not load HTML for application window again", () => {
|
||||||
|
expect(callForApplicationWindowHtmlMock).not.toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe("given opening of splash window has not finished yet, but another attempt to open the application is made", () => {
|
describe("given opening of splash window has not finished yet, but another attempt to open the application is made", () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
createElectronWindowMock.mockClear();
|
createElectronWindowMock.mockClear();
|
||||||
@ -100,15 +182,15 @@ describe("opening application window using tray", () => {
|
|||||||
|
|
||||||
describe("when opening of splash window resolves", () => {
|
describe("when opening of splash window resolves", () => {
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
await resolveOpeningOfWindow("splash");
|
await callForSplashWindowHtmlMock.resolve();
|
||||||
});
|
});
|
||||||
|
|
||||||
it("still only splash window is open", () => {
|
it("still only splash window is open", () => {
|
||||||
expectWindowsToBeOpen(["splash"]);
|
expectWindowsToBeOpen(["splash"]);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("when opening finishes, only an application window is open", async () => {
|
it("when opening of application window finishes, only an application window is open", async () => {
|
||||||
await resolveOpeningOfWindow("only-application-window");
|
await callForApplicationWindowHtmlMock.resolve();
|
||||||
|
|
||||||
expectWindowsToBeOpen(["only-application-window"]);
|
expectWindowsToBeOpen(["only-application-window"]);
|
||||||
});
|
});
|
||||||
@ -125,7 +207,7 @@ describe("opening application window using tray", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("when opening finishes, only an application window is open", async () => {
|
it("when opening finishes, only an application window is open", async () => {
|
||||||
await resolveOpeningOfWindow("only-application-window");
|
await callForApplicationWindowHtmlMock.resolve();
|
||||||
|
|
||||||
expectWindowsToBeOpen(["only-application-window"]);
|
expectWindowsToBeOpen(["only-application-window"]);
|
||||||
});
|
});
|
||||||
@ -143,21 +225,3 @@ const expectWindowsToBeOpenFor = (di: DiContainer) => (windowIds: string[]) => {
|
|||||||
windows.filter((window) => window.visible).map((window) => window.id),
|
windows.filter((window) => window.visible).map((window) => window.id),
|
||||||
).toEqual(windowIds);
|
).toEqual(windowIds);
|
||||||
};
|
};
|
||||||
|
|
||||||
const resolveOpeningOfWindowFor =
|
|
||||||
(
|
|
||||||
createElectronWindowMock: AsyncFnMock<
|
|
||||||
(configuration: LensWindowConfiguration) => ElectronWindow
|
|
||||||
>,
|
|
||||||
) =>
|
|
||||||
async (windowId: string) => {
|
|
||||||
await createElectronWindowMock.resolveSpecific(
|
|
||||||
[{ id: windowId }],
|
|
||||||
|
|
||||||
{
|
|
||||||
send: () => {},
|
|
||||||
close: () => {},
|
|
||||||
show: () => {},
|
|
||||||
},
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|||||||
@ -64,7 +64,7 @@ import { observable } from "mobx";
|
|||||||
import waitForElectronToBeReadyInjectable from "./electron-app/features/wait-for-electron-to-be-ready.injectable";
|
import waitForElectronToBeReadyInjectable from "./electron-app/features/wait-for-electron-to-be-ready.injectable";
|
||||||
import setupListenerForCurrentClusterFrameInjectable from "./start-main-application/lens-window/current-cluster-frame/setup-listener-for-current-cluster-frame.injectable";
|
import setupListenerForCurrentClusterFrameInjectable from "./start-main-application/lens-window/current-cluster-frame/setup-listener-for-current-cluster-frame.injectable";
|
||||||
import ipcMainInjectable from "./utils/channel/ipc-main/ipc-main.injectable";
|
import ipcMainInjectable from "./utils/channel/ipc-main/ipc-main.injectable";
|
||||||
import createElectronWindowForInjectable from "./start-main-application/lens-window/application-window/create-electron-window-for.injectable";
|
import createElectronWindowForInjectable from "./start-main-application/lens-window/application-window/create-electron-window.injectable";
|
||||||
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";
|
||||||
@ -97,6 +97,7 @@ import installHelmChartInjectable from "./helm/helm-service/install-helm-chart.i
|
|||||||
import listHelmReleasesInjectable from "./helm/helm-service/list-helm-releases.injectable";
|
import listHelmReleasesInjectable from "./helm/helm-service/list-helm-releases.injectable";
|
||||||
import rollbackHelmReleaseInjectable from "./helm/helm-service/rollback-helm-release.injectable";
|
import rollbackHelmReleaseInjectable from "./helm/helm-service/rollback-helm-release.injectable";
|
||||||
import updateHelmReleaseInjectable from "./helm/helm-service/update-helm-release.injectable";
|
import updateHelmReleaseInjectable from "./helm/helm-service/update-helm-release.injectable";
|
||||||
|
import waitUntilBundledExtensionsAreLoadedInjectable from "./start-main-application/lens-window/application-window/wait-until-bundled-extensions-are-loaded.injectable";
|
||||||
|
|
||||||
export function getDiForUnitTesting(opts: { doGeneralOverrides?: boolean } = {}) {
|
export function getDiForUnitTesting(opts: { doGeneralOverrides?: boolean } = {}) {
|
||||||
const {
|
const {
|
||||||
@ -120,6 +121,7 @@ export function getDiForUnitTesting(opts: { doGeneralOverrides?: boolean } = {})
|
|||||||
di.preventSideEffects();
|
di.preventSideEffects();
|
||||||
|
|
||||||
if (doGeneralOverrides) {
|
if (doGeneralOverrides) {
|
||||||
|
di.override(waitUntilBundledExtensionsAreLoadedInjectable, () => async () => {});
|
||||||
di.override(getRandomIdInjectable, () => () => "some-irrelevant-random-id");
|
di.override(getRandomIdInjectable, () => () => "some-irrelevant-random-id");
|
||||||
di.override(hotbarStoreInjectable, () => ({ load: () => {} }));
|
di.override(hotbarStoreInjectable, () => ({ load: () => {} }));
|
||||||
di.override(userStoreInjectable, () => ({ startMainReactions: () => {}, extensionRegistryUrl: { customUrl: "some-custom-url" }}) as UserStore);
|
di.override(userStoreInjectable, () => ({ startMainReactions: () => {}, extensionRegistryUrl: { customUrl: "some-custom-url" }}) as UserStore);
|
||||||
@ -256,7 +258,7 @@ const overrideElectronFeatures = (di: DiContainer) => {
|
|||||||
throw new Error("Tried to check for platform updates without explicit override.");
|
throw new Error("Tried to check for platform updates without explicit override.");
|
||||||
});
|
});
|
||||||
|
|
||||||
di.override(createElectronWindowForInjectable, () => () => async () => ({
|
di.override(createElectronWindowForInjectable, () => () => ({
|
||||||
show: () => {},
|
show: () => {},
|
||||||
|
|
||||||
close: () => {},
|
close: () => {},
|
||||||
@ -266,6 +268,9 @@ const overrideElectronFeatures = (di: DiContainer) => {
|
|||||||
|
|
||||||
sendFake(null, arg);
|
sendFake(null, arg);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
loadFile: async () => {},
|
||||||
|
loadUrl: async () => {},
|
||||||
}));
|
}));
|
||||||
|
|
||||||
di.override(
|
di.override(
|
||||||
|
|||||||
@ -9,9 +9,7 @@ import lensProxyPortInjectable from "../../../lens-proxy/lens-proxy-port.injecta
|
|||||||
import isMacInjectable from "../../../../common/vars/is-mac.injectable";
|
import isMacInjectable from "../../../../common/vars/is-mac.injectable";
|
||||||
import appNameInjectable from "../../../app-paths/app-name/app-name.injectable";
|
import appNameInjectable from "../../../app-paths/app-name/app-name.injectable";
|
||||||
import appEventBusInjectable from "../../../../common/app-event-bus/app-event-bus.injectable";
|
import appEventBusInjectable from "../../../../common/app-event-bus/app-event-bus.injectable";
|
||||||
import { delay } from "../../../../common/utils";
|
import waitUntilBundledExtensionsAreLoadedInjectable from "./wait-until-bundled-extensions-are-loaded.injectable";
|
||||||
import { bundledExtensionsLoaded } from "../../../../common/ipc/extension-handling";
|
|
||||||
import ipcMainInjectable from "../../../utils/channel/ipc-main/ipc-main.injectable";
|
|
||||||
|
|
||||||
const applicationWindowInjectable = getInjectable({
|
const applicationWindowInjectable = getInjectable({
|
||||||
id: "application-window",
|
id: "application-window",
|
||||||
@ -21,7 +19,7 @@ const applicationWindowInjectable = getInjectable({
|
|||||||
const isMac = di.inject(isMacInjectable);
|
const isMac = di.inject(isMacInjectable);
|
||||||
const applicationName = di.inject(appNameInjectable);
|
const applicationName = di.inject(appNameInjectable);
|
||||||
const appEventBus = di.inject(appEventBusInjectable);
|
const appEventBus = di.inject(appEventBusInjectable);
|
||||||
const ipcMain = di.inject(ipcMainInjectable);
|
const waitUntilBundledExtensionsAreLoaded = di.inject(waitUntilBundledExtensionsAreLoadedInjectable);
|
||||||
const lensProxyPort = di.inject(lensProxyPortInjectable);
|
const lensProxyPort = di.inject(lensProxyPortInjectable);
|
||||||
|
|
||||||
return createLensWindow({
|
return createLensWindow({
|
||||||
@ -45,14 +43,7 @@ const applicationWindowInjectable = getInjectable({
|
|||||||
onDomReady: () => {
|
onDomReady: () => {
|
||||||
appEventBus.emit({ name: "app", action: "dom-ready" });
|
appEventBus.emit({ name: "app", action: "dom-ready" });
|
||||||
},
|
},
|
||||||
beforeOpen: async () => {
|
beforeOpen: waitUntilBundledExtensionsAreLoaded,
|
||||||
const viewHasLoaded = new Promise<void>((resolve) => {
|
|
||||||
ipcMain.once(bundledExtensionsLoaded, () => resolve());
|
|
||||||
});
|
|
||||||
|
|
||||||
await viewHasLoaded;
|
|
||||||
await delay(50); // wait just a bit longer to let the first round of rendering happen
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|||||||
@ -38,21 +38,16 @@ export interface ElectronWindowConfiguration {
|
|||||||
onDomReady?: () => void;
|
onDomReady?: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type CreateElectronWindow = () => Promise<ElectronWindow>;
|
export type CreateElectronWindow = (config: ElectronWindowConfiguration) => ElectronWindow;
|
||||||
export type CreateElectronWindowFor = (config: ElectronWindowConfiguration) => CreateElectronWindow;
|
|
||||||
|
|
||||||
function isFileSource(src: ContentSource): src is FileSource {
|
const createElectronWindowInjectable = getInjectable({
|
||||||
return typeof (src as FileSource).file === "string";
|
id: "create-electron-window",
|
||||||
}
|
|
||||||
|
|
||||||
const createElectronWindowFor = getInjectable({
|
instantiate: (di): CreateElectronWindow => {
|
||||||
id: "create-electron-window-for",
|
|
||||||
|
|
||||||
instantiate: (di): CreateElectronWindowFor => {
|
|
||||||
const logger = di.inject(loggerInjectable);
|
const logger = di.inject(loggerInjectable);
|
||||||
const sendToChannelInLensWindow = di.inject(sendToChannelInElectronBrowserWindowInjectable);
|
const sendToChannelInLensWindow = di.inject(sendToChannelInElectronBrowserWindowInjectable);
|
||||||
|
|
||||||
return (configuration) => async () => {
|
return (configuration) => {
|
||||||
const applicationWindowState = di.inject(
|
const applicationWindowState = di.inject(
|
||||||
applicationWindowStateInjectable,
|
applicationWindowStateInjectable,
|
||||||
{
|
{
|
||||||
@ -172,19 +167,23 @@ const createElectronWindowFor = getInjectable({
|
|||||||
return { action: "deny" };
|
return { action: "deny" };
|
||||||
});
|
});
|
||||||
|
|
||||||
const contentSource = configuration.getContentSource();
|
|
||||||
|
|
||||||
if (isFileSource(contentSource)) {
|
|
||||||
logger.info(`[CREATE-ELECTRON-WINDOW]: Loading content for window "${configuration.id}" from file: ${contentSource.file}...`);
|
|
||||||
await browserWindow.loadFile(contentSource.file);
|
|
||||||
} else {
|
|
||||||
logger.info(`[CREATE-ELECTRON-WINDOW]: Loading content for window "${configuration.id}" from url: ${contentSource.url}...`);
|
|
||||||
await browserWindow.loadURL(contentSource.url);
|
|
||||||
}
|
|
||||||
|
|
||||||
await configuration.beforeOpen?.();
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
loadFile: async (filePath) => {
|
||||||
|
logger.info(
|
||||||
|
`[CREATE-ELECTRON-WINDOW]: Loading content for window "${configuration.id}" from file: ${filePath}...`,
|
||||||
|
);
|
||||||
|
|
||||||
|
await browserWindow.loadFile(filePath);
|
||||||
|
},
|
||||||
|
|
||||||
|
loadUrl: async (url) => {
|
||||||
|
logger.info(
|
||||||
|
`[CREATE-ELECTRON-WINDOW]: Loading content for window "${configuration.id}" from url: ${url}...`,
|
||||||
|
);
|
||||||
|
|
||||||
|
await browserWindow.loadURL(url);
|
||||||
|
},
|
||||||
|
|
||||||
show: () => browserWindow.show(),
|
show: () => browserWindow.show(),
|
||||||
close: () => browserWindow.close(),
|
close: () => browserWindow.close(),
|
||||||
send: (args) => sendToChannelInLensWindow(browserWindow, args),
|
send: (args) => sendToChannelInLensWindow(browserWindow, args),
|
||||||
@ -195,4 +194,4 @@ const createElectronWindowFor = getInjectable({
|
|||||||
causesSideEffects: true,
|
causesSideEffects: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
export default createElectronWindowFor;
|
export default createElectronWindowInjectable;
|
||||||
@ -4,13 +4,15 @@
|
|||||||
*/
|
*/
|
||||||
import { getInjectable } from "@ogre-tools/injectable";
|
import { getInjectable } from "@ogre-tools/injectable";
|
||||||
import type { LensWindow, SendToViewArgs } from "./lens-window-injection-token";
|
import type { LensWindow, SendToViewArgs } from "./lens-window-injection-token";
|
||||||
import type { ContentSource, ElectronWindowTitleBarStyle } from "./create-electron-window-for.injectable";
|
import type { ContentSource, ElectronWindowTitleBarStyle } from "./create-electron-window.injectable";
|
||||||
import createElectronWindowForInjectable from "./create-electron-window-for.injectable";
|
import createElectronWindowForInjectable from "./create-electron-window.injectable";
|
||||||
|
|
||||||
export interface ElectronWindow {
|
export interface ElectronWindow {
|
||||||
show: () => void;
|
show: () => void;
|
||||||
close: () => void;
|
close: () => void;
|
||||||
send: (args: SendToViewArgs) => void;
|
send: (args: SendToViewArgs) => void;
|
||||||
|
loadFile: (filePath: string) => Promise<void>;
|
||||||
|
loadUrl: (url: string) => Promise<void>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface LensWindowConfiguration {
|
export interface LensWindowConfiguration {
|
||||||
@ -33,23 +35,19 @@ const createLensWindowInjectable = getInjectable({
|
|||||||
id: "create-lens-window",
|
id: "create-lens-window",
|
||||||
|
|
||||||
instantiate: (di) => {
|
instantiate: (di) => {
|
||||||
const createElectronWindowFor = di.inject(createElectronWindowForInjectable);
|
const createElectronWindow = di.inject(createElectronWindowForInjectable);
|
||||||
|
|
||||||
return (configuration: LensWindowConfiguration): LensWindow => {
|
return (configuration: LensWindowConfiguration): LensWindow => {
|
||||||
let browserWindow: ElectronWindow | undefined;
|
let browserWindow: ElectronWindow | undefined;
|
||||||
|
|
||||||
const createElectronWindow = createElectronWindowFor({
|
|
||||||
...configuration,
|
|
||||||
onClose: () => browserWindow = undefined,
|
|
||||||
});
|
|
||||||
|
|
||||||
let windowIsOpening = false;
|
let windowIsOpening = false;
|
||||||
|
let contentIsLoading = false;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
id: configuration.id,
|
id: configuration.id,
|
||||||
|
|
||||||
get visible() {
|
get visible() {
|
||||||
return !!browserWindow;
|
return !!browserWindow && !contentIsLoading;
|
||||||
},
|
},
|
||||||
|
|
||||||
get opening() {
|
get opening() {
|
||||||
@ -59,7 +57,26 @@ const createLensWindowInjectable = getInjectable({
|
|||||||
show: async () => {
|
show: async () => {
|
||||||
if (!browserWindow) {
|
if (!browserWindow) {
|
||||||
windowIsOpening = true;
|
windowIsOpening = true;
|
||||||
browserWindow = await createElectronWindow();
|
|
||||||
|
browserWindow = createElectronWindow({
|
||||||
|
...configuration,
|
||||||
|
onClose: () => browserWindow = undefined,
|
||||||
|
});
|
||||||
|
|
||||||
|
const windowFilePath = configuration.getContentSource().file;
|
||||||
|
const windowUrl = configuration.getContentSource().url;
|
||||||
|
|
||||||
|
contentIsLoading = true;
|
||||||
|
|
||||||
|
if (windowFilePath) {
|
||||||
|
await browserWindow.loadFile(windowFilePath);
|
||||||
|
} else if (windowUrl) {
|
||||||
|
await browserWindow.loadUrl(windowUrl);
|
||||||
|
}
|
||||||
|
|
||||||
|
await configuration.beforeOpen?.();
|
||||||
|
|
||||||
|
contentIsLoading = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
browserWindow.show();
|
browserWindow.show();
|
||||||
|
|||||||
@ -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 { bundledExtensionsLoaded } from "../../../../common/ipc/extension-handling";
|
||||||
|
import { delay } from "../../../../common/utils";
|
||||||
|
import ipcMainInjectable from "../../../utils/channel/ipc-main/ipc-main.injectable";
|
||||||
|
|
||||||
|
const waitUntilBundledExtensionsAreLoadedInjectable = getInjectable({
|
||||||
|
id: "wait-until-bundled-extensions-are-loaded",
|
||||||
|
|
||||||
|
instantiate: (di) => {
|
||||||
|
const ipcMain = di.inject(ipcMainInjectable);
|
||||||
|
|
||||||
|
return async () => {
|
||||||
|
const viewHasLoaded = new Promise<void>((resolve) => {
|
||||||
|
ipcMain.once(bundledExtensionsLoaded, () => resolve());
|
||||||
|
});
|
||||||
|
|
||||||
|
await viewHasLoaded;
|
||||||
|
await delay(50); // wait just a bit longer to let the first round of rendering happen
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
causesSideEffects: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
export default waitUntilBundledExtensionsAreLoadedInjectable;
|
||||||
@ -181,13 +181,13 @@ export const getApplicationBuilder = () => {
|
|||||||
computed(() => []),
|
computed(() => []),
|
||||||
);
|
);
|
||||||
|
|
||||||
const iconPaths = mainDi.inject(trayIconPathsInjectable);
|
|
||||||
|
|
||||||
let trayMenuItemsStateFake: TrayMenuItem[];
|
let trayMenuItemsStateFake: TrayMenuItem[];
|
||||||
let trayMenuIconPath: string;
|
let trayMenuIconPath: string;
|
||||||
|
|
||||||
mainDi.override(electronTrayInjectable, () => ({
|
mainDi.override(electronTrayInjectable, () => ({
|
||||||
start: () => {
|
start: () => {
|
||||||
|
const iconPaths = mainDi.inject(trayIconPathsInjectable);
|
||||||
|
|
||||||
trayMenuIconPath = iconPaths.normal;
|
trayMenuIconPath = iconPaths.normal;
|
||||||
},
|
},
|
||||||
stop: () => {},
|
stop: () => {},
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user