Problem with electron scrolling with Electron BrowserWindow(); - node.js

I am having trouble getting my electron app to allow for scrolling. Please can someone give me some help? Here is my code below. Sorry I am still fairly new to electron and trying to get my head around it. The problem shows as the content in the browser window extends past the end of the window and I have no facility to scroll down using ether the trackpad or arrow keys.
function createWindow () {
server.run();
// Create the browser window.
mainWindow = new BrowserWindow({
width: 1024,
height: 768,
scrollBounce: false,
webPreferences: {
nodeIntegration: true,
contextIsolation: false,
zoomFactor: 0.8,
enableRemoteModule: false
},
frame: true,
minWidth: 1024,
minHeight: 768
});
// and load the index.html of the app.
mainWindow.loadURL('http://'+server.host+':'+server.port+'/')
/*
mainWindow.loadURL(url.format({
pathname: path.join(__dirname, 'index.php'),
protocol: 'file:',
slashes: true
}))
*/
const {shell} = require('electron')
shell.showItemInFolder('fullPath')
// Open the DevTools.
// mainWindow.webContents.openDevTools()
// 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.
// PHP SERVER QUIT
server.close();
app.quit();
mainWindow = null;
})
}

Related

Kuzzle: How does the autoReconnect argument works in WebSocket?

i want kuzzle to reconnect on a disconnected event, so i set autoReconnect argument to true as written in my code:
const connectionOptions = {
autoReconnect: true,
// reconnectionDelay: 500,
ssl: true,
port: PORT
}
kuzzle = new Kuzzle(new WebSocket(ADDRESS, connectionOptions), {
autoQueue: true,
autoReplay: true,
offlineMode: 'auto',
queueTTL: 0,
queueMaxSize: 500
})
i check the event of kuzzle with this:
kuzzle.on('reconnected', () => {
console.log('kuzzle reconnected')
})
kuzzle.on('disconnected', () => {
console.log('kuzzle disconnected')
})
But the only thing i see is the disconnected event but never the reconnect. Why ????
PS: i disable and enable my network interfaces to test my code

Puppeteer throws "Protocol error (IO.read): Target closed." now and again

This is driving me insane... I have the following code:
// Load a PUG template
const template = await loadTemplateRoute(pdfProps.layout);
// Generate HTML
const html = template(pdfProps);
// requirement for puppeteer to work locally, if using locally
const executablePath = process.env.EXECUTABLE_PATH || await chromium.executablePath;
console.log('executable path', executablePath);
// These are needed to run on WSL
chromium.args.push(['--disable-gpu', '--single-process']);
console.log('1');
const browser = await puppeteer.launch({
args: chromium.args,
defaultViewport: chromium.defaultViewport,
executablePath,
headless: true,
ignoreHTTPSErrors: true
});
console.log('2');
const page = await browser.newPage();
console.log('3');
// eslint-disable-next-line quote-props
await page.setContent(html, { 'waitUntil': 'networkidle2' });
console.log('4');
// here we can insert customizable features in the future using JSONB stored formats
const pdf = await page.pdf({
format: 'A4',
printBackground: true,
margin: {
top: '1cm',
right: '1cm',
bottom: '1cm',
left: '1cm'
}
});
await page.close();
console.log('5');
await browser.close();
console.log('6');
return pdf;
Running this gives me the PDF I want, but only like once in ten times. The other times I get either this after console.log('4'):
Protocol error (IO.read): Target closed.
at .../node_modules/puppeteer-core/lib/Connection.js:183:56
at new Promise (<anonymous>)
at CDPSession.send (.../node_modules/puppeteer-core/lib/Connection.js:182:12)
at Function.readProtocolStream (.../node_modules/puppeteer-core/lib/helper.js:254:37)
at processTicksAndRejections (internal/process/task_queues.js:94:5)
at Page.pdf (.../node_modules/puppeteer-core/lib/Page.js:1021:12)
Or other times (more seldom) this after console.log('3'):
Navigation failed because browser has disconnected!
at CDPSession.<anonymous> (.../node_modules/puppeteer-core/lib/LifecycleWatcher.js:46:107)
at CDPSession.emit (events.js:223:5)
at CDPSession.EventEmitter.emit (domain.js:475:20)
at CDPSession._onClosed (.../node_modules/puppeteer-core/lib/Connection.js:215:10)
at Connection._onClose (.../node_modules/puppeteer-core/lib/Connection.js:138:15)
at WebSocket.<anonymous> (.../node_modules/puppeteer-core/lib/WebSocketTransport.js:48:22)
at WebSocket.onClose (.../node_modules/puppeteer-core/node_modules/ws/lib/event-target.js:124:16)
at WebSocket.emit (events.js:223:5)
at WebSocket.EventEmitter.emit (domain.js:475:20)
at WebSocket.emitClose (.../node_modules/puppeteer-core/node_modules/ws/lib/websocket.js:191:10)
at Socket.socketOnClose (.../node_modules/puppeteer-core/node_modules/ws/lib/websocket.js:850:15)
at Socket.emit (events.js:223:5)
at Socket.EventEmitter.emit (domain.js:475:20)
at TCP.<anonymous> (net.js:664:12)
I run this on a WSL Ubuntu but running it on Mac gives errors too (but less frequently).
It seems to be working better if I wait like 5 minutes between tries but listing processes (ps -ef) shows nothing running/hanging...
EDIT: Logging out what's happening in /node_modules/puppeteer-core/lib/Connection.js:182:56 gives:
send(); Page.printToPDF {
transferMode: 'ReturnAsStream',
landscape: false,
displayHeaderFooter: false,
headerTemplate: '',
footerTemplate: '',
printBackground: true,
scale: 1,
paperWidth: 8.27,
paperHeight: 11.7,
marginTop: 0.39375,
marginBottom: 0.39375,
marginLeft: 0.39375,
marginRight: 0.39375,
pageRanges: '',
preferCSSPageSize: false
}
send(); IO.read { handle: '1' }
send(); IO.read { handle: '1' }
The Page.printToPDF works fine, the first IO.read also is working while the second IO.read throws the error...
After trying a bunch of things I started suspecting external sources as it worked fine with simple templates.
Reworking the templates to not load any external CSS and instead place all CSS in <style> tags and "pre-parse" all images to base64 (<img src="data:image/png;MIIlkaa3498asm..." />) it is no longer happening...
Clearly some load of resources that is messing with me...
I had the same issue and resolved it by
replacing page.pdf() with page.createPDFStream() (docs here)
adding a 60 seconds timeout to page.createPDFStream() and page.setContent (defaults to 30 sec)
waiting for ['load', 'domcontentloaded'] events to be fired
Example
await page.setContent(html, {
timeout: 60000,
waitUntil: ['load', 'domcontentloaded'],
});
await page.emulateMediaType('screen');
// const pdf = await page.pdf({
const pdfStream = await page.createPDFStream({
timeout: 60000,
format: 'A4',
margin: { top: '0.5cm', right: '1cm', bottom: '0.8cm', left: '1cm' },
printBackground: true,
});
// ...
// do something with the PDF stream, e.g. save to file
pdfStream
.on('end', () => console.log('pdfStream done'))
.on('error', (err) => console.log(err))
.pipe(fs.createWriteStream('my-form.pdf'));

