I'm using electron JS to build an app. I want to reload my app after reconnect. Need to show a loader window while reloading and hide after complete. Is there any way to do it?
I don't want to put loader inside my app. I like to show it in a separate browser window.
I'm expecting like this
BrowserWindow.on('reload-complete', (e) => {
hideLoadingWindow();
})
Finally, I got another method to overcome this situation. I'm not sure is it a good solution. but it looks simple to me.
var mainWindow = new BrowserWindow({
webPreferences: {
nodeIntegration: false,
preload: path.join(app.getAppPath(), 'preload.js')
},
minWidth: 1018,
width: 640,
minHeight: 1018,
height: 640,
title: 'Electron app',
show: false
});
createLoadingWindow();
mainWindow.once('ready-to-show', () => {
mainWindow.show();
});
mainWindow.webContents.on('did-start-loading', (e) => {
createLoadingWindow();
});
mainWindow.webContents.on('did-stop-loading', (e) => {
closeLoadingWindow();
});
The event below is the correct one for you:
BrowserWindow.webContents.once('did-finish-load', (e) => {
//hideLoadingWindow();
})
the 'did-finish-load' event will be triggered after the page is reloaded.
You can use show method and then use 'dom-ready' to detect your app loading ,
let loading= new BrowserWindow({show: false, frame: false})
loading.once('show', () => {
main = new BrowserWindow({show: false})
main.webContents.once('dom-ready', () => {
console.log('main loaded')
main.show()
loading.hide()
loading.close()
})
// load your app
main.loadURL(url);
})
Related
I have a list. Click one item and then pop-up window which is named open. It's focused when it first opens, but it's out of focus the second time.
enter image description here
when I click a button, the following code execute. But, winObj.focus() not working in electron. It's only focus the main window. How do I fix it?
chatList.js (build in react)
const onClickBtn = useCallback(
(chat) => {
const winObj = window.open(
`/chatting/${chat.url}`,
chat.url,
"",
true
);
winObj.focus();
},
[]
);
electron.js (same as public/main.js)
function createWindow() {
const win = new BrowserWindow({
width: 400,
height: 700,
webPreferences: {
nodeIntegration: true,
nativeWindowOpen: true,
preload: path.join(__dirname, "/../build/preload.js"),
},
});
const pubUrl = "https://---";
win.loadURL(pubUrl);
//when i click the button above, the event come into here.
win.webContents.setWindowOpenHandler((event) => {
return {
action: "allow",
overrideBrowserWindowOptions: {
...win.webContents.browserWindowOptions,
parent: win,
},
};
});
}
This is an existing bug with Electron.
win.focus() will not actually focus the BrowserWindow. You'll want to send an ipc message down to the main process, grab your BrowserWindow and call win.focus() from there.
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();
}
});
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.
}
I developed app and I want to make it if the user do nothing in 30 minutes close the app.
So I search it on google to solve this problem and I found that there is 'powerMonitor' API in electron but the problem is my app is old version (Electron 3.1.14) so it doesn't support various methods.
Electron powerMonitor API Docs
I think I should use powerMonitor.querySystemIdleTime() method and I tried to test 'pwoerMonitor' API so I paste code but
console.log(powerMonitor.querySystemIdleTime()) it returns this error message.
How can I detect system idle and do something in electron? Should I use another package?
import { app, dialog, Menu, Notification, Tray, ipcMain, powerMonitor } from 'electron'
import windowManager from 'electron-window-manager'
import schedule from 'node-schedule'
let mainWindow = null
let tray = null
if (process.env.NODE_ENV !== 'development') {
global.__static = require('path').join(__dirname, '/static').replace(/\\/g, '\\\\')
}
app.setAppUserModelId('Geomec Cloud Manager')
windowManager.init({
appBase: process.env.NODE_ENV === 'production'
? `file://${__dirname}`
: 'http://localhost:9080'
})
if (isSecondInstance) {
app.quit()
} else {
app.on('second-instance', () => {
if (mainWindow) {
mainWindow.object.show()
mainWindow.object.focus()
}
})
/* Main Window */
app.on('ready', () => {
mainWindow = windowManager.createNew('main-window', '', '/index.html', null, {
title: 'Geomec Cloud Manager',
height: 500,
width: 500,
useContentSize: true,
frame: false,
maximizable: false,
minimizable: false,
resizable: false
}).create()
console.log(powerMonitor.querySystemIdleTime()) // I thought it returns idle time
if (!process.argv.includes('--systray')) {
mainWindow.object.once('ready-to-show', () => {
mainWindow.object.show()
})
}
tray = new Tray(__static + '/tray-icon.ico')
const trayMenu = Menu.buildFromTemplate([{
label: '프로그램 정보',
click () {
const window = windowManager.createNew('about-window', '', '/index.html#about', null, {
height: 380,
width: 550,
useContentSize: true,
frame: false,
maximizable: false,
minimizable: false,
resizable: false,
modal: true,
parent: windowManager.get('main-window').object
}).create()
window.object.once('ready-to-show', () => {
window.object.show()
})
}
},
{
/* Tray 내부 프로그램 종료 함수 */
label: '프로그램 종료',
click () {
const notification = {
icon: __static + '/' + 'app-icon.png',
title: '네트워크 드라이브 연결이 해제되었습니다',
body: '프로그램을 종료합니다'
}
new Notification(notification).show()
mainWindow.object.webContents.send('terminate-child-processes')
ipcMain.on('child-processes-terminated', () => {
setTimeout(function () {
app.quit()
}, 5000)
})
}
}
])
tray.setToolTip('Geomec Cloud Manager')
tray.setContextMenu(trayMenu)
tray.on('click', () => {
mainWindow.object.show()
})
})
}
According to the docs the call is: powerMonitor.querySystemIdleTime(callback) and as the error message says, you are not giving the required argument.
Try changing:
console.log(powerMonitor.querySystemIdleTime())
to:
powerMonitor.querySystemIdleTime((idleSecs)=>{
console.log(`The system has been idle for ${idleSecs} seconds.`)
})
Based on your use case, it is actually powerMonitor.querySystemIdleState(idleThreshold, callback) you will want to be using, with idleThreshold set to 30 * 60.
I am trying to add thumbnail toolbar with specified buttons in a taskbar layout of an application from it's doc. But it's showing some problem.
The main.js:
// Modules to control application life and create native browser window
const {app, BrowserWindow, ipcMain, dialog} = require('electron')
const path = require('path')
// 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 mainWindow;
const isSecondInstance = app.makeSingleInstance((commandLine, workingDirectory) => {
if (mainWindow) {
if (mainWindow.isMinimized()) mainWindow.restore()
mainWindow.focus()
}
})
if (isSecondInstance) {
app.quit();
}
function createWindow () {
// Create the browser window.
mainWindow = new BrowserWindow({
show: false,
width: 500,
height: 200,
minWidth: 500,
minHeight: 200,
transparent: true,
frame: false,
})
mainWindow.setResizable(false)
// and load the index.html of the app.
mainWindow.loadFile('index.html')
// Open the DevTools.
// mainWindow.webContents.openDevTools()
mainWindow.once('ready-to-show', () => {
mainWindow.show()
mainWindow.focus()
})
// Emitted when the window is closed.
mainWindow.on('closed', function () {
// 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.
mainWindow = null
})
}
// 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.
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') {
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()
}
})
// 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.
ipcMain.on('open-information-dialog', (event) => {
if (mainWindow) {
const options = {
type: 'info',
title: 'I am abled',
buttons: ['Ok'],
message: 'This is the way.'
}
dialog.showMessageBox(mainWindow, options, function () {})
}
})
ipcMain.on('close', (event) => {
app.quit()
})
ipcMain.on('minimize', (event) => {
mainWindow.minimize()
})
ipcMain.on('progress', (event, per) => {
mainWindow.setProgressBar(per)
})
mainWindow.setThumbarButtons([
{
tooltip: 'button1',
icon: path.join(__dirname, 'button1.png'),
click () { console.log('button1 clicked') }
}, {
tooltip: 'button2',
icon: path.join(__dirname, 'button2.png'),
flags: ['enabled', 'dismissonclick'],
click () { console.log('button2 clicked.') }
}
])
The error:
All of my mainWindow reference working fine but when I am trying to set thumbar buttons with setThumbarButtons() it's getting the problem. I just try this one and I don't get any error but it's not showing any buttons on taskber window,
The Code:
app.on('ready', function(){
console.log(mainWindow)
mainWindow.setThumbarButtons([
{
tooltip: 'button1',
icon: path.join(__dirname, 'start.png'),
click () { console.log('button1 clicked') }
}
])
})
I can't make any sense with this problem.
The problem is that when you run mainWindow.setThumbarButtons your window hasn't been created. Therefor mainWindow is undefined. Which is the error you are running into, and what it says in the error screenshot you posted.
Currently you are creating and setting your window in the createWindow function.
If you move your setThumbarButtons code into the createWindow function it should work.
Something like the following:
function createWindow () {
// Create the browser window.
mainWindow = new BrowserWindow({
show: false,
width: 500,
height: 200,
minWidth: 500,
minHeight: 200,
transparent: true,
frame: false,
})
mainWindow.setResizable(false)
// and load the index.html of the app.
mainWindow.loadFile('index.html')
mainWindow.setThumbarButtons([
{
tooltip: 'button1',
icon: path.join(__dirname, 'start.png'),
click () { console.log('button1 clicked') }
}
])
// Open the DevTools.
// mainWindow.webContents.openDevTools()
mainWindow.once('ready-to-show', () => {
mainWindow.show()
mainWindow.focus()
})
// Emitted when the window is closed.
mainWindow.on('closed', function () {
// 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.
mainWindow = null
})
}
That way you are creating the mainWindow first and defining it before calling that function. Otherwise mainWindow will be undefined which is what you were experiencing.
In Electron I want to trigger a javascript function in a browser window when that browser window is shown.
The code I have at the moment is as follows:
main.js (Main Process)
myWin = new BrowserWindow({ width: 1200, height: 400, show: false })
.... some time later and under certain circumstances ;-) ....
myWin.show()
usbUpload.js (Browser Window)
function validateFlights() {
...blar...
}
this.addEventListener('onshow', () => {
validateFlights()
})
ValidateFlights() is the function in the browser window that I want to execute when the browser window is shown.
Any ideas?
You can directly call javascript in the renderer process from main process using executeJavaScript. Combined with 'show' event of BrowserWindow you can do the following:
myWin.on('show', () => {
myWin.webContents.executeJavaScript('validateFlights()')
})
Example:
main.js
const { app, BrowserWindow } = require('electron')
const path = require('path')
app.once('ready', () => {
let win = new BrowserWindow({show: false})
win.once('show', () => {
win.webContents.executeJavaScript('validateFlights()')
})
win.loadURL(path.resolve(__dirname, 'index.html'))
win.show()
})
index.html
<html>
<head>
<script type="text/javascript">
function validateFlights() {
console.log('validated')
}
</script>
</head>
<body></body>
</html>
In your main process you probably want to do something with win.show() and the focus event if your window is already open in the background. Something like so:
let win = new BrowserWindow({width: 800, height: 600})
win.on('onFocus', () => {
win.show()
})