mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
Show splash window until bundled extensions have been loaded (#4570)
* Show splash window until bundled extensions have been loaded Signed-off-by: Juho Heikka <juho.heikka@gmail.com> * Remove unnecessary variable. Signed-off-by: Juho Heikka <juho.heikka@gmail.com> * Refactor autoInitExtensions Signed-off-by: Juho Heikka <juho.heikka@gmail.com> * Add timeout to waiting for bundled extensions to load Signed-off-by: Juho Heikka <juho.heikka@gmail.com>
This commit is contained in:
parent
43277d2af6
commit
9284741df5
21
src/common/ipc/extension-loader.ipc.ts
Normal file
21
src/common/ipc/extension-loader.ipc.ts
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2021 OpenLens Authors
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
* this software and associated documentation files (the "Software"), to deal in
|
||||||
|
* the Software without restriction, including without limitation the rights to
|
||||||
|
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
|
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
* subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
export const BundledExtensionsLoaded = "extension-loader:bundled-extensions-loaded";
|
||||||
@ -27,3 +27,4 @@ export * from "./update-available.ipc";
|
|||||||
export * from "./cluster.ipc";
|
export * from "./cluster.ipc";
|
||||||
export * from "./type-enforced-ipc";
|
export * from "./type-enforced-ipc";
|
||||||
export * from "./hotbar";
|
export * from "./hotbar";
|
||||||
|
export * from "./extension-loader.ipc";
|
||||||
|
|||||||
@ -255,7 +255,8 @@ export class ExtensionLoader {
|
|||||||
|
|
||||||
loadOnClusterManagerRenderer() {
|
loadOnClusterManagerRenderer() {
|
||||||
logger.debug(`${logModule}: load on main renderer (cluster manager)`);
|
logger.debug(`${logModule}: load on main renderer (cluster manager)`);
|
||||||
this.autoInitExtensions(async (extension: LensRendererExtension) => {
|
|
||||||
|
return this.autoInitExtensions(async (extension: LensRendererExtension) => {
|
||||||
const removeItems = [
|
const removeItems = [
|
||||||
registries.GlobalPageRegistry.getInstance().add(extension.globalPages, extension),
|
registries.GlobalPageRegistry.getInstance().add(extension.globalPages, extension),
|
||||||
registries.AppPreferenceRegistry.getInstance().add(extension.appPreferences),
|
registries.AppPreferenceRegistry.getInstance().add(extension.appPreferences),
|
||||||
@ -311,7 +312,9 @@ export class ExtensionLoader {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected autoInitExtensions(register: (ext: LensExtension) => Promise<Disposer[]>) {
|
protected autoInitExtensions(register: (ext: LensExtension) => Promise<Disposer[]>) {
|
||||||
return reaction(() => this.toJSON(), installedExtensions => {
|
const loadingExtensions: { isBundled: boolean, loaded: Promise<void> }[] = [];
|
||||||
|
|
||||||
|
reaction(() => this.toJSON(), installedExtensions => {
|
||||||
for (const [extId, extension] of installedExtensions) {
|
for (const [extId, extension] of installedExtensions) {
|
||||||
const alreadyInit = this.instances.has(extId) || this.nonInstancesByName.has(extension.manifest.name);
|
const alreadyInit = this.instances.has(extId) || this.nonInstancesByName.has(extension.manifest.name);
|
||||||
|
|
||||||
@ -326,7 +329,14 @@ export class ExtensionLoader {
|
|||||||
|
|
||||||
const instance = new LensExtensionClass(extension);
|
const instance = new LensExtensionClass(extension);
|
||||||
|
|
||||||
instance.enable(register);
|
const loaded = instance.enable(register).catch((err) => {
|
||||||
|
logger.error(`${logModule}: failed to enable`, { ext: extension, err });
|
||||||
|
});
|
||||||
|
|
||||||
|
loadingExtensions.push({
|
||||||
|
isBundled: extension.isBundled,
|
||||||
|
loaded,
|
||||||
|
});
|
||||||
this.instances.set(extId, instance);
|
this.instances.set(extId, instance);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
logger.error(`${logModule}: activation extension error`, { ext: extension, err });
|
logger.error(`${logModule}: activation extension error`, { ext: extension, err });
|
||||||
@ -338,6 +348,8 @@ export class ExtensionLoader {
|
|||||||
}, {
|
}, {
|
||||||
fireImmediately: true,
|
fireImmediately: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
return loadingExtensions;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected requireExtension(extension: InstalledExtension): LensExtensionConstructor | null {
|
protected requireExtension(extension: InstalledExtension): LensExtensionConstructor | null {
|
||||||
|
|||||||
@ -24,7 +24,7 @@ import { makeObservable, observable } from "mobx";
|
|||||||
import { app, BrowserWindow, dialog, ipcMain, shell, webContents } from "electron";
|
import { app, BrowserWindow, dialog, ipcMain, shell, webContents } from "electron";
|
||||||
import windowStateKeeper from "electron-window-state";
|
import windowStateKeeper from "electron-window-state";
|
||||||
import { appEventBus } from "../common/event-bus";
|
import { appEventBus } from "../common/event-bus";
|
||||||
import { ipcMainOn } from "../common/ipc";
|
import { BundledExtensionsLoaded, ipcMainOn } from "../common/ipc";
|
||||||
import { delay, iter, Singleton } from "../common/utils";
|
import { delay, iter, Singleton } from "../common/utils";
|
||||||
import { ClusterFrameInfo, clusterFrameMap } from "../common/cluster-frames";
|
import { ClusterFrameInfo, clusterFrameMap } from "../common/cluster-frames";
|
||||||
import { IpcRendererNavigationEvents } from "../renderer/navigation/events";
|
import { IpcRendererNavigationEvents } from "../renderer/navigation/events";
|
||||||
@ -181,7 +181,7 @@ export class WindowManager extends Singleton {
|
|||||||
|
|
||||||
if (!this.mainWindow) {
|
if (!this.mainWindow) {
|
||||||
viewHasLoaded = new Promise<void>(resolve => {
|
viewHasLoaded = new Promise<void>(resolve => {
|
||||||
ipcMain.once(IpcRendererNavigationEvents.LOADED, () => resolve());
|
ipcMain.once(BundledExtensionsLoaded, () => resolve());
|
||||||
});
|
});
|
||||||
await this.initMainWindow(showSplash);
|
await this.initMainWindow(showSplash);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -29,7 +29,7 @@ import { ErrorBoundary } from "./components/error-boundary";
|
|||||||
import { Notifications } from "./components/notifications";
|
import { Notifications } from "./components/notifications";
|
||||||
import { ConfirmDialog } from "./components/confirm-dialog";
|
import { ConfirmDialog } from "./components/confirm-dialog";
|
||||||
import type { ExtensionLoader } from "../extensions/extension-loader";
|
import type { ExtensionLoader } from "../extensions/extension-loader";
|
||||||
import { broadcastMessage } from "../common/ipc";
|
import { broadcastMessage, BundledExtensionsLoaded } from "../common/ipc";
|
||||||
import { CommandContainer } from "./components/command-palette/command-container";
|
import { CommandContainer } from "./components/command-palette/command-container";
|
||||||
import { registerIpcListeners } from "./ipc";
|
import { registerIpcListeners } from "./ipc";
|
||||||
import { ipcRenderer } from "electron";
|
import { ipcRenderer } from "electron";
|
||||||
@ -39,6 +39,7 @@ import logger from "../common/logger";
|
|||||||
import { unmountComponentAtNode } from "react-dom";
|
import { unmountComponentAtNode } from "react-dom";
|
||||||
import { ClusterFrameHandler } from "./components/cluster-manager/lens-views";
|
import { ClusterFrameHandler } from "./components/cluster-manager/lens-views";
|
||||||
import type { LensProtocolRouterRenderer } from "./protocol-handler";
|
import type { LensProtocolRouterRenderer } from "./protocol-handler";
|
||||||
|
import { delay } from "./utils";
|
||||||
|
|
||||||
injectSystemCAs();
|
injectSystemCAs();
|
||||||
|
|
||||||
@ -54,8 +55,21 @@ export class RootFrame extends React.Component {
|
|||||||
lensProtocolRouterRendererInjectable: LensProtocolRouterRenderer,
|
lensProtocolRouterRendererInjectable: LensProtocolRouterRenderer,
|
||||||
) {
|
) {
|
||||||
catalogEntityRegistry.init();
|
catalogEntityRegistry.init();
|
||||||
extensionLoader.loadOnClusterManagerRenderer();
|
|
||||||
|
try {
|
||||||
|
// maximum time to let bundled extensions finish loading
|
||||||
|
const timeout = delay(10000);
|
||||||
|
|
||||||
|
const loadingExtensions = extensionLoader.loadOnClusterManagerRenderer();
|
||||||
|
const loadingBundledExtensions = loadingExtensions.filter(e => e.isBundled).map(e => e.loaded);
|
||||||
|
const bundledExtensionsFinished = Promise.all(loadingBundledExtensions);
|
||||||
|
|
||||||
|
await Promise.race([bundledExtensionsFinished, timeout]);
|
||||||
|
} finally {
|
||||||
|
ipcRenderer.send(BundledExtensionsLoaded);
|
||||||
|
}
|
||||||
lensProtocolRouterRendererInjectable.init();
|
lensProtocolRouterRendererInjectable.init();
|
||||||
|
|
||||||
bindProtocolAddRouteHandlers();
|
bindProtocolAddRouteHandlers();
|
||||||
|
|
||||||
window.addEventListener("offline", () => broadcastMessage("network:offline"));
|
window.addEventListener("offline", () => broadcastMessage("network:offline"));
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user