Electron: parent - child browserwindow macos behavior - electron

I have the following scenario: when I minimize the main window, the main window hides and a child window opens, and when I click on it, the main window opens again and the child window closes.
main.js
app.on("ready", () => {
// Main window
const mainWindow = windows.createMainWindow(app);
provider.generateProviderData(mainWindow)
const ses = mainWindow.webContents.session
// Display Dev Tools
//mainWindow.openDevTools();
// Quit when all windows are closed.
app.on("window-all-closed", () => {
app.quit()
});
ipcMain.on("windowControls:maximize", (ipcEvent) => {
const minimizedWindow = findBrowserWindow(ipcEvent)
const mainWindow = minimizedWindow.getParentWindow()
const minimizedWindowPosition = minimizedWindow.getPosition()
mainWindow.setPosition(minimizedWindowPosition[0], minimizedWindowPosition[1])
mainWindow.show()
minimizedWindow.close()
})
ipcMain.on("windowControls:minimize", (_ipcEvent) => {
mainWindow.hide()
windows.createMinimizedWindow(mainWindow)
})
function findBrowserWindow(ipcEvent) {
return BrowserWindow.fromWebContents(ipcEvent.sender)
}
});
window.js
exports.createMinimizedWindow = (parent) => {
const minimizedWindow = new BrowserWindow({
width: 220,
height: 50,
frame: false,
resizable: false,
transparent: true,
alwaysOnTop: true,
parent: parent,
webPreferences: {
preload: path.join(__dirname, "../preload.js"),
},
})
minimizedWindow.loadFile("minimized.html")
const parentPosition = parent.getPosition()
minimizedWindow.setPosition(parentPosition[0], parentPosition[1])
return minimizedWindow
}
The problem is that on Windows platform it works ok, but on MacOs it does not work and always keeps the parent window behind the child and does not keep hidden.

Related

How to make a splash screen on Electron?

I'm new to Electron and I joined an existing project. I'm trying to add an image before the main screen of the app that will last 5 seconds. At first, I tried it with useState and setTimeone but I've realized I'm in the wrong place of the code.
After reading all kinds of solutions, and running the app - I now need your help.
This is some of the code in my main.ts file:
mainWindow = new BrowserWindow({
show: false,
width: 521,
height: 712,
icon: getAssetPath('icon.png'),
webPreferences: {
nodeIntegration: true,
contextIsolation: true,
preload: app.isPackaged
? path.join(__dirname, 'preload.+212 662-122618 js')
: path.join(__dirname, '../../.erb/dll/preload.js'),
},
});
mainWindow.loadURL(resolveHtmlPath('index.html'));
mainWindow.on('ready-to-show', () => {
if (!mainWindow) {
throw new Error('"mainWindow" is not defined');
}
if (process.env.START_MINIMIZED) {
mainWindow.minimize();
} else {
mainWindow.show();
}
});
mainWindow.on('closed', () => {
mainWindow = null;
});
const menuBuilder = new MenuBuilder(mainWindow);
menuBuilder.buildMenu();
// Open urls in the user's browser
mainWindow.webContents.setWindowOpenHandler((edata) => {
shell.openExternal(edata.url);
return { action: 'deny' };
});
// Remove this if your app does not use auto updates
// eslint-disable-next-line
new AppUpdater();
};
/**
* Add event listeners...
*/
app.on('window-all-closed', () => {
// Respect the OSX convention of having the application in memory even
// after all windows have been closed
if (process.platform !== 'darwin') {
app.quit();
}
});
app
.whenReady()
.then(() => {
createWindow();
app.on('activate', () => {
// 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 (mainWindow === null) createWindow();
});
})
.catch(console.log);

Electron how to redirect users between various .html files

I am looking to try to redirect users from "home.html" to "dashboard.html". I've searched far and wide, yet I haven't found an answer.
When creating your window with the BrowserWindow module, you would have used the method win.loadFile(filePath[, options]) to load your html file.
Once the logic to change pages is successful, all you need to do is execute the win.loadFile(filePath[, options]) line of code again with the path to your new file.
As win.loadFile(filePath[, options]) returns a promise, let's add a .then() statement as well (though not requried).
main.js (main thread)
const electronApp = require('electron').app;
const electronBrowserWindow = require('electron').BrowserWindow;
const nodePath = require("path");
let window;
function createWindow() {
const window = new electronBrowserWindow({
x: 0,
y: 0,
width: 800,
height: 600,
show: false,
webPreferences: {
nodeIntegration: false,
contextIsolation: true,
preload: nodePath.join(__dirname, 'preload.js')
}
});
window.loadFile('home.html')
.then(() => { window.show(); });
return window;
}
electronApp.on('ready', () => {
window = createWindow();
});
// Run when logic to change to dashboard is successful.
function showDashboard() {
window.loadFile('dashboard.html')
.then(() => { window.show(); })
}

