From f3b38d36c6ebcbef6acef57279644b7c06031fed Mon Sep 17 00:00:00 2001 From: Sebastian Malton Date: Mon, 7 Jun 2021 08:39:38 -0400 Subject: [PATCH] Wait for LensApp to report that the view has loaded before showing main window (#2597) Signed-off-by: Sebastian Malton --- src/main/index.ts | 4 +-- src/main/window-manager.ts | 55 ++++++++++++++++++++++++++++---------- src/renderer/lens-app.tsx | 9 ++++--- 3 files changed, 49 insertions(+), 19 deletions(-) diff --git a/src/main/index.ts b/src/main/index.ts index ea8ab894e3..3abbfecd17 100644 --- a/src/main/index.ts +++ b/src/main/index.ts @@ -188,7 +188,7 @@ app.on("ready", async () => { installDeveloperTools(); if (!startHidden) { - windowManager.initMainWindow(); + windowManager.ensureMainWindow(); } ipcMain.on(IpcRendererNavigationEvents.LOADED, () => { @@ -236,7 +236,7 @@ app.on("activate", (event, hasVisibleWindows) => { logger.info("APP:ACTIVATE", { hasVisibleWindows }); if (!hasVisibleWindows) { - WindowManager.getInstance(false)?.initMainWindow(false); + WindowManager.getInstance(false)?.ensureMainWindow(false); } }); diff --git a/src/main/window-manager.ts b/src/main/window-manager.ts index 4e5588e47a..25b9e4ca88 100644 --- a/src/main/window-manager.ts +++ b/src/main/window-manager.ts @@ -21,19 +21,23 @@ import type { ClusterId } from "../common/cluster-store"; import { makeObservable, observable } from "mobx"; -import { app, BrowserWindow, dialog, shell, webContents } from "electron"; +import { app, BrowserWindow, dialog, ipcMain, shell, webContents } from "electron"; import windowStateKeeper from "electron-window-state"; import { appEventBus } from "../common/event-bus"; import { subscribeToBroadcast } from "../common/ipc"; import { initMenu } from "./menu"; import { initTray } from "./tray"; -import { Singleton } from "../common/utils"; +import { delay, Singleton } from "../common/utils"; import { ClusterFrameInfo, clusterFrameMap } from "../common/cluster-frames"; import { IpcRendererNavigationEvents } from "../renderer/navigation/events"; import logger from "./logger"; import { productName } from "../common/vars"; import { LensProxy } from "./proxy/lens-proxy"; +function isHideable(window: BrowserWindow | null): boolean { + return Boolean(window && !window.isDestroyed()); +} + export class WindowManager extends Singleton { protected mainWindow: BrowserWindow; protected splashWindow: BrowserWindow; @@ -54,7 +58,7 @@ export class WindowManager extends Singleton { return `http://localhost:${LensProxy.getInstance().port}`; } - async initMainWindow(showSplash = true) { + private async initMainWindow(showSplash: boolean) { // Manage main window size and position with state persistence if (!this.windowState) { this.windowState = windowStateKeeper({ @@ -120,13 +124,8 @@ export class WindowManager extends Singleton { if (showSplash) await this.showSplash(); logger.info(`[WINDOW-MANAGER]: Loading Main window from url: ${this.mainUrl} ...`); await this.mainWindow.loadURL(this.mainUrl); - this.mainWindow.show(); - this.splashWindow?.close(); - setTimeout(() => { - appEventBus.emit({ name: "app", action: "start" }); - }, 1000); } catch (error) { - logger.error("Showing main window failed", { error }); + logger.error("Loading main window failed", { error }); dialog.showErrorBox("ERROR!", error.toString()); } } @@ -146,9 +145,32 @@ export class WindowManager extends Singleton { }); } - async ensureMainWindow(): Promise { - if (!this.mainWindow) await this.initMainWindow(); - this.mainWindow.show(); + async ensureMainWindow(showSplash = true): Promise { + // This needs to be ready to hear the IPC message before the window is loaded + let viewHasLoaded = Promise.resolve(); + + if (!this.mainWindow) { + viewHasLoaded = new Promise(resolve => { + ipcMain.once(IpcRendererNavigationEvents.LOADED, () => resolve()); + }); + await this.initMainWindow(showSplash); + } + + try { + await viewHasLoaded; + await delay(50); // wait just a bit longer to let the first round of rendering happen + logger.info("[WINDOW-MANAGER]: Main window has reported that it has loaded"); + + this.mainWindow.show(); + this.splashWindow?.close(); + this.splashWindow = undefined; + setTimeout(() => { + appEventBus.emit({ name: "app", action: "start" }); + }, 1000); + } catch (error) { + logger.error(`Showing main window failed: ${error.stack || error}`); + dialog.showErrorBox("ERROR!", error.toString()); + } return this.mainWindow; } @@ -206,8 +228,13 @@ export class WindowManager extends Singleton { } hide() { - if (this.mainWindow && !this.mainWindow.isDestroyed()) this.mainWindow.hide(); - if (this.splashWindow && !this.splashWindow.isDestroyed()) this.splashWindow.hide(); + if (isHideable(this.mainWindow)) { + this.mainWindow.hide(); + } + + if (isHideable(this.splashWindow)) { + this.splashWindow.hide(); + } } destroy() { diff --git a/src/renderer/lens-app.tsx b/src/renderer/lens-app.tsx index c58845fe23..35151dcee2 100644 --- a/src/renderer/lens-app.tsx +++ b/src/renderer/lens-app.tsx @@ -49,6 +49,9 @@ export class LensApp extends React.Component { window.addEventListener("online", () => broadcastMessage("network:online")); registerIpcHandlers(); + } + + componentDidMount() { ipcRenderer.send(IpcRendererNavigationEvents.LOADED); } @@ -57,11 +60,11 @@ export class LensApp extends React.Component { - + - - + + );