I am new to electron js. I have a scenario to show a loading/splash screen and then show the login screen.
here is my main.js
// necessary modules for electron application
// importing electron
const { create } = require("domain");
const electron = require("electron");
// initilizing app
const app = electron.app;
// adding window to view
const BrowserWindow = electron.BrowserWindow;
// path module to build file path
const path = require("path")
// to make sure we are using a proper url
const url = require("url")
let {ipcMain} = electron
let toQuit = true; // important to quit
let category = 'main_window' // default window
let win;
app.on("ready", ()=>{
"use strict";
createWindow();
});
app.on("closed", () => {
"use strict";
win = null;
})
app.on('window-all-closed',()=>{
"use strict";
if(process.platform !== 'darwin'){
app.quit();
}
})
app.on("activate", () => {
if (win === null) {
createWindow();
}
});
function createWindow() {
"use strict";
var height;
var width;
var address;
var frame;
var removeMenu;
var title, backgroundColor;
switch (category) {
case "main_window":
height = 200; //Initialize size of BrowserWindow
width = 500; //Initialize size of BrowserWindow
frame = false;
removeMenu = true;
backgroundColor = "#ccc";
address = "Views/SplashScreen/index.html"; //Initialize the address or the file location of your HTML
break;
case "login":
height = 600; //Initialize size of BrowserWindow
width = 400; //Initialize size of BrowserWindow
frame = true;
removeMenu = true;
title = "Login"
address = "Views/Login/index.html"; //Initialize the address or the file location of your HTML
break;
default:
break;
}
win = new BrowserWindow({
height: height, //height and width of BrowserWindow
width: width, //height and width of BrowserWindow
minHeight: height, //minimum height and width of BrowserWindow, you can remove this if you want
minWidth: width, //minimum height and width of BrowserWindow, you can remove this if you want
frame: frame,
backgroundColor: backgroundColor,
webPreferences: {
nodeIntegration: true,
contextIsolation: false,
enableRemoteModule: true,
},
});
win.loadURL(
url.format({
pathname: path.join(__dirname, address),
protocol: "file",
slashes: true,
})
);
// enabling web dev tools
win.webContents.openDevTools({
mode: "detach",
});
// remove default top menu
win.removeMenu(removeMenu);
win.on("ready-to-show", () => {
win.show();
win.focus();
});
win.on("closed", (e) => {
e.preventDefault(); //We have to prevent the closed event from doing it.
if (toQuit) {
console.log("I am called")
//if the value of toQuit is true, then we want to quit the entire application
win = null;
app.exit(); //quit or exit the entire application
} else {
console.log("hide called");
win.hide(); //just hide the BrowserWindow and don't quit the entire application
toQuit = true; //reset the value of toQuit to true
}
});
}
//call this function from your any Javascript
ipcMain.on('createBrowserWindow', function (e, cat) {
"use strict";
category = cat; //get the category of window on which we want to show
toQuit = false; //set the value to false, meaning we don't want to close the entire application but just hide the current BrowserWindow
createWindow(); //call this function over and over again
});
and the splashscreen.js
const ipcRender = require('electron').ipcRenderer;
let count = 1;
let porgressBar = document.getElementById("progressbar");
let i = 70;
let interval = setInterval(()=>{
if(i >= 400){
clearInterval(interval);
ipcRender.send("createBrowserWindow", "login");
}
porgressBar.style.width = i + "px";
ran = Math.floor(Math.random() * (75 - 0 + 1)) + 0;
console.log(ran);
i = i+ran
},500);
Till now what I achieved is that, I am able to open the new window but the previous window is unable to close. I have tried several methods from stack overflow solutions but none of them worked.
package.json
{
"name": "electron-sms",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"start": "electron ."
},
"author": "",
"license": "ISC",
"devDependencies": {
"electron": "^17.1.2"
},
"dependencies": {
"#electron/remote": "^2.0.8"
}
}
Any workaround, please.
Thanks
I have found a solution to my problem.
In Electron Version >= 16
Install the #electron-remote using npm npm i #electron/remote. as remote has been removed in electron Version 14 and later.
secondly, Add the initialize electron-remote using this require("#electron/remote/main").initialize();
Example
const electron = require("electron");
// initilizing app
const app = electron.app;
// adding window to view
const BrowserWindow = electron.BrowserWindow;
// path module to build file path
const path = require("path")
// to make sure we are using a proper url
const url = require("url")
**require("#electron/remote/main").initialize();**
let {ipcMain} = electron
let toQuit = true; // important to quit
let category = 'main_window' // default window
enable webcontents in main.js
require("#electron/remote/main").enable(win.webContents);
in your renderer,js call it as
require("#electron/remote").getCurrentWindow().close();
You are done!
Happy Coding :)
Related
What I would like is to stream my ExcelJS workbook little by little to the browser. The problem is that I'm very uncomfortable with streams.
The facts:
I'm on Node JS v.14
I'm using last version of ExcelJS library to generate a big Excel file
I'm using last version of Koa as a REST API tool
Here's a simplified part of my code. The Excel workbook is ok. If I create a full buffer in memory and send this buffer to Koa, I can download it. But when I'm trying to stream and pass a stream to koa, things go wrong. The way of passing stream to ExcelJS is the right way, from their docs.
EDIT
Here's a full working work base (except for streams).
package.json
{
"name": "stackoverflow-exceljs-koa",
"private": true,
"version": "0.0.1",
"author": "rekam",
"dependencies": {
"exceljs": "^4.3.0",
"koa": "^2.13.4"
}
}
index.js
const Koa = require('koa');
const app = new Koa();
const { exportExcelData } = require('./builder');
app.use(async ctx => {
if (ctx.request.url === '/file') {
await exportExcelData('useFile', './test.xlsx');
ctx.body = 'Done, file saved at ' + __dirname + '/test.xlsx';
return;
}
if (ctx.request.url === '/stream') {
// const stream = new Stream();
// ctx.body = stream;
// await exportExcelData('useStream', stream);
ctx.body = 'to be implemented';
return;
}
ctx.body = 'Not Found';
ctx.status = 404;
});
app.listen(8101);
console.log('visit http://localhost:8101/file or /stream');
builder.js
const Excel = require('exceljs');
module.exports = {
async exportExcelData(type, streamOrFilename) {
const limit = 100;
let offset = 0;
const workbook = new Excel.stream.xlsx.WorkbookWriter({
stream: type === 'useStream' ? streamOrFilename : undefined,
filename: type === 'useFile' ? streamOrFilename : undefined,
useSharedStrings: true,
useStyles: true
});
const sheet = workbook.addWorksheet('Export');
sheet.columns = [{
header: 'ID',
key: 'id'
}];
const build = async (offset) => {
const rows = Array.from({ length: limit }).map((_, i) => ({ id: i + offset }));
if (offset > 10000) {
rows.pop(); // will break while looop
}
rows.forEach(row => sheet.addRow(row).commit());
return rows;
};
let rows;
do {
rows = await build(offset);
offset += limit;
} while (rows.length === limit);
sheet.commit();
await workbook.commit();
return;
}
};
usage
$ node index.js
I'm looking for a clean way to convert a SVG to PNG and download, in Vue 2. What is the best approach ?
I finally managed to come up with this solution:
save() {
const a = document.querySelector("a");
const triggerDownload = (imgURI: string) => {
const evt = new MouseEvent("click", {
view: window,
bubbles: false,
cancelable: true,
});
a?.setAttribute("download", "FileName.png");
a?.setAttribute("href", imgURI);
a?.setAttribute("target", "_blank");
a?.dispatchEvent(evt);
};
const canvas = document.getElementById("canvas") as HTMLCanvasElement;
const ctx = canvas.getContext("2d");
data = new XMLSerializer().serializeToString(
document.getElementById("svgId") as Node
);
const DOMURL = window.URL || window.webkitURL || window;
const img = new Image();
const svgBlob = new Blob([data], { type: "image/svg+xml;charset=utf-8" });
const url = DOMURL.createObjectURL(svgBlob);
img.onload = function () {
ctx?.drawImage(img, 0, 0);
DOMURL.revokeObjectURL(url);
const imgURI = canvas
.toDataURL("image/png")
.replace("image/png", "image/octet-stream");
triggerDownload(imgURI);
ctx?.clearRect(0, 0, canvas.width, canvas.height);
};
img.src = url;
},
I am developing an face detection application,for that I need to collect the users image for reference to detect them later.i have successfully uploaded the image in MySQL databse.now I need upload the image in public folder in react to detect the image in camera.i stuck in uploading image in react public folder.help me out get rid of this problem..
This is the React code where image to be detected in the imgUrl variable
detect = async () => {
const videoTag = document.getElementById("videoTag");
const canvas = document.getElementById("myCanvas");
const displaySize = { width: videoTag.width, height: videoTag.height };
faceapi.matchDimensions(canvas, displaySize);
//setInterval starts here for continuous detection
time = setInterval(async () => {
let fullFaceDescriptions = await faceapi
.detectAllFaces(videoTag)
.withFaceLandmarks()
.withFaceExpressions()
.withFaceDescriptors();
const value = fullFaceDescriptions.length;
this.setState({ detection: value });
fullFaceDescriptions = faceapi.resizeResults(
fullFaceDescriptions,
displaySize
);
canvas.getContext("2d").clearRect(0, 0, canvas.width, canvas.height);
//Label Images
var dummy = ["praveen", "vikranth", "Gokul", "Rahul"];
const labels = nameArray1;
// const labels = ["praveen", "vikranth", "Gokul", "Rahul"];
if (no_of_times <= 0) {
if (no_of_times === 0) {
labeledFaceDescriptors = await Promise.all(
labels.map(async (label) => {
// fetch image data from urls and convert blob to HTMLImage element
const imgUrl = `/img/${label}.png`; // for testing purpose
// const imgUrl = testImage;
const img = await faceapi.fetchImage(imgUrl);
const fullFaceDescription = await faceapi
.detectSingleFace(img)
.withFaceLandmarks()
.withFaceExpressions()
.withFaceDescriptor();
if (!fullFaceDescription) {
throw new Error(`no faces detected for ${label}`);
}
const faceDescriptors = [fullFaceDescription.descriptor];
return new faceapi.LabeledFaceDescriptors(label, faceDescriptors);
})
);
// console.log(no_of_times);
}
}
const maxDescriptorDistance = 0.7;
no_of_times++;
const faceMatcher = new faceapi.FaceMatcher(
labeledFaceDescriptors,
maxDescriptorDistance
);
const results = fullFaceDescriptions.map((fd) =>
faceMatcher.findBestMatch(fd.descriptor)
);
result = [];
results.forEach((bestMatch, i) => {
const box = fullFaceDescriptions[i].detection.box;
// console.log(box)
const text = bestMatch.toString(); //this for basMatch name detection
var str = "";
//This is for removing names confidence to map value without duplicate
var val = text.replace(/[0-9]/g, "");
for (let i of val) {
if (i !== " ") {
str += i;
} else {
break;
}
}
if (result.includes(str) === false) result.push(str);
const drawBox = new faceapi.draw.DrawBox(box, { label: text });
drawBox.draw(canvas);
faceapi.draw.drawFaceExpressions(canvas, fullFaceDescriptions, 0.85);
});
for (let i = 0; i < fullFaceDescriptions.length; i++) {
const result1 = fullFaceDescriptions[i].expressions.asSortedArray()[i];
// console.log(result[i]);
// console.log(result1.expression);
this.test(result[i], result1.expression);
}
}, 100);
In the above code i am manually putting image in public folder,this need to be done dynamically when the user uploads image.
this is place i get the images in base64 from nodejs
axios.get("/image").then((res) => {
testImage = res.data;
// console.log("from image" + res.data);
imgback = <img src={`data:image/jpeg;base64,${res.data}`} />;
});
This is nodejs code for the get request from reactjs
app.get("/image", (req, res) => {
connection.query("SELECT * FROM images", (error, row, fields) => {
if (!!error) {
console.log("Error in the query");
} else {
console.log("successful query");
var buffer = new Buffer(row[0].image, "binary");
var bufferBase64 = buffer.toString("base64");
res.send(bufferBase64);
}
});
});
my goal is, in the imgUrl variable in react code i need to specify the image folder for that i need to dynamically add image in folder.
Or is there is any other way to directly give image array in the imgUrl variable.please help me to sort out this problem.
I would like to show the value from the TouchBarSlider according to where I move it to. An example example of TouchBar can be followed here. I still cannot figure out how to display the value using their given method change from TouchBarSlider.
My current main.js looks like the following.
const {app, BrowserWindow, TouchBar} = require('electron')
const {TouchBarLabel, TouchBarSlider} = TouchBar
const slider = new TouchBarSlider({label: 'angle',
minValue: 0,
maxValue: 360})
const result = new TouchBarLabel()
result.label = '30' + ' deg';
const updateBar = () => {
let timeout = 100;
if (slider.change()){
result.label = slider.values.toString() + ' deg'
}
setTimeout(updateBar, timeout)
}
const touchBar = new TouchBar([
slider, // add slider
result // add display for slider value but doesn't work yet
])
let window;
app.once('ready', () => {
window = new BrowserWindow({
width: 300,
height: 200
});
window.loadURL('about:blank')
window.setTouchBar(touchBar);
})
// Quit when all windows are closed and no other one is listening to this.
app.on('window-all-closed', () => {
app.quit();
});
I also have example repository here. You can just replace my given main.js in the project in order to try things out. My electron version is 1.6.4 and node version is 7.4.0
const { app, BrowserWindow, TouchBar } = require('electron');
const path = require('path')
const url = require('url')
const {TouchBarButton, TouchBarLabel, TouchBarSlider} = TouchBar
const result = new TouchBarLabel();
result.label = '30' + ' deg';
const slider = new TouchBarSlider({
label: 'angle',
minValue: 0,
maxValue: 360,
change: (val) => result.label = val.toString() + ' deg' // register event handler here!
});
const touchBar = new TouchBar([
slider, // add slider
result // add display for slider value
]);
let window;
app.once('ready', () => {
window = new BrowserWindow({
width: 300,
height: 200
});
window.loadURL('about:blank');
window.setTouchBar(touchBar);
});
// Quit when all windows are closed and no other one is listening to this.
app.on('window-all-closed', () => {
app.quit();
});
Working code. Hope this helps! ;)
The following code works flawlessly when run in debug mode (F5) .. but when deployed (as a app tile) or run without the debugger (ctl+f5), it does not work properly.
behaviour expected/ when working: clicking the tile launches the steam url link immediately, without rendering the html page visibly.
behaviour received/ not working: clicking the tile launches the app, only rendering the html page and never launches the steam url.
var mydefs = new Object();
mydefs = { url: 'steam://rungameid/200710' };
function launch(url) {
var uri = new Windows.Foundation.Uri(url);
Windows.System.Launcher.launchUriAsync(uri).then(
function (success) {
if (success) {
// File launched
window.close();
} else {
// File launch failed
}
});
}
(function () {
"use strict";
WinJS.Binding.optimizeBindingReferences = true;
var app = WinJS.Application;
var activation = Windows.ApplicationModel.Activation;
app.onactivated = function (args) {
if (args.detail.kind === activation.ActivationKind.launch) {
launch(mydefs.url);
args.setPromise(WinJS.UI.processAll());
}
};
app.oncheckpoint = function (args) {
window.close();
};
app.start();
})();
Looks like a timing issue. The following works for me as a tile
(function () {
"use strict";
var mydefs = new Object();
mydefs = { url: 'steam://rungameid/200710' };
WinJS.Namespace.define("Steam", {
launch: function launch(url) {
var uri = new Windows.Foundation.Uri(url);
Windows.System.Launcher.launchUriAsync(uri).then(
function (success) {
if (success) {
// File launched
window.close();
} else {
// File launch failed
}
});
}
});
WinJS.Binding.optimizeBindingReferences = true;
var app = WinJS.Application;
var activation = Windows.ApplicationModel.Activation;
app.onactivated = function (args) {
if (args.detail.kind === activation.ActivationKind.launch) {
setTimeout('Steam.launch("steam://rungameid/200710");', 2000);
args.setPromise(WinJS.UI.processAll());
}
};
app.start();
})();