Options not working on new browser window in electron - javascript

I'm pretty new to Electron... whenever a new window is opened, I want a new window to be created by Electron. This works fine and occurs at "app.on('new-window',...". Although the newBrowser window is created, none of the option seem to be considered. The new browser window isn't 64 tall and the other options also don't work. Anyone have any suggestions?
/* main.js v1 */
const { app, BrowserWindow } = require('electron')
const { webContents } = require('electron')
const path = require('path')
const url = require('url')
let win
function createWindow () {
win = new BrowserWindow({ width: 800, height: 600 })
win.loadURL(url.format({
pathname: 'localhost:3500/session',
protocol: 'http:',
slashes: true
}))
win.on('web-contents-created', (event, contents) => {
contents.on('will-navigate', (event, navigationUrl) => {
const allWindows = BrowserWindow.getAllWindows()
for (let i = 0; i < allWindows.length; i++) {
const win = allWindows[i]
if (win.webContents.getURL() === navigationUrl) {
win.close()
return
}
}
})
})
win.on('closed', () => {
win = null
})
}
app.on('ready', createWindow)
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') {
app.quit()
}
})
app.on('activate', () => {
if (win === null) {
createWindow()
}
})
app.on('web-contents-created', (event, contents) => {
contents.on('will-navigate', (event, navigationUrl) => {
const allWindows = BrowserWindow.getAllWindows()
for (let i = 0; i < allWindows.length; i++) {
const win = allWindows[i]
if (win.webContents.getURL() === navigationUrl) {
win.close()
return
}
}
})
})
app.on('new-window', (event, url, frameName, disposition, options, additionalFeatures) => {
if (frameName === 'modal') {
// open window as modal
event.preventDefault()
Object.assign(options, {
modal: true,
parent: win,
height: 250,
})
event.newGuest = new BrowserWindow(options)
}
})

Related

Can't get mainWindow.loadURL to load a forged url in Electron

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 ?

Electron send data to react with preload.js

I am trying achieve something where I can directly send data to react and where in react whenever it receives it does something.
So my electron.js is in below format.
// ./public/electron.js
const path = require("path");
const { app, BrowserWindow, ipcMain} = require("electron");
const isDev = false; //require("electron-is-dev"); //false
let splash = null;
let win = null;
let etmf_obj = null;
function createWindow() {
// Create the browser window.
win = new BrowserWindow({
width: 1920,
height: 1080,
webPreferences: {
nodeIntegration: true,
contextIsolation: true,
enableRemoteModule: true,
preload: path.join(__dirname, "./preloadDist.js"),
},
});
// win.loadFile("index.html");
win.loadURL(
isDev
? "http://localhost:3000"
: `file://${path.join(__dirname, "../build/index.html")}`
);
// Open the DevTools.
if (!isDev) {
win.webContents.openDevTools({ mode: "undocked" });
}
}
app.whenReady().then(createWindow);
app.on("window-all-closed", () => {
if (process.platform !== "darwin") {
app.quit();
}
});
app.on("activate", () => {
if (BrowserWindow.getAllWindows().length === 0) {
createWindow();
}
});
function restartApp() {
console.log("restarting app..");
app.exit();
app.relaunch();
}
//IPC SECTION
ipcMain.handle("notify", (event, args) => {
console.log("from react I got" + args);
console.log("hello from electron via react"); //this one works as expected
});
ipcMain.on("splashDone", function () {
console.log("splash done");
});
ipcMain.on("relaunchApp", function () {
restartApp();
});
ipcMain.on("closeAll", function () {
app.quit();
});
ipcMain.on("callAnim", function (args) {
win.webContents.send("showAnimation", args);// trying to send data directly to
//react here but don't know whether its right way or not
});
and my preload file preloadDist.js is in below format
const { ipcRenderer, contextBridge } = require("electron");
contextBridge.exposeInMainWorld("electron", {
notificationApi: {
sendNotification(message) {
ipcRenderer.invoke("notify", message);
},
},
batteryApi: {},
filesApi: {},
splashStatus: {
splashDone() {
ipcRenderer.invoke("splashDone")
}
},
});
and react to call function of or to send data I am do this
for example to send notification data :
<button
className="speak_border"
onMouseEnter={() => setHovermic(true)}
onMouseLeave={() => setHovermic(false)}
onClick={() => {
soundwave();
window.electron.notificationApi.sendNotification(
"From react Hi!");
}}
>
and to receive data I am not able to figure out but as I am doing win.webContents.send("showListenAnimation", args);
I am not able to understand how this will be received at the react end
what I tried is:
useEffect(() => {
try {
window.electron.on(
"showAnimation",
function (event, data) {
if (data) {
setAnim(true);
}
if (!data) {
setAnim(false);
}
}
);
} catch (e) {
console.log("issue with on getting data");
}
});
But this way I am getting error and not able to figure out the way to receive, but sending data from react to electron is working perfectly fine!
Please guide on this and how to achieve with about preload.js and electron.js
format.