Electron Uncaught ReferenceError: require is not defined | I have nodeIntegration set to true

I am getting this error whilst using the latest version of Electron. I have nodeIntegration set to true in my main javascript file. I have copy and pasted this code from a working Electron application but it doesn't seem to work with my new app.
Electron Version: ^12.0.0
My main JS
//Require Electron
const { BrowserWindow, app, autoUpdater, globalShortcut, ipcMain } = require('electron');
const main = require('electron-reload');
//Electron reload
const electron_reload = require('electron-reload')(__dirname);
//Disable security warnings
process.env['ELECTRON_DISABLE_SECURITY_WARNINGS'] = 'true';
//Main window
function createMain() {
const main = new BrowserWindow({
minWidth: 425,
minHeight: 524,
width: 1600,
height: 900,
frame: null,
icon: './assets/icon.png',
webPreferences: {
nodeIntegration: true,
nodeIntegrationInWorker: true,
nodeIntegrationInSubFrames: true,
enableRemoteModule: true,
}
});
main.loadFile('./HTML/index.html');
main.setMenu(null);
main.webContents.toggleDevTools();
main.webContents.on('did-finish-load', function () {
main.show();
//Ctrl+Shift+I - Open Developer Tools
globalShortcut.register('CommandOrControl+Shift+I', () => {
console.log('Developer Tools Opened');
main.webContents.toggleDevTools();
});
//Make full screen
globalShortcut.register('F11', () => {
main.maximize();
})
});
//Tries to quit the application when main window is closed
main.on('closed', function () {
app.quit();
});
}
//Once the Electron application is initialised (when it is ready) the function createMain is called
app.whenReady()
.then(createMain)
.then(console.log('Launching ChecklistsPro'));
//When the application is launched, if it has no windows open then it will call the createMain function
app.on('activate', () => {
if (BrowserWindow.getAllWindows().length === 0) {
createMain();
}
});
Trying to use require
const electron = require('electron');
I have had the same issue.
It comes with the update from electron 11.x to 12.x See here: https://www.electronjs.org/releases/stable#release-notes-for-v1200
You have to disable contextisolation, which changed from beeing true by default in the new electron version.
function createWindow () {
const win = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
nodeIntegration: true,
contextIsolation: false
}
})
win.loadFile('index.html')
}
Another solution is to downgrade to electron 11.x where contextIsolation: false is the default.
My sources:
https://www.reddit.com/r/electronjs/comments/lxjva0/required_not_defined_but_nodeintegration_set_to/
Picture of electron Changelog

How to disable fullscreen on electron window (linux)

