Converting Web app into Desktop app with Electron - electron

Hey i am web developer and i wanted to make app for desktop. I discovered program named Electron i downloaded it from this page: electron.atom.io
Next I created files that are needed for running this app:
index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Hello World!</title>
</head>
<body>
<h1>Hello World!</h1>
We are using node <script>document.write(process.versions.node)</script>,
Chrome <script>document.write(process.versions.chrome)</script>,
and Electron <script>document.write(process.versions.electron)</script>.
</body>
</html>
Then main.js:
const {app, BrowserWindow} = require('electron')
const path = require('path')
const url = require('url')
// 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 createWindow () {
// Create the browser window.
win = new BrowserWindow({width: 800, height: 600})
// and load the index.html of the app.
win.loadURL(url.format({
pathname: path.join(__dirname, 'index.html'),
protocol: 'file:',
slashes: true
}))
// Open the DevTools.
win.webContents.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 macOS 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 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 (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.
and package.json:
{
"name" : "Test-App",
"version" : "0.1.0",
"main" : "main.js"
}
Now when i type in CMD
Electron .
i get the error
'electron' is not recognized as an internal or external command,
operable program or batch file.
Is there any way to run this program from app installed without CMD or How can i fix this?

Welcome to stackoverflow!
The package you installed is a demo package that is meant to demonstrate the different features Electron offers to developers. It is not suitable for your needs right now.
What you need instead is, as devilfart and Vadim pointed out, a global installation of the Electron runtime. This can be achieved by starting a command line with administrative rights and entering the following command:
npm install -g electron
This will install the Electron runtime as a global package inside your base node_modules directory and enable the use of the electron command.

Related

Electron - restart app / refresh environment variables

I'm currently working on an Electron app which uses a third party software. At some point I'm checking if that software is installed on the user's computer (it has to be in PATH), and if it's not there I just run the installation. As I said, the installation will append a directory to the PATH variable. After this happens, I need to restart the app in order to have access to the updated variables.
I already tried to use relaunch, just as in the docs, but it doesn't refresh the variables:
app.relaunch()
app.exit(0)
If I restart the app manually, then everything works ok.
Does anyone have some ideas ? Thanks.
My solution just works for production:
In production, your application could not get your PC's environment variable. So, when you create mainWindow in main.js, you should read environment variables and pass it to process.env variable. After you relaunch the application, it will reload env again as you expected.
Library in use:
https://github.com/sindresorhus/shell-env
https://github.com/sindresorhus/shell-path
import shellEnv from 'shell-env';
import os from 'os';
import shellPath from 'shell-path';
const isDevelopment = process.env.NODE_ENV === 'development';
function createMainWindow() {
mainWindow = new BrowserWindow({
webPreferences: {
nodeIntegration: true,
},
width: 800,
height: 1000,
});
// ...
if (!isDevelopment) {
// TODO: if we're running from the app package, we won't have access to env vars
// normally loaded in a shell, so work around with the shell-env module
// TODO: get current os shell
const { shell } = os.userInfo();
const decoratedEnv = shellEnv.sync(shell);
process.env = { ...process.env, ...decoratedEnv };
console.log('DEBUG process.env', process.env);
// TODO: If we're running from the app package, we won't have access to env variable or PATH
// TODO: So we need to add shell-path to resolve problem
shellPath.sync();
}
// ...
}
After relaunching the application, the environment variables will be updated.
app.relaunch()
app.exit(0)
Notice: Without check !isDevelopment, after relaunching, the application won't be displayed. I have no idea.

Setting platform dependant icon via electron-forge electronPackagerConfig

Using electron-forge to build a desktop app. The app is built for both OSX & Windows. Inside my package.json, I have:
"electronPackagerConfig": {
"icon": "src/images/icon/app_icon_osx.icns"
}
When I build on Windows, I'm having to manually change the icon in package.json from "app_icon_osx.icns" to "app_icon_win.ico".
If I try to just use "app_icon.png" for both platforms, the icon doesn't show on OSX, and the build fails with "rcedit.exe failed with exit code 1. Fatal error: Unable to set icon" on Windows.
I have all 3 versions of the icon (icns, ico, png) in a folder in the project. Because i'm using electron-forge, i don't seem to be able to use electron packager's --icon argument.
Is there a way I can pass the icon to use as a command line arg, instead of hardcoded in package.json? Or a way I can use the same png for both platforms?
The extension is automatically added for each platform. Just supply an icon per platform like this: app_icon.icns, app_icon.ico, ...
Then update your config:
"electronPackagerConfig": {
"icon": "src/images/icon/app_icon"
}
The accepted answer works for macOS and Windows, but for Linux you'll have to do something like this:
Set the app icon (for the app list only) in the maker:
{
name: "#electron-forge/maker-deb",
config: {
options: {
icon: "./src/images/icon.png",
},
},
},
Create an assets folder (or anything) an copy it during the build with the copy-webpack-plugin in your webpack.main.config.js:
const CopyPlugin = require("copy-webpack-plugin");
module.exports = {
// ...
plugins: [new CopyPlugin([{ from: "./assets", to: "assets" }])],
};
You can now access any files inside this folder from your main process, so reference the icon when creating your BrowserWindow as documented here
mainWindow = new BrowserWindow({
// ...
icon: path.join(__dirname, "assets/icon.png"),
});
In forge.config.js, do:
const path = require('path')
module.exports = {
packagerConfig: {
icon: path.join(__dirname, 'favicon'),
},
}
Important notes:
If the file extension is omitted, it is auto-completed to the correct extension based on the platform, including when platform: 'all' is in effect.
This setting doesn't change the icon when running electron-forge start.
If the setting is correct, and you still don't see the correct icon, you might have encountered the icon cache issue.
If on Windows 10, run ie4uinit -show in the command line will show the latest icon.

Button to open developer Tools in compiled app

I'm searching a way to open the developer Tools windows (using a <button>) once the app is compiled in exe, when I cannot use shortcut as I do in developer mode.
Instead of a button its better you do it via a shortcut key.
use - https://www.npmjs.com/package/electron-localshortcut
The library provides apis to register local shortcuts(as opposed to global shortcuts) to your electron app both on mac and windows.
const electronLocalshortcut = require('electron-localshortcut');
function registerShortcuts() {
electronLocalshortcut.register(mainWindow, 'CommandOrControl+B', () => {
mainWindow.webContents.openDevTools();
});
}
app.on("ready", () => {
registerShortcuts();
});

Aurelia: using es6 import for electron + typescript

I have an aurelia application running in electron. My source files are typescript and I have ambient typings for electron and node.
Because I know I'm compiling for use on electron, I am transpiling my typescript to es6 and with System module loading; this means I can turn system.js's transpiler off. I'm using system.js and jspm because that is approach Aurelia has been pushing.
So in my ts files: I would like to be able to do:
import {remote} from 'electron';
Unfortunately, system.js does not know anything about the module electron and fails during runtime. TypeScript on the other hand is perfectly happy because I've set up the typings for electron and node; I get full intellisense in VSCode too.
note: if you attempt to do var electron = require('electron'); in the header, system.js interferes with it and it fails to load. You can place that 'require('electron')' within a class or function and it will work, but I don't find this ideal.
Question: How can I get system.js to correctly return the 'electron' module that is only available when you run the app in electron itself?
A solution --hopefully there is a better way-- I've come up with is to shim the electron module for system.js and link it directly to the contents of require('electron'):
electron.js
System.register([], function (exports_1, context_1) {
"use strict";
var __moduleName = context_1 && context_1.id;
var electron;
return {
setters: [],
execute: function () {
electron = require('electron');
exports_1("default", electron);
Object.keys(electron).forEach(function (key) {
exports_1(key, electron[key]);
});
}
}
});
this effectively wraps the internal electron module and allows system.js to know about it. It works; but hopefully there is a more elegant/built-in way that others know of.
You don't need any mappings or changes to the typescypt as import {remote} from 'electron' will attempt to resolve electron.js as a last resort.

SECURITY_ERR: DOM Exception 18 on iOS 5.1 when upgrading app with WebView that opens local database

If you build a simple Titanium mobile application that contains a WebView which has in it javascript that opens a local database, the first time you install it to an iOS 5.1 device it will open the database correctly. However, if you then upgrade the app on the device (it can still be the exact same version/build), it will error when opening the local database:
SECURITY_ERR: DOM Exception 18
Steps to reproduce:
Add the app.js and database.html files below to the root of Resources.
Install app to iOS 5.1 device (Run > iOS Device in Ti Studio).
Open app, it will say "db opened".
Upgrade app on iOS 5.1 device (Run > iOS Device in Ti Studio).
Open app, it will say "db opening failed: Error: SECURITY_ERR: DOM Exception 18".
Here is the code to reproduce:
app.js:
var win = Ti.UI.createWindow({});
var webView = Ti.UI.createWebView({
top : 0, right : 0, bottom : 0, left : 0, url: 'database.html'
});
win.add(webView);
win.open();
database.html:
<!DOCTYPE HTML>
<html>
<head>
<title>db test</title>
<script>
window.onload = function () {
var dbConn;
try {
dbConn = openDatabase('test', '0.1', 'test database', 5 * 1024 * 1024);
alert('db opened');
} catch (e) {
alert('db opening failed: ' + e.toString());
}
};
</script>
</head>
<body>
db test
</body>
</html>
This issue seems to be the same as Apache Cordova has had and fixed.
https://issues.apache.org/jira/browse/CB-347
Has anyone else run into this issue? Any ideas for a work-around?
We ended up creating a custom webview module for iOS to fix the issue ourselves, as who knows how long it'll take before Titanium does the same:
Webview Module Source

Resources