apis delcared in contextbridge undefined in render process

I've been working on updating a electron app from 11.x to 12.x and have run into an issue where the apis declared by contextBridge.exposeInMainWorld come as undefined when called upon through window.
This is my preload.js file
const { contextBridge, ipcRenderer } = require('electron');
const { path } = require('path')
contextBridge.exposeInMainWorld('api',{
getPath: (filePath) => {
return path.parse(filePath).base;
},
removeAllListeners: (ListenerType) => {
ipcRenderer.removeAllListeners(ListenerType);
},
openNewPDF: (pdf) => {
ipcRenderer.send('openNewPDF',pdf);
},
newWindow: (file) => {
ipcRenderer.send('newWindow',file);
},
togglePrinting: (value) => {
ipcRenderer.send('togglePrinting',value)
},
resizeWindow: (value) => {
ipcRenderer.send('resizeWindow', value)
}
});
my app.js
function createWindow(filename = null) {
// Create the browser window.
let win = new BrowserWindow({
width: 550,
height: 420,
minWidth: 565,
minHeight: 200,
preload: path.resolve(path.join(__dirname, 'app/preload.js')),
resizable: true,
titleBarStyle: 'default',
show: false
});
wins.push(win);
// and load the index.html of the app.
win.loadFile('app/index.html');
win.openDevTools();
let wc = win.webContents
wc.on('will-navigate', function (e, url) {
if (url != wc.getURL()) {
e.preventDefault()
shell.openExternal(url)
}
})
win.once('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.
wins = [];
});
win.webContents.removeAllListeners('did-finish-load');
win.webContents.once('did-finish-load', () => {
if (filename) {
win.webContents.send('file-open', filename);
win.show();
} else {
win.show();
}
});
if (!menuIsConfigured) {
const menu = Menu.buildFromTemplate(menuTemplate);
menu.getMenuItemById('file-open').click = () => {
openNewPDF();
};
menu.getMenuItemById('file-print').click = () => {
const focusedWin = BrowserWindow.getFocusedWindow();
focusedWin.webContents.send('file-print');
};
Menu.setApplicationMenu(menu);
menuIsConfigured = true;
}
const openNewPDF = () => {
dialog
.showOpenDialog(null, {
properties: ['openFile'],
filters: [{ name: 'PDF Files', extensions: ['pdf'] }]
})
.then((dialogReturn) => {
const filename = dialogReturn['filePaths'][0];
if (filename) {
if (wins.length === 0) {
createWindow(filename.toString());
} else {
const focusedWin = BrowserWindow.getFocusedWindow();
if (focusedWin) {
focusedWin.webContents.send('file-open', filename.toString());
}
}
}
});
}
ipcMain.removeAllListeners('togglePrinting');
ipcMain.once('togglePrinting', (e, msg) => {
const menu = Menu.getApplicationMenu();
menu.getMenuItemById('file-print').enabled = Boolean(msg);
});
ipcMain.removeAllListeners('newWindow');
ipcMain.once('newWindow', (e, msg) => {
console.log('opening ', msg, ' in new window');
createWindow(msg);
});
ipcMain.removeAllListeners('resizeWindow');
ipcMain.once('resizeWindow', (e, msg) => {
const { width, height } = win.getBounds();
if (width < 1000 || height < 650) {
win.setResizable(true);
win.setSize(1000, 650);
win.center();
}
});
ipcMain.removeAllListeners('openNewPDF');
ipcMain.once('openNewPDF', (e, msg) => {
openNewPDF();
});
}
let fileToOpen = '';
const args = process.argv;
const argsLength = args.length;
if (argsLength > 1 && args[argsLength - 1].endsWith('.pdf')) {
fileToOpen = args[argsLength - 1];
}
app.on('open-file', (event, path) => {
event.preventDefault();
if (app.isReady()) {
if (wins.length === 0) {
createWindow(path.toString());
} else {
const focusedWin = BrowserWindow.getFocusedWindow();
focusedWin.webContents.send('file-open', path.toString());
}
}
fileToOpen = path.toString();
});
app.whenReady().then(() => {
if (fileToOpen) {
createWindow(fileToOpen);
} else {
createWindow();
}
});
app.on('window-all-closed', () => {
app.quit()
});
app.on('activate', () => {
if (BrowserWindow.getAllWindows().length === 0) {
createWindow();
}
});
I'm lost on why contextBridge doesn't work.
The object passed to the BrowserWindow constructor is not correct. The preload option should be a property of webPreferences
const win = new BrowserWindow({
webPreferences: {
preload: YOUR_PRELOAD_SCRIPT_PATH
}
});
See the docs

Electron JS - Get path of chosen directory

