Home > Enterprise >  How to execute node command when some event occur in electron js window
How to execute node command when some event occur in electron js window

Time:03-31

I am making a electron js application which have two buttons. I have assigned click event listners on both of them. What I want to do uppon someone click them is to increase or decrease brightness respectively.

I have build a function in node.js that does increase the brighthness if we run using sudo command.

Here is the function:

let fs = require("fs");

function inc() {
  var data = fs.readFileSync(
    "/sys/class/backlight/amdgpu_bl1/brightness",
    "utf-8"
  );

  var newData = parseInt(data)   10;
  if (newData > 255) {
    newData = 255;
  } else if (newData < 0) {
    newData = 0;
  }
  newData = newData.toString();

  fs.writeFileSync(
    "/sys/class/backlight/amdgpu_bl1/brightness",
    newData,
    "utf-8"
  );
}

The index.html code is:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <title>Clock App</title>
    <link rel="stylesheet" href="style.css" />
  </head>
  <body>
    <button onclick="incBright()"> </button>
    <button onclick="decBright()">-</button>
    <script src="script.js"></script>
  </body>
</html>

I want to execute the inc() function when someone click on the' ' button! elctron js app window

Can someone tell me is that even possible to do that or not.

I am using linux

I don't have any idea about this stuff

CodePudding user response:

To communicate between the main thread and render thread(s) you will want to become familiar with Electron's Inter-Process Communication and Context Isolation.

Additionally, you will want to become familiar with Electron's ipcRenderer and ipcMain modules.


On brightness adjustments, you will want to communicate that adjustment to the main thread through the use of IPC. To safely communicate to the main thread, one should use a preload.js script.

The preload.js script is integrated into the construction of your application window, allowing permissible actions to take place.

Below is a preload script that uses "channel names" to convey information to and from the main thread and render thread(s).

Is a good design decision not to implement concrete functions directly within your preload.js script. Instead, use you preload script as a gate keeper to only allow messages between threads. This will greatly simplify your preload script and separate your concerns.

Below is an example of a preload script that will fulfill your requirements, noting the use of the channel names brightness:increment and brightness:decrement. You can rename these channel names to whatever you like.

preload.js (main thread)

// Import the necessary Electron components.
const contextBridge = require('electron').contextBridge;
const ipcRenderer = require('electron').ipcRenderer;

// White-listed channels.
const ipc = {
    'render': {
        // From render to main.
        'send': [
            'brightness:increment',
            'brightness:decrement'
        ],
        // From main to render.
        'receive': [],
        // From render to main and back again.
        'sendReceive': []
    }
};

// Exposed protected methods in the render process.
contextBridge.exposeInMainWorld(
    // Allowed 'ipcRenderer' methods.
    'ipcRender', {
        // From render to main.
        send: (channel, args) => {
            let validChannels = ipc.render.send;
            if (validChannels.includes(channel)) {
                ipcRenderer.send(channel, args);
            }
        },
        // From main to render.
        receive: (channel, listener) => {
            let validChannels = ipc.render.receive;
            if (validChannels.includes(channel)) {
                // Deliberately strip event as it includes `sender`.
                ipcRenderer.on(channel, (event, ...args) => listener(...args));
            }
        },
        // From render to main and back again.
        invoke: (channel, args) => {
            let validChannels = ipc.render.sendReceive;
            if (validChannels.includes(channel)) {
                return ipcRenderer.invoke(channel, args);
            }
        }
    }
);

Now that our preload script is configured, let's utilise it in the construction of our application window.

Additionally, let's listen on these message channels, and when detected, call our adjustBrightness function.

main.js (main thread)

const electronApp = require('electron').app;
const electronBrowserWindow = require('electron').BrowserWindow;
const electronIpcMain = require('electron').ipcMain;

const nodeFs = require("fs");
const nodePath = require("path");

// Prevent garbage collection
let window;

function createWindow() {
    const window = new electronBrowserWindow({
        x: 0,
        y: 0,
        width: 800,
        height: 600,
        show: false,
        webPreferences: {
            nodeIntegration: false, // For safety, let's disable Node integration
            contextIsolation: true, // For safety, let's enable context isolation
            preload: nodePath.join(__dirname, 'preload.js') // Let's use our preload script
        }
    });

    window.loadFile('index.html')
        .then(() => { window.show(); });

    return window;
}

electronApp.on('ready', () => {
    window = createWindow();
});

electronApp.on('window-all-closed', () => {
    if (process.platform !== 'darwin') {
        electronApp.quit();
    }
});

electronApp.on('activate', () => {
    if (electronBrowserWindow.getAllWindows().length === 0) {
        createWindow();
    }
});

// Let's listen for messages to increment or decrement the brightness
electronIpcMain.on('brightness:increment', () => {
    adjustBrightness(10);
})

electronIpcMain.on('brightness:decrement', () => {
    adjustBrightness(-10);
})

// Function to adjust screen brightness
function adjustBrightness(adjustment) {
    let data = nodeFs.readFileSync('/sys/class/backlight/amdgpu_bl1/brightness', 'utf-8');

    let newData = parseInt(data)   adjustment;

    if (newData > 255) {
        newData = 255;
    } else if (newData < 0) {
        newData = 0;
    }

    newData = newData.toString();

    nodeFs.writeFileSync('/sys/class/backlight/amdgpu_bl1/brightness', newData, 'utf-8');
}

Lastly, let's make sure our rendered html sends the messages out to the main thread when the corresponding buttons are clicked.

index.html (render thread)

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Clock App</title>
    </head>

    <body>
        <input type="button" id="incBrightness" value=" ">
        <input type="button" id="decBrightness" value="-">
    </body>

    <script>
        document.getElementById('incBrightness').addEventListener('click', () => {
            window.ipcRender.send('brightness:increment');
        })

        document.getElementById('decBrightness').addEventListener('click', () => {
            window.ipcRender.send('brightness:decrement');
        })
    </script>
</html>
  • Related