1
0
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:
Juho Heikka 2021-12-23 11:00:18 +02:00 committed by GitHub
parent 43277d2af6
commit 9284741df5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 55 additions and 7 deletions

View 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";

View File

@ -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";

View File

@ -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 {

View File

@ -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);
} }

View File

@ -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"));