How to install a spellchecker in Electron for an external URL

I'm using a very simple Electron app to load a URL in a frameless window. Here's the app.js:
const {app, BrowserWindow} = require('electron')
let window = null
app.once('ready', () => {
window = new BrowserWindow({
width: 800,
height: 600,
icon: __dirname + '/icon/appIcon.png',
show: false,
webPreferences: {
nodeIntegration: false
}
})
window.loadURL('https://www.notion.so')
window.setMenuBarVisibility(false)
window.once('ready-to-show', () => {
// window.maximize()
window.show()
})
})
As Electron doesn't have all the same utilities as Chrome or Chromium, spell check does not work. I'm trying to install electron-spell-check-provider here but can't figure out how it works for the life of me. It has one snippet it says to paste in the renderer process, what section is that of this code?
I apologize if this is a very basic question, I'm still very new to Electron development and would be very grateful for help on this.

Problem with open new browser using router in Vue/Electron. Redirecting to default route

I'm trying to open a new window using Vue/Electron but the new windows is opening on default rounte instead the needed route.
*The route on navigation-drawer is working well.
file: router/index.js
import Process from '#/components/ProcessManager/Process.vue'
export default new Router({
routes: [
{
path: '/',
name: 'home',
component: require('#/components/LandingPage').default
},
{
path: 'process',
name: 'process',
component: Process,
},
{
path: '*',
redirect: '/'
}
]
file:main/index.js
const processURL = process.env.NODE_ENV === 'development'
? `http://localhost:9080/#/process`
: `file://${__dirname}/index.html#process`
function createWindow2 () {
let win = new BrowserWindow({ width: 400, height: 320, webPreferences: {webSecurity: false} })
win.loadURL(processURL)
win.on('closed', () => {
win = null
})
}
It looks like it loads the index.html but does not start the app, and the reason is shown in the error message in the screenshot you supplied.
Looking at the error message, you can read here what's going on.

Ways to detect node environment in electron

I would like to know how can I detect the NODE_ENV variable inside the electron main file.
What I'm trying to do is to set the loadURL to localhost:8080 if my NODE_ENV === 'dev' otherwise to /dist/index.html. Because I want to use some webpack-dev-server features such as the HMR and live reload during the development.
I set my npm script in this way but I'm not sure if it is correct.
package.json
"scripts": {
"start": "electron .",
"start:dev": "NODE_ENV=dev webpack-dev-server --config webpack.dev.js && electron .",
"build": "NODE_ENV=prod webpack --config webpack.prod.js && electron ."
},
Here is my electron main file.
main.js
const electron = require('electron');
const url = require('url');
const path = require('path');
const { app, BrowserWindow } = electron;
let mainWindow = null;
app.on('ready', function() { // eslint-disable-line
mainWindow = new BrowserWindow({
webPreferences: {
nodeIntegration: true,
},
});
// mainWindow.loadURL('http://localhost:8080/');
mainWindow.loadURL(url.format({
pathname: path.join(__dirname, '/dist/index.html'),
protocol: 'file:',
slashes: true,
}));
mainWindow.on('closed', function(){
app.quit();
});
});
I will share some of the code from a project I am working on that deals with this issue and hopefully it will help clarify how you might be able to solve your issue.
Electron considers the environment to always be "development" if you are not loading the app from an executable file after packaging the app with something like electron-builder or electron-packager.
Distinguishing "development" from "production" #7714
This has made it time consuming for me to test other items that behave differently in prod vs. dev, but at least that seems to consistently work.
Once this is understood you can use electron.app.isPackaged to set a variable in your main.js file that can be used to control certain functionality.
Demo below...let me know if you have confusion that is not explained in the commented parts of the code.
Here are the npm scripts I am using in a project running Electron v7.0.1:
"main": "main.js",
"scripts": {
"test": "jest",
"prod": "webpack --mode production --config webpack.build.config.js && electron --noDevServer .",
"start": "webpack-dev-server --hot --host 0.0.0.0 --config=./webpack.dev.config.js --mode development",
"build": "webpack --config webpack.build.config.js --mode production",
"package-mac": "electron-builder build --x64 --mac",
"package-all": "electron-builder build -mwl",
"package-linux": "electron-builder build --linux",
"gh-publish-mac": "electron-builder build --x64 --mac -p always",
"gh-publish": "electron-builder build -mwl -p always",
}
Here is code from the main.js file that is used to manage some functionality based on dev vs prod:
// Keep a reference for dev mode
let dev = false;
// this works if npm run build, followed by npm run package-(any of the scripts),
// and then open from executable file
dev = !app.isPackaged;
function createWindow() {
// Create the new browser window instance. devtools set to false in production
if (!dev) {
mainWindow = new BrowserWindow({
width: 2000,
height: 1000,
minWidth: 1304,
minHeight: 700,
backgroundColor: "-webkit-linear-gradient(top, #3dadc2 0%,#2f4858 100%)",
show: false,
title: "Swell",
allowRunningInsecureContent: true,
webPreferences: {
devTools: false,
nodeIntegration: true,
sandbox: false,
webSecurity: true,
},
icon: `${__dirname}/src/assets/icons/64x64.png`,
});
} else {
mainWindow = new BrowserWindow({
width: 2000,
height: 1000,
minWidth: 1304,
minHeight: 700,
backgroundColor: "-webkit-linear-gradient(top, #3dadc2 0%,#2f4858 100%)",
show: false,
title: "Swell",
allowRunningInsecureContent: true,
webPreferences: {
nodeIntegration: true,
sandbox: false,
webSecurity: true,
},
icon: `${__dirname}/src/assets/icons/64x64.png`,
});
}
if (dev) {
const {
default: installExtension,
REACT_DEVELOPER_TOOLS,
REDUX_DEVTOOLS,
} = require("electron-devtools-installer");
// If we are in developer mode Add React & Redux DevTools to Electon App
installExtension(REACT_DEVELOPER_TOOLS)
.then((name) => console.log(`Added Extension: ${name}`))
.catch((err) => console.log("An error occurred: ", err));
installExtension(REDUX_DEVTOOLS)
.then((name) => console.log(`Added Extension: ${name}`))
.catch((err) => console.log("An error occurred: ", err));
}
// and load the index.html of the app.
let indexPath;
if (dev && process.argv.indexOf("--noDevServer") === -1) {
// if we are in dev mode load up 'http://localhost:8080/index.html'
indexPath = url.format({
protocol: "http:",
host: "localhost:8080",
pathname: "index.html",
slashes: true,
});
} else {
indexPath = url.format({
// if we are not in dev mode load production build file
protocol: "file:",
pathname: path.join(__dirname, "dist", "index.html"),
slashes: true,
});
}
// our new app window will load content depending on the boolean value of the dev variable
mainWindow.loadURL(indexPath);
// give our new window the earlier created touchbar
mainWindow.setTouchBar(touchBar);
// prevent webpack-dev-server from setting new title
mainWindow.on("page-title-updated", (e) => e.preventDefault());
// Don't show until we are ready and loaded
mainWindow.once("ready-to-show", () => {
mainWindow.show();
// Open the DevTools automatically if developing
if (dev) {
mainWindow.webContents.openDevTools();
}
});
// Emitted when the window is closed.
mainWindow.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.
//tldr: Remove the BrowserWindow instance that we created earlier by setting its value to null when we exit Swell
mainWindow = null;
});
//require menu file
require("./menu/mainMenu");
}
// 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", () => {
// createLoadingScreen();
createWindow();
if (!dev) {
autoUpdater.checkForUpdates();
}
});
ipcMain.on("check-for-update", () => {
//listens to ipcRenderer in UpdatePopUpContainer.jsx
if (!dev) autoUpdater.checkForUpdates();
});
Well, some quick solution would be if statement
if(process.env.NODE_ENV === 'dev') {
mainWindow.loadURL('http://localhost:8080/')
} else {
mainWindow.loadURL(url.format({
pathname: path.join(__dirname, '/dist/index.html'),
protocol: 'file:',
slashes: true,
}));
}

Resources