I'm currently starting a new project with electron and react and I don't understand but I'm trying to use React devTools, I've tried some methods and none of them worked.
For instance, I followed here the method of electron-devtools-installer, which can be found here : https://github.com/MarshallOfSound/electron-devtools-installer
and when I launch the app the inspector still tells me
that
Download the React DevTools for a better development experience: https://reactjs.org/link/react-devtoolsYou might need to use a local HTTP server (instead of file://): https://reactjs.org/link/react-devtools-faq
Here is my main.js :
const { app, BrowserWindow, Notification, ipcMain } = require("electron");
const path = require("path");
const isDev = !app.isPackaged;
const {
default: installExtension,
REACT_DEVELOPER_TOOLS,
} = require("electron-devtools-installer");
let createWindow = () => {
const win = new BrowserWindow({
width: 800,
height: 600,
backgroundColor: "white",
title: "TaleSmith",
icon: path.join(__dirname, "../assets/icons/appIcon.png"),
webPreferences: {
nodeIntegration: false,
worldSafeExecuteJavaScript: true,
contextIsolation: true, // is a feature that ensures that both your preload scripts and Electron internal logical tun in separate context
preload: path.join(__dirname, "preload.js"),
},
});
win.loadFile(path.join(__dirname, "..", "src", "index.html"));
isDev && win.webContents.openDevTools();
};
if (isDev) {
require("electron-reload")(__dirname, {
electron: path.join(
__dirname,
"..",
"..",
"node_modules",
".bin",
"electron",
),
});
}
app.whenReady().then(async () => {
installExtension(REACT_DEVELOPER_TOOLS)
.then((name) => console.log(`Added Extension: ${name}`))
.catch((err) => console.log("An error occurred: ", err));
createWindow();
});
ipcMain.on("notify", (_, message) => {
new Notification({
title: "Hello World",
body: message,
}).show();
});
app.on("window-all-closed", () => {
if (process.platform !== "darwin") {
app.quit();
}
});
app.on("activate", () => {
if (BrowserWindow.getAllWindows().length === 0) {
createWindow();
}
});
Thanks a lot for your help !
Leverage the "dom-ready" event to initiate the dev tools instead of when the app is ready. Give this a try
const {
app,
BrowserWindow,
Notification,
ipcMain
} = require("electron");
const path = require("path");
const isDev = !app.isPackaged;
const {
default: installExtension,
REACT_DEVELOPER_TOOLS,
} = require("electron-devtools-installer");
let createWindow = () => {
const win = new BrowserWindow({
width: 800,
height: 600,
backgroundColor: "white",
title: "TaleSmith",
icon: path.join(__dirname, "../assets/icons/appIcon.png"),
webPreferences: {
nodeIntegration: false,
worldSafeExecuteJavaScript: true,
contextIsolation: true, // is a feature that ensures that both your preload scripts and Electron internal logical tun in separate context
preload: path.join(__dirname, "preload.js"),
},
});
win.loadFile(path.join(__dirname, "..", "src", "index.html"));
if (isDev) {
require("electron-reload")(__dirname, {
electron: path.join(
__dirname,
"..",
"..",
"node_modules",
".bin",
"electron",
),
});
// Errors are thrown if the dev tools are opened
// before the DOM is ready
win.webContents.once("dom-ready", async () => {
await installExtension([REACT_DEVELOPER_TOOLS])
.then((name) => console.log(`Added Extension: ${name}`))
.catch((err) => console.log("An error occurred: ", err))
.finally(() => {
win.webContents.openDevTools();
});
});
}
};
app.on("ready", createWindow);
ipcMain.on("notify", (_, message) => {
new Notification({
title: "Hello World",
body: message,
}).show();
});
app.on("window-all-closed", () => {
if (process.platform !== "darwin") {
app.quit();
}
});
app.on("activate", () => {
if (BrowserWindow.getAllWindows().length === 0) {
createWindow();
}
});
Related
I have the following code (main.js) :
const console = require('console');
const {
app,
BrowserWindow,
BrowserView,
screen,
globalShortcut,
ipcMain
} = require('electron');
const path = require('path');
if (require('electron-squirrel-startup')) {
app.quit();
}
const createWindow = () => {
const view = new BrowserView();
mainWindow = new BrowserWindow({
width: 400,
height: 600,
frame: false,
resizable: false,
webPreferences: {
preload: path.join(__dirname, 'preload.js'),
webviewTag: true,
nodeIntegration: true,
contextIsolation: false,
},
});
mainWindow.webContents.openDevTools();
mainWindow.loadFile(path.join(__dirname, 'home.html'));
globalShortcut.register('q', () => {
app.quit()
});
globalShortcut.register('h', () => {
mainWindow.setSize(400, 600);
var xx = Math.round(screen.getPrimaryDisplay().workAreaSize.width / 2 - 200);
var yy = Math.round(screen.getPrimaryDisplay().workAreaSize.height / 2 - 300);
mainWindow.setPosition(xx, yy, true);
mainWindow.resizable = false;
mainWindow.loadFile(path.join(__dirname, 'home.html'));
});
globalShortcut.register('1', () => {
mainWindow.resizable = true;
mainWindow.setPosition(0, mainWindow.getPosition()[1]);
mainWindow.setSize(screen.getPrimaryDisplay().workAreaSize.width, 64);
mainWindow.loadURL('https://example.com?variable=static');
});
globalShortcut.register('2', () => {
var size = mainWindow.getSize();
mainWindow.resizable = true;
mainWindow.setPosition(0, mainWindow.getPosition()[1]);
mainWindow.setSize(size[0], 128);
mainWindow.loadURL('https://example.com?variable=static');
});
globalShortcut.register('3', () => {
var size = mainWindow.getSize();
mainWindow.resizable = true;
mainWindow.setPosition(0, mainWindow.getPosition()[1]);
mainWindow.setSize(size[0], 128 + 55);
mainWindow.loadURL('https://example.com?variable=static');
});
};
app.on('ready', function () {
createWindow();
ipcMain.on('form-submitted', (event, variable) => {
console.log('Form submitted with conference name:', variable);
event.sender.loadURL('https://example.com?variable=' + variable);
});
});
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') {
app.quit();
}
});
app.on('activate', () => {
if (BrowserWindow.getAllWindows().length === 0) {
createWindow();
}
});
app.on('will-quit', () => {
globalShortcut.unregisterAll()
})
When I press 1, 2 or 3 the window refreshes the correct URL.
But the moment I set the variable in the URL it stops working; it says it's unable to run jQuery (yes, remote website has javascript).
I wonder if this is a 'security' feature ?
I have tried turning webSecurity parameter to off, no luck.
What am I missing here ?
We are currently improve a project with electronjs: We have main.js for electron as you know and we have another html page that javascripts codes in it. We created a close button in this html page and this button should close the app but we cant reach main.js for close the app. Can you help me?
This code is from html page :
<div class="background-three link-container">
<button class="link-three" onclick="kapat()" id="kptbtn">Kapat</button>
</div>
<script>
function kapat(){
//what should I write here.
}
</script>
and this main.js
const { app, BrowserWindow } = require('electron')
const path = require('path')
function createWindow() {
const win = new BrowserWindow({
transparent: true,
frame: false,
resizable: false,
width: 500,
height: 700,
webPreferences: {
preload: path.join(__dirname, 'preload.js')
}
})
win.loadFile('girisEkrani.html')
}
app.whenReady().then(() => {
createWindow()
app.on('activate', () => {
if (BrowserWindow.getAllWindows().length === 0) {
createWindow()
}
})
})
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') {
app.quit()
}
})
You must use ipcMain and ipcRenderer. Main for reading message and Renderer for sending message.
.html page
<script>
function kapat() {
const { ipcRenderer } = require('electron')
const ipc = ipcRenderer;
ipc.send('kapat');
}
...
</script>
if you define ipc stuff out of the function it will not work and effect other functions.
main.js
const { app, BrowserWindow, ipcMain } = require('electron')
const path = require('path')
const ipc = ipcMain;
function createWindow() {
const win = new BrowserWindow({
transparent: true,
frame: false,
resizable: false,
width: 500,
height: 700,
webPreferences: {
nodeIntegration: true,
contextIsolation: false,
}
})
ipc.on('kapat', () => { win.close() })
win.loadFile('girisEkrani.html')
}
I'm struggling to pass a data from newly opened site window to renderer. What I want to achieve is to find a login button on site and listen on click event. I was reading about webview in electron, but I couldn't make It work. For now I'm stuck on window.open() method. Can you please point me what aspect I am missing? Here are my files:
//main.js
const {app, BrowserWindow, ipcMain} = require('electron')
const path = require('path')
function createWindow () {
const mainWindow = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
preload: path.join(__dirname, 'preload.js'),
nodeIntegration: true,
contextIsolation: false,
enableRemoteModule: true
}
})
mainWindow.loadFile('index.html')
// Open the DevTools.
mainWindow.webContents.openDevTools()
}
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()
})
ipcMain.on("open-login-window", () => {
console.info('dostal');
});
//renderer.js
const electron = require("electron");
const ipc = electron.ipcRenderer
const button = document.getElementById("login-button");
button.addEventListener("click", () => {
ipc.send("open-login-window")
const windowProxy = window.open('https://www.somesite.com/login', null, 'minimizable=false')
windowProxy.postMessage('hi', '*')
});
Node version: 14.18.0
OS: Mac
This is my package.json file
{
"name": "cryptic-app",
"version": "1.0.0",
"description": "",
"main": "main.js",
"scripts": {
"start": "electron ./main.js"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"electron": "14.1.0"
}
}
This is my main.js
const electron = require('electron')
const path = require('path')
const shell = require('electron').shell
const { app, BrowserWindow, Menu } = electron
function createWindow () {
const mainWindow = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
enableRemoteModule: true,
nodeIntegration: true,
contextIsolation: false,
}
})
// and load the index.html of the app.
const indexFilePath = path.join( __dirname, 'src/index.html')
mainWindow.loadFile(indexFilePath)
mainWindow.webContents.openDevTools()
var menu = Menu.buildFromTemplate([
{
label: 'Menu',
submenu: [
{
label: 'Adjust notification value'
},
{
label: 'CoinMarketCap',
click() {
shell.openExternal('http://www.coinmarketcap.com/')
}
},
{
type: 'separator'
},
{
label: 'Exit',
click() {
app.quit()
}
},
]
}
])
Menu.setApplicationMenu(menu)
}
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()
})
This is my index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Hello World!</title>
<link rel="stylesheet" href="../assets/css/main.css">
</head>
<body>
<div class="row">
<div id="price-container">
<p class="subtext">Current BTC USD</p>
<h1 id="price">Loading...</h1>
</div>
<div id="goal-container">
<p>
<img src="https://s3.amazonaws.com/coursetro/tutorial_images/up.svg">
<span id="target-price">Choose a target price</span>
</p>
</div>
<div class="right-container">
<button id="notifyBtn">Notify me when...</button>
</div>
</div>
<script src="./index.js"></script>
</body>
</html>
This is my index.js file
const electron = require('electron')
const path = require('path')
const { BrowserWindow } = electron
console.log(electron)
const notifyBtn = document.getElementById('notifyBtn')
notifyBtn.addEventListener('click', function(e) {
const modalPath = path.join('file://', __dirname, 'add.html')
console.log("modalPath", modalPath)
let win = new BrowserWindow({ width: 400, height: 200, parent: top })
win.on('close', function() {
win = null
})
win.loadFile(modalPath)
win.show()
})
This is the electron object from index.js
I am getting BrowserWindow is not a constructor error inside the render process, I am not sure what is causing this issue. Can someone please help?
This is how I solved this problem :-
As I am using electron > 14, so remote resources are not available inside renderer process and not made avaolable by lectron module.
To make remote resources available to renderer process I added this module. #electron/remote
Then this is how my main.js looks now
const remote = require('#electron/remote/main')
const electron = require('electron')
remote.initialize() // Intitialize
const path = require('path')
const shell = require('electron').shell
const { app, BrowserWindow, Menu } = electron
function createWindow () {
// Create the browser window.
const mainWindow = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
nodeIntegration: true,
contextIsolation: false,
show: false,
}
})
remote.enable(mainWindow.webContents) // Loads webcontents
const indexFilePath = path.join( __dirname, 'src/index.html')
mainWindow.loadFile(indexFilePath)
mainWindow.webContents.openDevTools()
var menu = Menu.buildFromTemplate([
{
label: 'Menu',
submenu: [
{
label: 'Adjust notification value'
},
{
label: 'CoinMarketCap',
click() {
shell.openExternal('http://www.coinmarketcap.com/')
}
},
{
type: 'separator'
},
{
label: 'Exit',
click() {
app.quit()
}
},
]
}
])
Menu.setApplicationMenu(menu)
}
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()
})
Now I can can access Browser window inside my index.js file like this
const { BrowserWindow } = require('#electron/remote')
Links to refer for:-
About webcontents, read here
I am working on a project with Electron and React. I am going to be making multiple calls to the database via ipcMain and ipcRenderer so I moved the calls for ipcMain to another file(ipcMainHandler.js).
The challenge I am facing now is how to send responses back to the ipcRenderer. I am unable to access the mainWindow from within that file.
This is the code for my main file.
const url = require('url');
const { app, BrowserWindow } = require('electron');
let mainWindow;
function createWindow() {
mainWindow = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
nodeIntegration: true,
enableRemoteModule: true,
preload: __dirname + '/preload.js'
},
});
const startUrl =
process.env.ELECTRON_START_URL ||
url.format({
pathname: path.join(__dirname, './build/index.html'),
protocol: 'file:',
slashes: true,
});
mainWindow.loadURL(startUrl);
mainWindow.webContents.openDevTools();
mainWindow.on('closed', function () {
mainWindow = null;
});
}
app.on('ready', createWindow);
app.on('window-all-closed', function () {
if (process.platform !== 'darwin') {
app.quit();
}
});
app.on('activate', function () {
if (mainWindow === null) {
createWindow();
}
});
require('./src/server/helpers/ipcMainHandler.js');
The ipcMainHandler.js file
const { SIGNIN_REQUEST, SIGNIN_RESPONSE } = require('../../common/events.js');
const { ipcMain } = require('electron');
ipcMain.on(SIGNIN_REQUEST, (event, data) => {
const user = AuthController.userSignin({ ...data });
});
Things I have tried
Accessing the currentWindow from remote - throws a remote undefined error
Adding the mainWindow to a global variable and trying to access it in the ipcHander. - This also returns an undefined message.
This has been resolved. I used the event object to send the response from ipcMain.
ipcMain.on(SIGNIN_REQUEST, async (event, data) => {
const user = await AuthController.userSignin({ ...data });
event.sender.send(SIGNIN_RESPONSE, user);
});