Electron - Close initial window but keep child open - javascript

I am coding an electron app which is supposed to load a splash screen, and then open a new window. Afterwards the splash screen should be closed.
However I am not able to do that. In my index.js, the startup script, I have the following code:
const { app, BrowserWindow } = require("electron");
app.on("ready", () => {
let win = new BrowserWindow({ /*...*/ });
win.loadURL(`file://${__dirname}/splash/splash.html`);
win.on("ready-to-show", () => { win.show(); });
win.on("closed", () => { app.quit(); });
});
In splash.html I load the splash.js by using
<script>require("./splash");</script>
And in splash.js I tried the following code:
const remote = require("electron").remote;
let tWin = remote.getCurrentWindow();
let next = function(){
let win = new remote.BrowserWindow({ /*...*/ });
win.loadURL(`file://${__dirname}/main/main.html`);
win.on("ready-to-show", () => { win.show(); });
win.on("closed", () => { app.quit(); });
tWin.close();
// I could just use win.hide(); here instead
// of tWin.close(); but that can't really be the right way.
};
The function next() gets called after a timeout. The problem is, if called, the main window shows up for a second but both, slpash and main close instantly.
I tried to fix that by commenting out
win.on("closed", () => { app.quit(); });
in my index.js. But that led to the following error:
Attempting to call a function in a renderer window that has been closed or released.
Uncaught Exception:
Error: Attempting to call a function in a renderer window that has been closed or released. Function provided here: splash.js:38:9.
at BrowserWindow.callIntoRenderer (/usr/lib/node_modules/electron-prebuilt/dist/resources/electron.asar/browser/rpc-server.js:199:19)
at emitOne (events.js:96:13)
at BrowserWindow.emit (events.js:188:7)
Does anyone have an idea on how to prevent the newly created window from closing?

I usually use a diferent approach. Here's how a use do it:
create global var reference for the main window and the splash window, if not it will be self closed by the garbage collector.
load 'splash' browserwindow
on 'show' event I call a function to load 'main' window
on main window 'dom-ready', I close 'splash' and show 'main'
Here's one example of my main.js electron code, feel free to ask:
'use strict';
//generic modules
const { app, BrowserWindow, Menu } = require('electron');
const path = require('path')
const url = require('url')
const config = require('./config'); // => 1: archivo de configuracion
const fileToLoad = config.files.current ? config.files.current : config.files.raw;
const jsonData = require(fileToLoad); // => 2: archivo de datos (json)
const pug = require('electron-pug')({ pretty: true }, jsonData); // => 3: pasamos datos ya tratados a plantillas pug/jade
// Keep a global reference of the window object, if you don't, the window will
// be closed automatically when the JavaScript object is garbage collected.
let win, loading
app.mainWindow = win;
function initApp() {
showLoading(initPresentation)
}
function showLoading(callback) {
loading = new BrowserWindow({ show: false, frame: false })
loading.once('show', callback);
loading.loadURL(url.format({
pathname: path.join(__dirname, '/src/pages/loading.html'),
protocol: 'file:',
slashes: true
}))
loading.show();
}
function initPresentation() {
win = new BrowserWindow({
width: 1280,
height: 920,
show: false,
webPreferences: {
experimentalFeatures: true
}
})
win.webContents.once('dom-ready', () => {
console.log("main loaded!!")
win.setMenu(null);
win.show();
loading.hide();
loading.close();
})
// Emitted when the window is closed.
win.on('closed', () => {
// Dereference the window object, usually you would store windows
// in an array if your app supports multi windows, this is the time
// when you should delete the corresponding element.
win = null
})
win.loadURL(url.format({
//pathname: path.join(__dirname, '/src/pages/home.pug'),
pathname: path.join(__dirname, '/lab/pug/index.pug'),
protocol: 'file:',
slashes: true
}))
win.webContents.openDevTools() // Open the DevTools.
}
// 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', initApp)
// 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', () => {
// 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 (win === null) {
initApp()
}
})
// In this file you can include the rest of your app's specific main process
// code. You can also put them in separate files and require them here.*/

Related

My Electron app after packaging doesn't launch

