im try to do a project that connect pc to pc like screencast. when following the coding online im having a problem when trying to click the button. i cant click the button to pup up the id code.
This the code for app.js
const { app, BrowserWindow, ipcMain } = require('electron')
const path = require('path')
const { v4: uuid4} = require('uuid');
const screenshot= require('screenshot-desktop');
var socket = require('socket.io-client')('http://172.20.10.3:5000');
var interval;
const createWindow = () => {
// Create the browser window.
const mainWindow = new BrowserWindow({
width: 500,
height: 150,
webPreferences: {
preload: path.join(__dirname, 'index.js')
}
})
// and load the index.html of the app.
mainWindow.removeMenu();
mainWindow.loadFile('index.html')
// Open the DevTools.
// mainWindow.webContents.openDevTools()
}
// 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.whenReady().then(() => {
createWindow()
app.on('activate', () => {
// On macOS it's common to re-create a window in the app when the
// dock icon is clicked and there are no other windows open.
if (BrowserWindow.getAllWindows().length === 0)
createWindow()
})
})
// Quit when all windows are closed, except on macOS. There, it's common
// for applications and their menu bar to stay active until the user quits
// explicitly with Cmd + Q.
app.on('window-all-closed', () => {
if (process.platform !== 'darwin')
app.quit()
})
ipcMain.on("start-share", function(event , arg){
var uuid = uuid4();
socket.emit("join-message", uuid);
event.reply("uuid", uuid);
})
ipcMain.on("stop-share", function(event, arg){
})
// In this file you can include the rest of your app's specific main process
// code. You can also put them in separate files and require them here.
This is the index.js file
const ipcRenderer = require ('electron').ipcRenderer;
window.onload = function(){
ipcRenderer.on("uuid", (event, data)=>{
document.getElementById("code").innerHTML = data;
})
}
function startShare(){
ipcRenderer.send("start-share", {} );
document.getElementById("start").style.display = "none";
document.getElementById("stop").style.display = "block";
}
function stopShare(){
ipcRenderer.send("stop-share", {});
document.getElementById("stop").style.display = "none";
document.getElementById("start").style.display = "block";
}
this is the popup when running the code. i cant click the start button
enter image description here
im following this video from (youtube)
this the documentation that i follow in electronelectron website
if someone having problem to see the codes i will try to edit and insert more code or maybe send a zip file. im really needed some help in developed this project for education purpose
im expecting some guide to develop this project. if can i would like the same in the video but i have follow that video from start to end but stuck in the middle of the video. really needed the help
It seems you didn't add your startShare and stopShare functions to your index.html. The preload script is used only for a bridge between your main process and ui process. It doesn't have window object and doesn't attach itself to the index.html.
webPreferences: {
preload: path.join(__dirname, 'index.js')
}
You have to create a bridge and pass ipcRenderer.on function to your ui process. Or you also can add nodeIntegration: true to your webPreferences object. You can read some disadvantages about it.
Then you need to attach your index.js file to the index.html using <script> tag.
Related
I have created a button(Connect), when I click it should go to the other page(second.html). It works with localhost, but not with Electron App. What am I doing wrong?
<script>
$(document).ready(() => {
$( '#buttonConnect').on('click',() =>{
const inputIp = $('#ip');
if(inputIp.val() !== ""){
window.location.href = "observer.html ?ip="+inputIp.val();
}else{
alert("Check Connection Settings!");
}
});
});
</script>
<button class="btn btn-primary" id="buttonConnect">Connect</button>
You need to communicate with electron from your remote window to tell it which URL to load.
Using IPC is the recommended way of doing that.
(a former solution was using remote which is deprecated now)
In your remote code (your jQuery code from above, in this case):
let { ipcRenderer } = require("electron");
$(document).ready(() => {
$( '#buttonConnect').on('click',() =>{
const inputIp = $('#ip');
if (inputIp.val() !== ""){
ipcRenderer.send("load-page", `second.html?ip=${inputIp.val()}`);
}
else {
alert("Check Connection Settings!");
}
});
});
In your main electron code (probably app.js):
let electron = require("electron");
let { BrowserWindow, ipcMain } = electron;
// ...
ipcMain.on("load-page", (event, uri) => {
let win = new BrowserWindow({ /* ... */ });
// I don't know your directory structure.
// You may have to adapt the following line.
win.loadURL(`file://${__dirname}/${uri}`);
});
I have an electron app that loads the URL of the web version of the app.
However I cannot close the application by clicking in the X button and I dont have access to the webapp.
I have tried this:
let count = BrowserWindow.getAllWindows().length;
///returns 1, so there is only 1 window)
window.onbeforeunload=function(e){
e.returnValue=undefined;
return undefined;
}
window.close();
app.quit();
Nothing happens.
app.exit(0) works, but I dont want to use it. Is there a way I can close the app with window.close and app.quit?
EDIT:
The problem are those global beforeunload events. If i click remove in the devtools I am able to close the app.
Also this let names= window.eventNames();returns an array that does not have any beforeunload events
In the file where you created the BrowserWindow, you can attach an event to the 'close' handler for the window. For Electron, this is usually main.js.
const {app, BrowserWindow} = require('electron');
let mainWindow = null;
app.on('ready', () => {
mainWindow = new BrowserWindow({
//options here
});
mainWindow.loadURL([url here]);
//attach event handler here
mainWindow.on("close", () => {
mainWindow = null;
app.quit();
});
});
For good measure, in the case that you may have more than one window, place this in your main.js file.
app.on('window-all-closed', () => {
if(process.platform !== "darwin")
app.quit();
});
You need to save the BrowserWindow object reference. Then listen for a 'closed' event and dereference it:
const { app, BrowserWindow } = require('electron');
let win; // = new BrowserWindow();
win.on('closed', () => {
win = null
})
After dereference, it's all simple, just listen for 'window-all-closed' event on app:
app.on('window-all-closed', () => {
app.quit()
})
What I'm trying to achieve is "real" app-like behaviour in a sense that when I close the app on MacOS (hit X, so the app is still in dock) and afterwards open the app from dock again, the webpage content should be there immediately. As I'm trying to build a container for a web-app, the behaviour I'm getting is that every time I open the app, the web page is loaded again causing friction in the UX.
I've tried some dirty workarounds, like calling .hide() on main window from the renderer process before unloading the window:
const {remote} = require('electron');
const main = remote.require('./main.js');
window.onbeforeunload = e => {
main.hideWindow();
e.returnValue = false;
};
and in main process
exports.hideWindow = () => {
mainWindow.hide();
};
But that way I cannot quit my app at all.
Another option I considered was to load the whole mainWindow DOM in the memory, then upon opening the app, in the <webview> preload script load the cached content into the webview and once the page loads, overwrite the webview content, but it also seems very hackish.
I know Slack behaves exactly how I want my app to behave, but I'm struggling to find how they achieve that instant-load (or perhaps not ever closing, except when Quit is selected from the Dock or Cmd+Q is hit).
If I understand your issue correctly then I think there are a couple of standard workarounds for this. Specifically around
...not ever closing, except when Quit is selected from the Dock or
Cmd+Q is hit)
// Quit when all windows are closed.
app.on('window-all-closed', () => {
// On OS X it is common for applications and their menu bar
// to stay active until the user quits explicitly with Cmd + Q
if (process.platform !== 'darwin') {
app.quit()
}
})
And...
open the app from dock again, the webpage content should be there
immediately.
app.on('activate', () => {
// On OS X it's common to re-create a window in the app when the
// dock icon is clicked and there are no other windows open.
if (mainWindow === null) {
createWindow()
}
})
I ended up having a flag which governs the "closing" behaviour
let allowQuitting = false;
and handling the closing like this
function quitApp() {
if (app) {
allowQuitting = true;
app.quit();
}
}
function closeApp() {
if (mainWindow && !mainWindow.isDestroyed()) {
mainWindow.hide();
}
}
On closing, I listen on closing events
function createWindow() {
mainWindow.on('closed', function () {
closeApp();
});
mainWindow.on('close', event => {
if (allowQuitting === false) {
event.preventDefault();
closeApp();
}
});
...
}
app.on('ready', createWindow);
On activating, I first check if the window exists
app.on('activate', function () {
if (mainWindow === null) {
createWindow();
} else {
mainWindow.show();
}
});
The app can be closed using Cmd+Q due to the accelerator:
const template = [{
label: 'Application',
submenu: [
...
{
label: 'Quit', accelerator: 'Command+Q', click: () => quitApp()
}
]
},
...
];
Menu.setApplicationMenu(Menu.buildFromTemplate(template));
This gives me the desired result, albeit with a side-effect. The app can be closed with Cmd+Q, but can't be closed from the dock (by selecting Quit) or when shutting the system down (says it interrupted the shutdown).
I am writing an application in electron where if a user has a unsaved file open I want to prompt the user before saving it. I found this example code online:
window.onbeforeunload = (e) => {
var answer = confirm('Do you really want to close the application?');
e.returnValue = answer; // this will *prevent* the closing no matter what value is passed
if(answer) { mainWindow.destroy(); } // this will close the app
};
This code strangely works if the dialogs Yes, Cancel or X button is pressed within a few seconds of appearing but if you let the dialog rest on screen for a little and then click a button the application will close no matter what is pressed.
This code is located in the my main script file called by index.html
Really strange behavior! I cannot explain why it's happening, but can give you a workaround implemented in main process.
You can use electron's dialog module and create the same confirmation dialog with electron. This one works as expected.
main.js
const { app, BrowserWindow, dialog } = require('electron')
const path = require('path')
app.once('ready', () => {
let win = new BrowserWindow()
win.loadURL(path.resolve(__dirname, 'index.html'))
win.on('close', e => {
let choice = dialog.showMessageBox(
win,
{
type: 'question',
buttons: ['Yes', 'No'],
title: 'Confirm',
message: 'Do you really want to close the application?'
}
)
if (choice === 1) e.preventDefault()
})
})
It might be possible only when DevTools window is activated.
In any case, prefer working with the event close as pergy suggested above. This is so far the best approach.
But be aware that e.preventDefault() is spreading everywhere in the code. Once you managed properly the preventDefault() you need to turn the variable e.defaultPrevented = false to get back to the natural behavior of your app.
Actually, it seems e.preventDefault() function is turnind the variable e.defaultPrevented to true until you change its value.
In my case, I had to use a variable called modificationEnCours which is true when I don't want to close my window and then false if I want to like that:
let mainWindow
let mainMenu // Menu de la fenĂȘtre principale
app.on('ready', () => {
// Listen for app to be ready
// Create the mainWindow
mainWindow = new BrowserWindow({
width: 1024,
height: 768,
minHeight: 350,
minWidth: 500,
frame: true,
webPreferences: {
nodeIntegration: true
}
})
// Quit app when window is closed
mainWindow.on('close', function(e){
console.log('close')
if (modificationEnCours){
e.preventDefault()
if(msgBoxVerifieSauvegarde('Question','Voulez-vous enregistrer avant de quitter ?')) {
modificationEnCours=false
app.quit()
}
} else if (process.platform !== 'darwin') {
modificationEnCours=false
app.quit()
mainWindow = null
}
})
// Load html in window
mainWindow.loadFile(path.join(__dirname, 'mainWindow.html'))
// Build menu from template
mainMenu = Menu.buildFromTemplate(mainMenuTemplate)
// Insert menu
Menu.setApplicationMenu(mainMenu)
})
I am learning Electron and built my own "hello world" type application that works. I started learning it like an hour ago so any noob friendly tips are highly appreciated.
I decided to include angularjs + angular material to style it and see how it works. Now my piece of code that sends notification isn't working. That raised a question.
How do I send click events from angularjs to electron?
Here is the sample code from all files
main.js copied from get-started electron github page
const electron = require('electron');
const {ipcMain} = require('electron');
// Module to control application life.
const {app} = electron;
// Module to create native browser window.
const {BrowserWindow} = electron;
// Keep a global reference of the window object, if you don't, the window will
// be closed automatically when the JavaScript object is garbage collected.
let win;
function openInbox() {
win.loadURL('https://inbox.google.com/?pli=1');
}
function createWindow() {
// Create the browser window.
win = new BrowserWindow({width: 1366, height: 768});
// and load the index.html of the app.
win.loadURL(`file://${__dirname}/index.html`);
win.openDevTools();
// Emitted when the window is closed.
win.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.
win = null;
});
}
// 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', createWindow);
// Quit when all windows are closed.
app.on('window-all-closed', () => {
// On OS X it is common for applications and their menu bar
// to stay active until the user quits explicitly with Cmd + Q
if (process.platform !== 'darwin') {
app.quit();
}
});
app.on('activate', () => {
// On OS X it's common to re-create a window in the app when the
// dock icon is clicked and there are no other windows open.
if (win === null) {
createWindow();
}
});
// In this file you can include the rest of your app's specific main process
// code. You can also put them in separate files and require them here.
ctrl.js // renderer file that used to work and send notifications prior to including angularjs + material lib
const {ipcRenderer} = require('electron');
const button = document.getElementById('button');
button.addEventListener('click', evt => {
new Notification('Angular Material FTW!');
});
index.html
<!DOCTYPE html>
<html ng-app="webApp">
<head>
<meta charset="UTF-8">
<title>Hello World!</title>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.5/angular.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.5/angular-animate.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.5/angular-aria.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angular_material/1.0.7/angular-material.min.js"></script>
<script src="angular-main.js"></script>
<link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/angular_material/1.0.7/angular-material.min.css">
</head>
<body layout-align="center center" layout-padding>
<h1 id="hello">Hello World!</h1>
<div></div>
<md-button class="button md-raised md-primary">Click Me</md-button>
</body>
<script src="ctrl.js"></script>
</html>
angular-main.js Angular file
(function() {
angular
.module('webApp', ['ngMaterial'])
.config(themeConfiguration)
.controller('appCtrl', appCtrl);
function themeConfiguration($mdThemingProvider) {
$mdThemingProvider.theme('default')
.primaryPalette('blue', {
'default': '500'
})
.accentPalette('red')
.warnPalette('deep-orange')
.backgroundPalette('grey', {
'default': '100'
});
}
function appCtrl() {
var vm = this;
vm.notification = function Notification(evt) {
new Notification('Hello angular');
};
}
})();
If I remove Angularjs and Material the ctrl.js works and send notification just fine.
Answering my own question, to make things work just place code inside angularjs Controller function like this
function appCtrl() {
var vm = this;
const button = document.getElementById('button');
button.addEventListener('click', evt => {
new Notification('Angular Material FTW!');
});
}