Electron: loadURL from buffer - electron

In my renderer I can emit an event to create a PDF. However, before writing to disk I'd like to first open the newly cerated PDF in another window. How can I circumvent the writing to the file system and use data as my source for loadURL?
My code so far:
ipcMain.on('view-pdf', (event, url) => {
let pdf
mainWindow.webContents.printToPDF({}, (error, data) => {
if (error) throw error
pdf = data
// what's the magic here to make pdf work?
})
const pdfWindow = new BrowserWindow({
width: 1024,
height: 800,
webPreferences: {
plugins: true,
webSecurity: false
}
})
pdfWindow.loadURL(pdf)
})

The async nature of Javascript is a beast. This works as expected:
ipcMain.on('view-pdf', (event, url) => {
mainWindow.webContents.printToPDF({}, (error, data) => {
if (error) throw error
const pdf = data.toString('base64')
const pdfWindow = new BrowserWindow({
width: 1024,
height: 800,
webPreferences: {
plugins: true,
webSecurity: false
}
})
pdfWindow.loadURL('data:application/pdf;base64,' + pdf)
})
})
The code is not perfect but this is how it works.

Related

require cannot be used in Electron's preloadjs

main.js
//...
const win = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
preload: path.join(__dirname, './preload/preload.js')
}
});
//...
preload.js
const { contextBridge, ipcRenderer } = require('electron');
const qrcode = require('qrcode');
contextBridge.exposeInMainWorld('electronAPI', {
qrc: qrcode
})
the error
Unable to load preload script: F:\project\bluetools\preload\preload.js
Error: module not found: qrcode
Although direct exposure is not a good behavior, but I need to do it; and the example in the official documentation can be exposed directly, although it is not recommended; but why I require any third-party package in preloadjs shows "module not found: xxx"
Just add nodeIntegration: true to webPreferences. Like that.
//...
const win = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
nodeIntegration: true,
preload: path.join(__dirname, './preload/preload.js')
}
});
//...
I refer to here, I have got a solution, but it seems to be more troublesome, but what is this compared to security and normative?
ipc.js
module.exports = {
xxx_req: (argements) => {
const { ipcMain, winb: win } = argements;
ipcMain.on('xxx_req', (event, response) => {
win.webContents.send("xxx", "hello");
});
}
}
main.js
const ipcm = require('./ipc.js');
const createWindow = () => {
const win = new BrowserWindow({...});
ipcm.xxx_req({ ipcMain, winb: win })
}
preload.js
const { contextBridge, ipcRenderer } = require('electron');
contextBridge.exposeInMainWorld('electronAPI', {
xxx_req: (response) => ipcRenderer.send('xxx_req',response),
xxx: (callback) => ipcRenderer.on('xxx',callback),
})
index.js(render process)
window.electronAPI.xxx_req("hello");
window.electronAPI.qrcode((event, detail) => {
console.log(detail)
});
If you still don't understand why I did this, please refer to here.

Electron - ERROR:print_render_frame_helper.cc(2224) Printing failed

I have no idea what is happening here, basically I tried to print a document in electron using webContents.print, by silent print, but this error occurs and the printer only prints the document a single time, after that the print queue is filled with new orders, but the error still happening and the file is not printed.
Some code of what I am trying to do:
ipcMain.handle('imprimir', async (event, args) => {
console.log(args);
const ticket = new BrowserWindow({
width: 300,
height: 400,
webPreferences: {
nodeIntegration: true,
enableRemoteModule: true,
contextIsolation: false
}
});
ticket.loadFile('src/views/ticket.html')
.then(() => {
ticket.webContents.send('enviar-pedido', args);
var options = {
silent: true,
deviceName: 'HP Deskjet 2000 J210 series',
printBackground: true,
color: false,
margin: {
marginType: 'printableArea'
},
landscape: false,
pagesPerSheet: 1,
collate: false,
copies: 1,
/*pageSize: { height: 600, width: 353 }*/
}
ticket.webContents.print(options, (success, failureReason) => {
if (!success) {
console.log(failureReason);
}
console.log('Print Initiated');
ticket.close();
});
});
Note: I do not speak fluent English and this is my first question here, I am sorry if I commited some mistake.
I ran into this just the other day.
I determined the error does not appear with the BrowserWindow option
nodeIntegration: false
If you do not need nodeIntegration in the HTML loaded into the ticket window you should be able to turn this off.

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(); })
}