hello guys so basically after packaging my app with multiple packagers it still doesnt want to load the window when i open my .exe file :/
const PHPServer = require('php-server-manager');
const { app, Menu, shell, ipcMain } = require('electron');
const config = require('config')
const path = require('path')
const MainWindow = require('./MainWindow')
let mainWindow;
process.env.NODE_ENV = 'production'
shell.showItemInFolder('fullPath')
const isDev = process.env.NODE_ENV !== 'production' ? true : false
const server = new PHPServer({
php: "foundation/php/php.exe", // <==== ADDED
port: 8000,
directory: path.resolve(__dirname)+'/source',
stdio: 'inherit',
directives: {
display_errors: 1,
expose_php: 1
},
config: `${__dirname}foundation/php/php.ini`
});
function createWindow() {
server.run();
mainWindow = new MainWindow('http://'+server.host+':'+server.port+'/', isDev)
mainWindow.on('closed',function(){
mainWindow = null;
})
}
// Close App
ipcMain.on('close-me', (evt, arg) => {
app.quit()
})
app.on('ready', createWindow)
// Quit when all windows are closed.
app.on('window-all-closed', function () {
// On OS X it is common for applications and their menu bar
// to stay active until the user quits explicitly with Cmd + Q
if (process.platform !== 'darwin') {
// PHP SERVER QUIT
server.close();
app.quit();
}
})
app.on('activate', function () {
// On OS X 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()
}
})
//app.disableHardwareAcceleration()
app.commandLine.appendSwitch('force_high_performance_gpu')
app.allowRendererProcessReuse = true
this is my main.js and im using PHP in this electron project
also note that i use electron-forge for packaging
when i run npm start , the window show up perfectly but whenever i package my tool and then try to open the exe file it seems like nothing show up only a small icon of the app in the explorer bar , pretty weird since there is no error in my code ,
anyone has an answer ?

Uncaught TypeError: Cannot destructure property 'dialog' of 'require(...).remote' as it is undefined even thought enable remote modules set to true

I am trying to open a dialog box in my electron app but when I Try importing it in my app.js the error in the title shows up even thought 'enableRemoteModule' is set to true .
I am trying to open a dialog box in my electron app but when I Try importing it in my app.js the error in the title shows up even thought 'enableRemoteModule' is set to true .
app.js
const { dialog } = require("electron").remote;
const OpenBookBtn = document.getElementById("OpenBookBtn")
const viewerElement = document.getElementById('viewer')
const CloseBookBtn = document.getElementById("CloseBookBtn")
WebViewer({
path:'../public/lib',
},viewerElement).then(instance =>{
instance.setTheme("dark");
})
viewerElement.style.display = 'none'
OpenBookBtn.addEventListener('click',()=>{
const file = dialog.showOpenDialog();
viewerElement.style.display = "block"
})
CloseBookBtn.addEventListener('click',(event)=>{
viewerElement.style.display = 'none'
})
index.js
const { app, BrowserWindow } = require('electron');
const path = require('path');
// Handle creating/removing shortcuts on Windows when installing/uninstalling.
if (require('electron-squirrel-startup')) { // eslint-disable-line global-require
app.quit();
}
const createWindow = () => {
// Create the browser window.
const mainWindow = new BrowserWindow({
webPreferences: {
nodeIntegration: true,
enableRemoteModule: true,
contextIsolation: false,
},
width: 800,
height: 600,
});
// and load the index.html of the app.
mainWindow.loadFile(path.join(__dirname, 'index.html'));
// Open the DevTools.
mainWindow.webContents.openDevTools();
};
// 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', createWindow);
// Quit when all windows are closed, except on macOS. There, it's common
// for applications and their menu bar to stay active until the user quits
// explicitly with Cmd + Q.
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') {
app.quit();
}
});
app.on('activate', () => {
// On OS X 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) {
createWindow();
}
});
// In this file you can include the rest of your app's specific main process
// code. You can also put them in separate files and import them here.
First install the remote module using
> npm install #electron/remote
In the new versions of electron, you have to include remote as
const remote = require('#electron/remote');
const { dialog } = remote;
And in your index.js file add the following
const remoteMain = require('#electron/remote/main');
remoteMain.initialize();
Also, after creating the mainWindow object
remoteMain.enable(mainWindow.webContents)

Outsource functionality from main.js

I've started building an electron application from scratch. So far I can modify the mainWindow by inserting all the logic in main.js, but I'd like to keep the logic in separate files. Unfortunatly I fail to import them correctly, so help would be nice..
// main.js
const { app, BrowserWindow, Menu, dialog } = require('electron');
const fs = require('fs');
const { test } = require('./test'); // test module to be imported
let win;
function createWindow() {
win = new BrowserWindow({
icon: `file://${__dirname}/dist/text-editor/favicon.ico`,
webPreferences: {
nodeIntegration: true
}
});
win.maximize();
win.loadURL(`file://${__dirname}/dist/text-editor/index.html`);
win.webContents.openDevTools();
//menu bar
const template = getTemplate();
const menu = Menu.buildFromTemplate(template);
Menu.setApplicationMenu(menu);
win.on('closed', function () {
win = null;
});
console.log(test.getName()); // throws error
}
// create window on electron init
app.on('ready', createWindow);
// quit when all windows are closed
app.on('window-all-closed', function () {
if (process.platform !== 'darwin') {
app.quit();
}
});
app.on('activate', function () {
if (win === null) {
createWindow();
}
});
function getTemplate() {...} // for example move this method to new file
// test.js
const getName = () => {
return "Tom";
};
module.exports.getName = getName;
Running this code with ng build --prod && electron . throws:
Cannot read property 'getName' of undefined.
Thanks in advance ;)
Please import your js as const test = require('./test') and then use test.getName() in your main js file. when calling const {test} is trying to import the test object in the at relevant file . You can read more about that from this answer