Im fairly new in the programming world. I'm making an app where it should be possible to choose a directory, where to save some generated files.
I'm working with the ipc, and it seems like some of the code works, but it looks like i can't get the mainIpc to send the path back to the renderer.
I hope the hive can help, thanks in advance!
Renderer:
const electron = require("electron");
const ipc = require("electron").ipcRenderer;
createBtn.addEventListener("click", (event) => {
ipc.send("path:get");
});
ipc.on("path:selected", function (path) {
console.log("Full path: ", path);
});
Main
const ipc = require("electron").ipcMain;
const os = require("os");
const { dialog } = require("electron");
ipc.on("path:get", function (event) {
if (os.platform() === "linux" || os.platform() === "win32") {
dialog.showOpenDialog(
{
properties: ["openFile"],
},
function (files) {
if (files) win.webContents.send("path:selected", files[0]);
console.log("SENT");
}
);
} else {
dialog.showOpenDialog(
{
properties: ["openFile", "openDirectory"],
},
function (files) {
if (files) win.webContents.send("path:selected", files[0]);
console.log("SENT");
}
);
}
});
Edit: Adding the setup
Setup
const { app, BrowserWindow } = require("electron");
const ipc = require("electron").ipcMain;
const os = require("os");
const { dialog } = require("electron");
try {
require("electron-reloader")(module);
} catch (_) {}
let win;
function createWindow() {
win = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
nodeIntegration: true,
},
});
win.loadFile("./src/index.html");
}
app.whenReady().then(createWindow);
app.on("window-all-closed", () => {
if (process.platform !== "darwin") {
app.quit();
}
});
app.on("activate", () => {
if (BrowserWindow.getAllWindows().length === 0) {
createWindow();
}
});
I figured it out with some kind help.
So if anyone needs the same procedure i'll try to explain what i got to.
So, in the main, i had to add a then, because the showDialog returns a promise
if (os.platform() === "linux" || os.platform() === "win32") {
dialog
.showOpenDialog({
properties: ["openFile", "openDirectory"],
})
.then((result) => {
if (result) win.webContents.send("path:selected", result.filePaths);
})
.catch((err) => {
console.log(err);
});
} else {
dialog
.showOpenDialog({
properties: ["openFile", "openDirectory"],
})
.then((result) => {
console.log(result.filePaths);
if (result) win.webContents.send("path:selected", result.filePaths);
})
.catch((err) => {
console.log(err);
});
}
});
This sends back an array with the path at [0]
in the renderer i forgot to add the event as an parameter.
ipc.on("path:selected", (event, path) => {
chosenPath = path;
console.log("Full path: ", chosenPath[0]);
});

Electron app opening all pages upon startup

I am setting up a multi-paged electron application, however whenever I start my application it opens all the pages, and anytime I click a button that is supposed to bring the user to the next page, it skips ahead and opens the other pages as well.
I believed the issue was with setting the parent/child relation of each window, however when commenting or removing those properties the issue persists.
const{app, BrowserWindow, ipcMain} = require('electron');
import{fstat} from 'fs';
import{resolve} from 'path';
const packagejson = require('../package.json')
app.commandLine.appendSwitch('touch-events', 'enabled');
if (require('electron-squirrel-startup')) {
app.quit();
}
let mainWindow;
let startWindow;
let setOriginsWindow;
const createWindow = () => {
startWindow = new BrowserWindow({
width: 800,
height: 600,
});
startWindow.loadURL(`file://${__dirname}/index.html`);
startWindow.webContents.openDevTools();
startWindow.on('closed', () => {
startWindow = null;
});
};
app.on('ready', createWindow);
ipcMain.on('set-origins', (event) => {
setOriginsWindow = new BrowserWindow({
})
setOriginsWindow.on('close', function() {setOriginsWindow = null});
setOriginsWindow.loadURL(`file://${__dirname}/set_origin_page.html`)
setOriginsWindow.once('ready-to-show', () => {
setOriginsWindow.show();
});
setOriginsWindow.openDevTools();
if(packagejson.ENV == "dev"){
setOriginsWindow.openDevTools();
}
})
// parent:startWindow,
// fullscreen: true,
// modal:true,
// show:false
ipcMain.on('start-procedure', (event) => {
mainWindow = new BrowserWindow({
})
mainWindow.on('close', function () {mainWindow = null});
mainWindow.loadURL(`file://${__dirname}/main_page.html`);
mainWindow.once('ready-to-show', () => {
mainWindow.show();
});
mainWindow.openDevTools();
if(packagejson.ENV == "dev"){
mainWindow.openDevTools();
}
})
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') {
app.quit();
}
});
app.on('activate', () => {
if (startWindow === null) {
createWindow();
}
});
'''
The 1st page to open should be a splashscreen with button that when pressed, will open page 2. Page 2 has a button that when pressed will open page 3.
Electron is not good for multipage apps, and displays a blank screen for around a quarter of a second when changing pages. Instead, you might want to create a file with all pages combined and switch between them with DOM methods
For Example
var splash_screen = document.getElementById('splash-screen');
var second_screen = document.getElementById('second-screen');
var third_screen = document.getElementById('third-screen');
document.removeChild(second_screen)
document.removeChild(third_screen)
var splash_button_click = () => {
document.removeChild(splash_screen);
document.appendChild(second_screen);
}

Categories

Resources