Messages between `BrowserView` and the `renderer` React page in `Electron

I'm trying to figure out how to exchange messages between the main process and the BrowserView.
I've been using the ipc between the main process and the renderer process within a "simple" react renderer page.
But now, using the same technique, I do not see the received message in the console of the BrowserView, which, as far as I understand, seems to behave differently from a "normal" react renderer page.
And this SOF post seems confirm my hypothesis: Electron BrowserView Renderer process vs WebView
In preload I defined:
declare global {
interface Window {
api: {
electronIpcSend: (channel: string, ...arg: any) => void;
electronIpcOn: (channel: string, listener: (event: any, ...arg: any) => void) => void;
}
}
}
In main I have :
function createWindowTypeC (url_string: string) {
WindowTypeC = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
nodeIntegration: false,
contextIsolation: true,
nodeIntegrationInWorker: false,
sandbox: true,
nodeIntegrationInSubFrames: false,
webSecurity: true,
webviewTag: false,
preload: path.join(__dirname, "./preload/preload.js"), /* eng-disable PRELOAD_JS_CHECK */
}
})
// and load the index.html of the app.
// Emitted when the window is closed.
WindowTypeC.on('closed', () => {
WindowTypeC.removeBrowserView(view_C)
WindowTypeC = null
})
enforceInheritance(WindowTypeC.webContents)
// https://www.electronjs.org/docs/latest/api/browser-view
let view_C = new BrowserView()
view_C.webContents.once('did-finish-load', () => {
contents.focus()
view_C.webContents.send('ping', 'whoooooooooh!')
})
view_C.setAutoResize({
width: true,
height: true,
horizontal: true,
vertical: true
})
WindowTypeC.setBrowserView(view_C)
view_C.setBounds({ x: 0, y: 0, width: 800, height: 600 })
view_C.setBackgroundColor("#1e1e1e")
setTimeout(() => {
view_C.webContents.loadURL(url_string)
}, 200)
view_C.webContents.openDevTools({
mode: 'left'
})
}
While in the App_C.tsx I have:
import * as React from 'react';
function App_C(props) {
window.api.electronIpcOn('ping', (event, message) => {
console.log("App_C-window.api.electronIpcOn-ping-message: ", message)
})
window.api.electronIpcSend('pong', "Hello from App_C.tsx")
return (
<div id="outer-container" className='outer-container'>
<h1>App_C</h1>
</div>
);
}
export default App_C;
Executing the code, the page gets correctly rendered, but I do not see any message sent from the BrowserView to the renderer process.
Second, collateral, question, is: how to send a message on the way back, in the BrowserView sent by the renderer process?
And third question: how to interact with the page rendered by the BrowserView?

Why did electron not create file?

I'm building an app on electron and now I'm trying to create a simple file.
Here's the JS:
const app = require("electron").remote;
var dialog = app.dialog;
var fs = require("fs");
document.getElementById('save_project').onclick=() => {
dialog.showSaveDialog((filename) => {
if(filename === undefined){
console.log("You didnt save the file");
return;
};
var content = "hello there";
fs.writeFile(filename, content, (err) => {
if(err) console.log(err);
alert("The file has been successfully saved.")
})
});
};
This window will open as supposed:
Then, I wrote for instance: "hello.txt" on the name input and clicked save.
There's no log written on the console neither a file written in the directory
Edit:
with this js, happens the same ():
const fs = require("fs");
const {dialog} = require("electron").remote;
document.getElementById("save_project").addEventListener("click", () => {
dialog.showSaveDialog((filename) => {
if(filename === undefined){
console.log("nop");
return;
}
fs.writeFile(filename, content, (err) => {
if(err){
console.log(err);
return;
}
alert("file created");
});
});
}, false);
Edited:
Here's the createWindow()
function createWindow () {
// Create the browser window.
const mainWindow = new BrowserWindow({
width: 1920,
height: 1080,
webPreferences: {
preload: path.join(__dirname, "preload.js"),
nodeIntegration: true
},
});
const childWindow = new BrowserWindow ({ width: 1600, height: 800, parent: mainWindow, modal: true, show : false});
// and load the index.html of the app.
mainWindow.loadFile("index.html");
childWindow.loadFile("welcome.html");
childWindow.once("ready-to-show", () => {
childWindow.show();
});
// Open the DevTools.
mainWindow.webContents.openDevTools();
}
Basically, from what i understood, "dialog.showSaveDialog((filename).." this was kinda blocking... i fixed by using:
const {dialog} = require("electron").remote;
let filename = dialog.showSaveDialogSync()
if(filename === undefined){
console.log("filename undefined");
return;
}else{
console.log(filename)
saveAsToFile(filename, ...);
}

Resources