Electron: always returns ontouchstart = true

I'm currently working on a web application with Electron. If I open the app in the normal Chrome browser it works as expected: click as click, touch as touch.
But if I package it with electron it does not work right - it always returns touchstart = true, even though I'm not in the dev tools in the responsive view or on a device that is touchable - so clicks won't work.
This is the beginning of my javascript file:
var selectEvents = (function () {
if ('ontouchstart' in document === true) {
return "touchstart";
} else {
return "click";
}
})();
and this is my main.js for electron
const {app, BrowserWindow} = require('electron');
const path = require('path');
const url = require('url');
// init win
let win;
function createWindow(){
// create browser window
win = new BrowserWindow({width:3840, height: 1080, icon:__dirname+'/images/icons/bosch_logo.jpg', kiosk: true});
// load index.html
win.loadURL(url.format({
pathname: path.join(__dirname, 'index.html'),
protocol: 'file:',
slashes: true
}));
// open devtools
win.webContents.openDevTools();
win.on('closed', () => {
win = null;
});
}
// Run create window function
app.on('ready', createWindow);
// quit when all windows are closed
app.on('window-all-closed', () => {
// check for mac osx
if(process.platform !== 'darwin') {
app.quit();
}
})
In my HTML I created a button with the id 'next-button-1'
After an interaction it checks in the script if it's a click or a touchevent normally.
$('#next-button-1').on(selectEvents, function () {
...
}
Searched now quite a while on google but didn't find a working solution. Maybe you could help me
Added "click touchstart" to the first return. Now it works also on Electron. Hope this is reliable.
var selectEvents = (function () {
if ('ontouchstart' in document === true) {
return "click touchstart";
} else {
return "click";
}
})();

Bringing an electron app to foreground with a global shortcut (like Spotlight/Launchy)

I'm looking to replicate behavior similar to that of Launchy/Quicksilver/Spotlight.
I want to have an electron app that's always running. When I hit a shortcut key, the electron app is brought to the foreground and to focus.
I understand that the globalShortcut module can be used to bind a shortcut, however I can't figure out how to make that shortcut trigger bringing the app to the foreground.
Any help would be much appreciated...
Let's start with the simplest case and then build our solution to better handle some edge cases.
The simplest possible case is to show a window that is already open whenever the global shortcut we registered is pressed.
const path = require('path');
const { app, BrowserWindow, globalShortcut } = require('electron');
let mainWindow = null;
app.on('ready', () => {
mainWindow = new BrowserWindow();
mainWindow.loadURL(path.join(__dirname, 'index.html'));
const shortcut = globalShortcut.register('Control+Space', () => {
mainWindow.show();
});
if (!shortcut) { console.log('Registration failed.'); }
});
This code has some problems though. The good news is that it still works if the window has been minimized. The bad news is that it will not work if the window has been closed. This is because closing the last window quits the application. Bummer. (Frankly, I was a little surprised by this—but that's what happens. So, let's go with it.)
Let's stop that from happening.
app.on('window-all-closed', (event) => {
event.preventDefault();
});
Okay, our app doesn't quit, it but it crashes.
Uncaught Exception:
Error: Object has been destroyed
Alright, fine. This is because the window is destroyed when it's close. So, let's not close it. Let's hide it, shall we? Within app.on('ready', () => {…}), add the following:
mainWindow.on('close', (event) => {
event.preventDefault();
mainWindow.hide();
});
The end result looks like this:
const path = require('path');
const { app, BrowserWindow, globalShortcut } = require('electron');
let mainWindow = null;
app.on('ready', () => {
mainWindow = new BrowserWindow();
mainWindow.loadURL(path.join(__dirname, 'index.html'));
const shortcut = globalShortcut.register('Control+Space', () => {
mainWindow.show();
});
if (!shortcut) { console.log('Registration failed.'); }
mainWindow.on('close', (event) => {
event.preventDefault();
mainWindow.hide();
});
});
app.on('window-all-closed', (event) => {
event.preventDefault();
});
And with that you should have the basic functionality in place. You press your global shortcut and the window appears. Dismiss it and press the keys and watch it reappear.

Categories

Resources