These are the only four attributes mentioned in docs.
(1) minimizable
(2) maximizable
(3) fullscreen
(4) fullscreenable
While former two specify that these aren't implemented on Linux, the latter two are for mac only.
So, how do I prevent user from making the window occupy full screen on Linux? And what's the point of having max height and max width properties then (I can't drag and resize beyond those but I can still maximize the window)?
Code:
const { app, BrowserWindow,Menu } = require('electron');
const path = require('path');
require('electron-reload')(__dirname, {
electron: path.join(__dirname,'..', 'node_modules', '.bin', 'electron')
});
// Handle creating/removing shortcuts on Windows when installing/uninstalling.
if (require('electron-squirrel-startup')) { // eslint-disable-line global-require
app.quit();
}
let mainWindow;
const createWindow = () => {
mainWindow = new BrowserWindow({
width: 550,
height: 500,
skipTaskbar: true,
maxWidth:1000,
maxHeight:800,
show:false,
fullscreenable:false,
fullscreen: false,
maximizable: false
});
mainWindow.loadURL({url});
mainWindow.once('ready-to-show', () => {
mainWindow.show()
})
mainWindow.on('closed', () => {
mainWindow = null;
});
};
app.on('ready', createWindow);
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') {
app.quit();
}
});
app.on('activate', () => {
if (mainWindow === null) {
createWindow();
}
});
Indeed, as said in the docs, maximizable has not been implemented in Linux.
I have not found a "proper" solution, but a work-around.
You should be able to listen to the maximize event, and then call the unmaximize method (I don't see any warning about this event or method about Linux so they should be available). So essentially you would "cancel" the maximizing.
mainWindow.on('maximize', () => {
mainWindow.unmaximize()
});
set resizable key to false:
mainWindow = new BrowserWindow({
resizable: false
});
This should disable the fullscreen button on the m

How to make a dialog to block the BrowserWindow when open?

I call dialog.showOpenDialog() to find the path to the folder. But the problem is that this does not block the mainWindow. It is necessary that when the standard path selection GUI appears, the program continues to work only after the path selection is completed. Googled and realized that you need to use remote. But nothing happens.
I get:
Cannot destructure property dialog of 'undefined' or 'null'.
if from electron.remote take dialog.
I tried a lot of different things (and these are not all attempts, just what I remembered):
const { dialog } = require ('electron').remote;
var remote = electron.remote;
var dialog = remote.dialog;
const dialog = require ('electron').remote.dialog;
I tried to connect a lot and yet.
My main.js:
const url = require('url');
const path = require('path');
const {dialog} = electron.remote;
const {app, BrowserWindow, Menu} = electron;
app.on('ready', function () {
const {start_width, start_height} = electron.screen.getPrimaryDisplay().workAreaSize;
mainWindow = new BrowserWindow({
minWidth: 1250,
minHeight: 800,
height: start_height,
width: start_width,
center: true,
show: false,
});
mainWindow.loadURL(url.format({
pathname: path.join(__dirname, 'templates/mainWindow.html'),
protocol: 'file:',
slashes: true
}));
mainWindow.on('closed', function () {
app.quit();
});
// mainWindow.webContents.openDevTools();
const mainMenu = Menu.buildFromTemplate(mainMenuTemplate);
Menu.setApplicationMenu(mainMenu);
mainWindow.maximize();
mainWindow.show();
});
function createAddWindow() {
addWindow = new BrowserWindow({
width: 300,
height: 200,
title: 'Add item'
});
addWindow.loadURL(url.format({
pathname: path.join(__dirname, 'templates/addWindow.html'),
protocol: 'file:',
slashes: true
}));
addWindow.on('close', function () {
addWindow = null;
})
}
const mainMenuTemplate = [
{
label: 'Analysis',
submenu: [{
label: 'Global search',
accelerator: 'Ctrl+O',
click() {
var path = createAddWindow();
console.log(path);
}
},
{
label: 'Search for a year',
accelerator: 'Ctrl+Alt+O',
click() {
console.log(folderSelect());//i need console.log (like the whole program) to continue to work after folderSelect returns some value.
}
},
{
label: 'Quit',
accelerator: process.platform == 'darwin' ? 'Command+Q' : 'Ctrl+Q',
click() {
app.quit();
}
},
]
}
];
function folderSelect() {
dialog.showOpenDialog({properties: ['openDirectory']}, function (path) {
console.log(path[0]);
if (path === undefined) {
return 'error';
}
else{
return path[0];
}
});
}
I need console.log (like the whole program) to continue to work after folderSelect returns some value.
For example, if I called the folderSelect function, you cannot interact with the program until the folder after selection window closes.
I saw a lot of similar questions on SO, but whatever I did nothing works.
In order to block the main window, you need to pass a BrowserWindow object to the dialog.showOpenDialog method as the first optional argument, the one you would like to attach the dialog to (mainWindow in your case I guess).
Quote from the docs:
dialog.showOpenDialog([browserWindow, ]options)
The browserWindow argument allows the dialog to attach itself to a
parent window, making it modal.
Now, how you make it happen is the whole different matter. It can be done in multiple ways, but if you are looking to invoke the dialog from renderer process the simplest one would be something like this:
import { remote } from 'electron'
remote.dialog.showOpenDialog(
remote.getCurrentWindow(), // <- notice this one
{ properties: ['openDirectory'] }
).then(result => {
// prefer promised API
})
The crucial part for whole thing to work properly is to have nodeIntegration enabled in your BrowserWindow options, which depending on a version of Electron you are using, you might or might not have (they've switched defaults from true to false in version 4). In any case it's better to have it set explicitly from now on. So that's how you would typically initiate your mainwindow now:
mainWindow = new BrowserWindow({
// ...
show: false,
webPreferences: {
nodeIntegration: true // <- this one
}
});

Resources