2

I'm making an app using Electron framework and I tried using buttons to close and minimize the window. I've tried multiple things for it to do this but without success.

This is what I have for the moment:
HTML:

<body>
    <!-- Titlebar -->
    <button id="minimize-button">-</button>
    <button id="close-button">x</button>

    <!-- Script -->
    <script src="./js/minimize-close.js"></script>
</body>

JS (minimize-close.js):

const { ipcRenderer } = require('electron');

document.getElementById("minimize-button").addEventListener('click', () => {
    ipcRenderer.send('minimize-window');
});

document.getElementById("close-button").addEventListener('click', () => {
    ipcRenderer.send('close-window');
});

JS (index.js):

const { app, BrowserWindow, ipcMain } = require('electron');

function createWindow(){
    const window = new BrowserWindow({
        width: 960, height: 580,
        resizable: false, maximizable: false,
        frame: false, autoHideMenuBar: true,
        icon: './icon.ico',
        webPreferences: {
            nodeIntegration: true,
            devTools: false
        }
    });

    window.loadFile('./src/index.html');
}

// Minimize and close window
ipcMain.on('minimize-window', () => {
    window.minimize();
});

ipcMain.on('close-window', () => {
    window.close();
});

app.whenReady().then(() => {
    createWindow();

    app.on('activate', function(){
        if(BrowserWindow.getAllWindows().length === 0){
            createWindow();
        }
    });
});

app.on('window-all-closed', function(){
    if(process.platform !== 'darwin'){
        app.quit();
    }
});
Anox3D
  • 39
  • 1
  • 9
  • 1
    Your remote seems incorrect, I believe it should be `const { remote } = require("electron")`, because rn you're just requiring electron, not the remote module. Also, it seems like remote is deprecated, and you should instead use ipcMain and ipcRenderer (https://www.electronjs.org/docs/api/ipc-main) which will let you to send events from the client to the main process. – Ameer Jul 01 '21 at 22:13
  • I already tried using ipcRenderer, I'm gonna try again. – Anox3D Jul 01 '21 at 22:17
  • Can you add your attempt with ipcRenderer and ipcMain to your question please? – Ameer Jul 01 '21 at 22:18
  • I'll do it if does not work. – Anox3D Jul 01 '21 at 22:18
  • Okay so, I tried and still the same results. – Anox3D Jul 01 '21 at 22:27
  • I think the issue may be that you don't have nodeIntegration enabled, take a look at https://stackoverflow.com/a/62437788/10213537, for enabling nodeIntegration – Ameer Jul 01 '21 at 23:03
  • Even with nodeIntegration it doesn't work... – Anox3D Jul 01 '21 at 23:07
  • 1
    Hold on, I think you may have an issue with the scope of the `window` variable, you're defining a variable `window` to the scope of the function `createWindow` but using the variable outside of that scope. Try setting `ipcMain.on`s inside the `createWindow` function and see if that works – Ameer Jul 02 '21 at 00:31

1 Answers1

3

You need to set contextIsolation: false.
Also I have read around that window must be global. If not at some point it will be collected by the garbage collector because function which created it has already finished.

let window;

function createWindow(){
    window = new BrowserWindow({
        width: 960, height: 580,
        resizable: false, maximizable: false,
        frame: false, autoHideMenuBar: true,
        icon: './icon.ico',
        webPreferences: {
            nodeIntegration: true,
            // devTools: false,  // commented for debugging purposes
            contextIsolation: false
        }
    });

    window.loadFile('./src/index.html');
    window.webContents.openDevTools(); // Open dev tools to see if any error arised. In this case I saw 'require is not defined' before setting contextIsolation. Remove it when going into production.
}

Option B: more "secure"

If security is a concern and you want nodeIntegration and contextIsolation to retain their default secure values then preload.js scheme is needed.
This should be the case if remote content is loaded by your App.

HTML

<body>
    <!-- Titlebar -->
    <button id="minimize-button">-</button>
    <button id="close-button">x</button>
</body>

preload.js

const { ipcRenderer } = require('electron');

window.addEventListener('DOMContentLoaded', () => {
    document.getElementById("minimize-button").addEventListener('click', () => {
        ipcRenderer.send('minimize-window');
    });
    
    document.getElementById("close-button").addEventListener('click', () => {
        ipcRenderer.send('close-window');
    });
})

index.js

const path = require('path');


function createWindow(){
    window = new BrowserWindow({
        width: 960, height: 580,
        resizable: false, maximizable: false,
        frame: false, autoHideMenuBar: true,
        icon: './icon.ico',
        webPreferences: {
            // devTools: false,  // commented for debugging purposes
            preload: path.join(__dirname, 'preload.js')
        }
    });

    window.loadFile('./src/index.html');
    window.webContents.openDevTools(); // Open dev tools to see if any error arised. In this case I saw 'require is not defined' before setting contextIsolation. Remove it when going into production.
}
cachique
  • 1,150
  • 1
  • 12
  • 16