My window in Electron doesn't appear no matter what I do, there is something wrong with my code?

1.6k Views Asked by At

Firstly I'm using Vuejs and Electron, the package.json will be in the end of this post.

I'm trying to use this listener to show my window as the Electron's documentation recommend.

win.once("ready-to-show", () => win.show());

But it seems that this never fired, only if I manually get the variable win and call the function show().

Below is my background.js (The file that runs the Electron's main process) file and my windowManager.js file (The file that I've created for build my windows and return them, I import this file into background.js)

//background.js
"use strict";

import { app, protocol, BrowserWindow, ipcMain } from "electron";
import installExtension, { VUEJS_DEVTOOLS } from "electron-devtools-installer";
import { windowManager } from "./backend/windowManager.js";
const isDevelopment = process.env.NODE_ENV !== "production";

let winHome, winMain;

// Scheme must be registered before the app is ready
protocol.registerSchemesAsPrivileged([
  { scheme: "app", privileges: { secure: true, standard: true } },
]);

// Quit when all windows are closed.
app.on("window-all-closed", () => {
  // On macOS it is common for applications and their menu bar
  // to stay active until the user quits explicitly with Cmd + Q
  if (process.platform !== "darwin") {
    app.quit();
  }
});

app.on("activate", async () => {
  // On macOS it's common to re-create a window in the app when the
  // dock icon is clicked and there are no other windows open.
  if (BrowserWindow.getAllWindows().length === 0) {
    winHome = await windowManager.createHomeWindow();
    winHome.show();
  }
});

// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
app.on("ready", async () => {
  if (isDevelopment && !process.env.IS_TEST) {
    // Install Vue Devtools
    try {
      await installExtension(VUEJS_DEVTOOLS);
    } catch (e) {
      console.error("Vue Devtools failed to install:", e.toString());
    }
  }
  winHome = await windowManager.createHomeWindow();
  winHome.show();
});

// Exit cleanly on request from parent process in development mode.
if (isDevelopment) {
  if (process.platform === "win32") {
    process.on("message", (data) => {
      if (data === "graceful-exit") {
        app.quit();
      }
    });
  } else {
    process.on("SIGTERM", () => {
      app.quit();
    });
  }
}

// IPC callback listeners
const closeWindow = () => {
  BrowserWindow.getFocusedWindow().close();
};

const openMainWindow = async () => {
  winMain = await windowManager.createMainWindow();
  winHome.close();
};

// Setting the IPC listeners
ipcMain.on("close-window", closeWindow);
ipcMain.on("open-main-window", openMainWindow);

//windowManager.js
import { BrowserWindow } from "electron";
import { createProtocol } from "vue-cli-plugin-electron-builder/lib";
import * as path from "path";

export const windowManager = {
  async createWindow(sizeProperties, settings, router = null) {
    let win;
    // Create the browser window.
    win = new BrowserWindow({
      ...sizeProperties,
      ...settings,
      webPreferences: {
        // Use pluginOptions.nodeIntegration, leave this alone
        // See nklayman.github.io/vue-cli-plugin-electron-builder/guide/security.html#node-integration for more info
        nodeIntegration: process.env.ELECTRON_NODE_INTEGRATION,
        contextIsolation: !process.env.ELECTRON_NODE_INTEGRATION,
        preload: path.join(__dirname, "preload.js"),
      },
    });

    //Checking with was sent some router
    router = router ? `/#/${router}` : "";

    try {
      if (process.env.WEBPACK_DEV_SERVER_URL) {
        // Load the url of the dev server if in development mode
        await win.loadURL(`${process.env.WEBPACK_DEV_SERVER_URL}${router}`);
        if (!process.env.IS_TEST) win.webContents.openDevTools();
      } else {
        createProtocol("app");
        // Load the index.html when not in development
        await win.loadURL(`app://./index.html${router}`);
      }
    } catch (error) {
      console.error(error);
    }

    //Setting the default behavior for window
    win.once("ready-to-show", () => {
      win.show();
    });
    win.on("closed", () => {
      win.destroy();
    });

    //TODO Check if this line is necessary
    win.show();

    return win;
  },
  async createHomeWindow() {
    return await this.createWindow(
      {
        width: 706,
        height: 550,
      },
      {
        frame: false, //Remove frame to hide default menu
        resizable: false,
        show: false, //Don't show at the begin
      }
    );
  },
  async createMainWindow() {
    let win = await this.createWindow(
      {
        width: 800,
        height: 550,
      },
      {
        frame: false, //Remove frame to hide default menu
        show: false, //Don't show at the begin
      },
      "main"
    );
    //Extra window behavior
    win.maximize();
    return win;
  },
};

And the package.json

{
  "name": "simulans",
  "version": "0.1.0",
  "private": true,
  "scripts": {
    "serve": "vue-cli-service serve",
    "build": "vue-cli-service build",
    "lint": "vue-cli-service lint",
    "electron:build": "vue-cli-service electron:build",
    "electron:serve": "vue-cli-service electron:serve",
    "postinstall": "electron-builder install-app-deps",
    "postuninstall": "electron-builder install-app-deps"
  },
  "main": "background.js",
  "dependencies": {
    "core-js": "^3.6.5",
    "vue": "^2.6.11",
    "vue-router": "^3.0.3",
    "vuex": "^3.4.0"
  },
  "devDependencies": {
    "@vue/cli-plugin-babel": "~4.5.0",
    "@vue/cli-plugin-eslint": "~4.5.0",
    "@vue/cli-plugin-vuex": "~4.5.0",
    "@vue/cli-service": "^3.0.5",
    "@vue/eslint-config-prettier": "^6.0.0",
    "babel-eslint": "^10.1.0",
    "electron": "^13.0.1",
    "electron-devtools-installer": "^3.1.0",
    "eslint": "^6.7.2",
    "eslint-plugin-prettier": "^3.3.1",
    "eslint-plugin-vue": "^6.2.2",
    "prettier": "^2.2.1",
    "vue-cli-plugin-electron-builder": "~2.0.0",
    "vue-template-compiler": "^2.6.11"
  },
  "eslintConfig": {
    "root": true,
    "env": {
      "node": true
    },
    "extends": [
      "plugin:vue/essential",
      "eslint:recommended",
      "@vue/prettier"
    ],
    "parserOptions": {
      "parser": "babel-eslint"
    },
    "rules": {
      "prettier/prettier": 0
    }
  },
  "browserslist": [
    "> 1%",
    "last 2 versions",
    "not dead"
  ]
}
1

There are 1 best solutions below

0
On

You are using an asynchronous function for creating your browser window. This is not a problem, but here, you are binding your BrowserWindow events after you make your asynchonous call.

This basically means that you are waiting for your try/catch block to end before binding your ready-to-show event. I suspect that the event is fired before the asynchronous call ends.

If this is the case, the solution is just to place your win.once("ready-to-show", () => win.show()); before your try { ... } catch ... block.