ElectronJS is an Open Source Framework used for building Cross-Platform native desktop applications using web technologies such as HTML, CSS, and JavaScript which are capable of running on Windows, macOS, and Linux operating systems. It combines the Chromium engine and NodeJS into a Single Runtime.
Electron at its core is a NodeJS application having capabilities to interact with the native OS environment such as File System, System Tray etc. For creating interactive native OS applications Electron needs to integrate itself with OS functionalities. One such crucial functionality is Desktop Notifications. All three operating systems have provisions for sending Desktop Notifications. Electron provides the built-in Notification Module which allows the application to send Custom Notifications, using the operating systems native notification APIs to display it. This tutorial will demonstrate how to create Custom Desktop Notifications using the Notification Module.
We assume that you are familiar with the prerequisites as covered in the above-mentioned link. For Electron to work, node and npm need to be pre-installed in the system.
Notifications In Electron: The Notification Module is a part of the Main Process. To import and use the Notification Module in the Renderer Process, we can use the Remote Module provided by Electron. In this tutorial, we will also be using Electron Remote. For more details on the Remote Module, Refer this link.
Example: We will start by building the basic Electron Application by following the given steps.
- Step 1: Navigate to an Empty Directory to setup the project, and run the following command,
npm init
To generate the package.json file. Install Electron using npm if it is not installed.
npm install electron --save-dev
This command will also create the package-lock.json file and install the required node_modules dependencies. Once Electron has been successfully installed, Open the package.json file and perform the necessary changes under the “scripts” key.
package.json:
{ "name": "electron-notification", "version": "1.0.0", "description": "Custom notification in Electron", "main": "main.js", "scripts": { "start": "electron" }, "keywords": [ "electron" ], "author": "Radhesh Khanna", "license": "ISC", "dependencies": { "electron": "^8.2.5" } }
- Step 2: Create a main.js file according to the project structure. This file is the Main Process and acts as an entry point into the application. Copy the Boilerplate code for the main.js file as given in the following link. We will modify the code to suit our project needs.
main.js:
const { app, BrowserWindow } = require(
'electron'
)
function
createWindow() {
// Create the browser window.
const win =
new
BrowserWindow({
width: 800,
height: 600,
webPreferences: {
nodeIntegration:
true
}
})
// Load the index.html of the app.
win.loadFile(
'src/index.html'
)
// Open the DevTools.
win.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)
// 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
(BrowserWindow.getAllWindows().length === 0) {
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.
- Step 3: Create the index.html file within the src directory. We will also copy the boilerplate code for the index.html file from the above-mentioned link. We will modify the code to suit our project needs.
index.html:
<!DOCTYPE html>
<
html
>
<
head
>
<
meta
charset
=
"UTF-8"
>
<
title
>Hello World!</
title
>
/security#csp-meta-tag -->
<
meta
http-equiv
=
"Content-Security-Policy"
content
=
"script-src 'self' 'unsafe-inline';"
/>
</
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
>.
<!-- Adding Individual Renderer Process JS File -->
<
script
src
=
"index.js"
></
script
>
</
body
>
</
html
>
- Output: At this point, our basic Electron Application is set up. To launch the Electron Application, run the Command:
npm start
Notification Options: Now we will create a Custom Desktop Notification on a Windows Machine. The Notification Module provides certain Instance Events, Instance Methods, and Options which are Operating System specific. If a property that is incompatible with the native OS is used, it is Simple Ignored. A detailed list of the same is provided below.
- title: String Supported by all OS. The Title of the Notification shown at top of Notification Window
- subtitle: String (Optional) Supported by macOS only. A Subtitle of the Notification. Shown Below the Title
- body: String Supported by all OS. The Body of the Notification Window
- silent: Boolean (Optional) Supported by all OS. Whether or not to omit OS Notification Sound on displaying the notification
- icon: String (Optional) Supported by all OS. An Icon to display in the Notification Window. For the purpose of this tutorial, used a PNG image of the Electron logo saved in the ‘assets’ folder
- hasReply: Boolean (Optional) Supported by macOS only. To display an Inline Reply Option to the Notification window
- replyPlaceholder: String (Optional) Supported by macOS only. The Placeholder for the ‘hasReply’ input field
- urgency: String (Optional) Supported by Linux Only. The urgency of the Notification. Values can be ‘normal’, ‘critical’, or ‘low’.
- closeButtonText: String (Optional) Supported by macOS only. A Custom Title for the Close Button of the Notification
- timeoutType: String (Optional) Supported in Windows and Linux operating Systems. The Timeout Duration of the Notification. Values can be ‘default’ or ‘never’. As of Electron 8.0+, there is a bug associated with this property. Setting the value as ‘never’, the notification should only disappear on manual intervention by the user. However, This is not the case. Irrespective of the value, the notification will disappear on its own. You can follow the bug tracking here.
- actions: Object (Optional) Supported by macOS only. Actions to add to the Notification. It is an Array of Objects. Every Object consists of ‘type’ and ‘text’. There are certain limitations associated with using this property. In the case of multiple actions defined, only the first one is used. If multiple actions are provided then they will be listed as additional actions, i.e. displayed when the mouse is active over the first action button. This case is also incompatible with
hasReply
property and will be ignored ifhasReply: true
.
For a detailed explanation, Refer this link. - sound: String (Optional) Supported by macOS only. Sound File to play when the Notification is displayed. Any of the default sounds present in macOS can also be used in addition to a custom sound file. The sound file needs to be present within the app bundle or any of the following locations that are mentioned in this link. In this tutorial the custom sound file is present within the assets folder as sound.mp3
The Notification Module also provides us with a Static Method,
Notification.isSupported(). Returns a Boolean value stating whether Notifications are Supported in the Current System or not. In the index.html file, add the following code before the script tag.
- index.html:
<
br
><
br
>
<
strong
>
Trigger Custom Notifications in Electron
</
strong
>
<
button
id
=
"trigger"
>
Trigger Custom Notification
</
button
>
- Output:
The Trigger Custom Notification Button does not have any functionality associated with it. We will add an EventListener
to the button to trigger the Custom Notification. We will also add EventListener to the Notification object. Create the index.js file following the project Structure and perform the following changes.
- index.js:
const electron = require(
'electron'
);
const path = require(
'path'
)
// Importing the Notification Module from Electron,
// Since it is a Part of the Main Process, Using the
// Remote Module to Import it in Renderer Process
const Notification = electron.remote.Notification;
var
button = document.getElementById(
'trigger'
);
const options = {
title:
'Custom Notification'
,
subtitle:
'Subtitle of the Notification'
,
body:
'Body of Custom Notification'
,
silent:
false
,
icon: path.join(__dirname,
'../assets/image.png'
),
hasReply:
true
,
timeoutType:
'never'
,
replyPlaceholder:
'Reply Here'
,
sound: path.join(__dirname,
'../assets/sound.mp3'
),
urgency:
'critical'
closeButtonText:
'Close Button'
actions: [ {
type:
'button'
,
text:
'Show Button'
}]
}
// Instantiating a new Notifications Object
// with custom Options
const customNotification =
new
Notification(options);
button.addEventListener(
'click'
,
function
(event) {
console.log(Notification.isSupported());
customNotification.show();
// customNotification.close();
});
// Instance Events for the new Notification Object
customNotification.addListener(
'click'
, () => {
console.log(
'Notification is Clicked'
);
});
customNotification.addListener(
'show'
, () => {
console.log(
'Notification is shown'
);
});
customNotification.addListener(
'close'
, () => {
console.log(
'Notification is Automatically Closed'
)
});
- customNotification.show() Instance Method to immediately show the Notification to the user. In case the Notification has been shown, dismisses the previous one and creates a new Notification with identical Options.
- customNotification.close() Instance Method to dismiss the Notification.
- Event: ‘click’ Event is Emitted, when user clicks on the Notification.
- Event: ‘show’ Event is Emitted, when notification is shown to the user.
- Event: ‘close’ Event is Emitted, when Notification is Closed. Not guaranteed to be emitted every time. Notification will automatically close irrespective of ‘timeoutType’ property.
- Output:
Instance events: Notification Module also provides two more Instance events which are supported by macOS only.
// Emitted when user clicks the reply button from // 'hasReply: true' property customNotification.addListener( 'reply' , (event, reply) => { console.log( 'Replied String is - ' , reply); }); // Emitted when the user clicks on any one action // defined in the actions:[{}] property customNotification.addListener( 'action' , (event, index) => { console.log( 'Index of the action clicked is - ' , index); }); |
Instance Properties: Electron Notification Module also Supports Instance Properties which can be set to the Notification Object. They can be used instead of Options and can also change pre-defined options when triggering Custom Notifications. A detailed list is given below.
customNotification.title = 'Title has been Changed' ; // Supported in macOS customNotification.subtitle = 'Subtitle of the Notification' ; customNotification.body = 'Body has been changed' ; // Supported in macOS customNotification.closeButtonText = 'Close Button' // Supported in macOS customNotification.hasReply = true ; // Supported in macOS customNotification.replyPlaceholder = 'Reply Placeholder' ; customNotification.silent = false ; // Supported in Linux customNotification.urgency = 'low' ; // Supported in Windows and Linux OS // This is a bug, as described above. customNotification.timeoutType= 'default' ; |