globalShortcut from electron will disable the original keypress - javascript

I am trying to intercept Ctrl+C and Ctrl+V commands and get the value from the clipboard in Electron.
I tried doing it using GlobalShortcut from electron
const ret = globalShortcut.register('CommandOrControl+X', () => {
console.log('CommandOrControl+X is pressed')
})
This is intercepting the keyevent but it stops the original keyevent from happening,
One way is to intercept using above code and then manually execute the key event from it.
Can anyone please help me with what can be done in this case?

There also is a small library called electron-localshortcut that enables local scope shortcuts in Electron. When the window is inactive, the referenced shortcuts are disabled and given back to Windows' control.
Use like this in your main.js:
const electronLocalshortcut = require('electron-localshortcut');
electronLocalshortcut.register(mainWindow, 'STRG+C', () => {
// Copy to Clipboard
});

Related

Pass a puppeteer based client object to onClick button inside a puppeteer page

I have a non-common use case I'd like to implement. I found an open source project that uses puppeteer to automate action within whatsapp web. It provides a client object with an API to listen to events or do some actions such as
client.on('message_create', (msg) => {
client.sendMessage(number, text);
});
I'm not so proficient with JS, but what I understand is that it launches a real instance of whatsapp web and then interacts with it.
What I want to do is - once whatsapp web is loaded, add a div with buttons that would interact with my wrapper app functions and do automated stuff.
I did manage to add external button to the UI and set it's onClick, I done it via the the page.evaluate function, something like that:
await client.puppeteerPage.evaluate(async () => {
let btn = document.querySelector('#updateIcButton');
btn.addEventListener("click", async ()=>{
// Do some action with the client, however - client is undefined here
});
});
So far so good, but now comes the problem - what I want to do is to interact with the client functions inside the click listener, which I currently found impossible to do since inside the 'evaluate' function which is the only way I found to inject buttons, the client from the upper scope is undefined... I couldn't find a way to pass the client object as it creates a cyclic dependency or something if I pass as parameter.. Also tried other stuff such as calling exposeFunction or addScriptTag but nothing seem to be working.
I'm not sure it's possible anyhow, as although I'm not so proficients with JS and web dev, I understand that the web page doesn't "know" or can't interact with the puppeteer application wrapping it.
I'd appreciate if someone can please suggest a way to solve or another possible way to add UI that can interact with my puppeteer application and do automated stuff within the page instance.
Appreciate your help!
More of my source code:
client.on('ready', async () => {
await client.pupPage.exposeFunction("sendMessage", client.sendMessage);
client.pupPage.evaluate((divHtml) => {
//here I have logic to load a div container with a single button
//Once the div is added, I'm querying the button ID and trying to set it's onClick to interact with the client from above
let btn = document.querySelector('#updateIcButton');
btn.addEventListener("click", async ()=>{
// Do some action with the client
sendMessage("phonenumber","sometext"); // trying to call the func I exposed
});
}, divHtml);
});

Simulating keyboard events with JavaScript

How to simulate typing of some text in a contenteditable element?
I need to simulate everything as a user will events will do for test purposes.
I can fire an event with:
node.dispatchEvent(new KeyboardEvent('keydown', {key: 'A'}))
node.dispatchEvent(new KeyboardEvent('keyup', {key: 'A'}))
But it will not print A. So I have to use API:
node.innerHTML += 'A'
But the cursor will be in a different place, so I need to create a range.
let r = document.createRange()
r.selectNodeContents(editor)
r.collapse(false)
let s = window.getSelection()!
s.removeAllRanges()
s.addRange(r)
What about simulating arrows? How to simulate arrow up? Maybe there is some library to do this?
Testing Library is a great option for simulating user interactions. It can be paired with a companion library, user-event, to simulate user input such as click, dblClick, arrow up/down, tab, and much more. Here's an example of simulating user input in a text field:
import { screen } from '#testing-library/dom';
import userEvent from '#testing-library/user-event';
test('type', () => {
document.body.innerHTML = `<textarea />`;
// type 'Hello' followed by the enter key, followed by 'World!' into the textarea
userEvent.type(screen.getByRole('textbox'), 'Hello,{enter}World!');
// We expect that textarea to now have the given value
expect(screen.getByRole('textbox')).toHaveValue('Hello,\nWorld!');
});
You can delay the input, or use the skipClick option to input before clicking the element (in the case where the element auto-focuses, for example).
There are tons of examples here: https://testing-library.com/docs/ecosystem-user-event/. They also have wrappers for various frameworks such as react, angular, and puppeteer. So depending on what framework you use (or just vanilla js), you can:
Create your page/component
Simulate user input events with the user-event library
Assert certain conditions that you expect to be true
I also really like that the library makes it easy to mock server requests so I can fully test a component without worrying about its internals and how it's structured.

How to make page search on electron like in Chrome or VS Code or Firefox? [duplicate]

Does the Electron application framework have built-in text search?
The quick-start application doesn't provide any apparent search functionality (e.g. using Ctrl-F or from the menu options). I would have expected this to be a BrowserWindow option (or an option of its WebContents), but I don't see anything helpful in the docs.
I know this is an old thread, but might still be relevant for people out there.
Had the same problem, and first fixed by using electron-in-page-search, but this component doesn't work properly with Electron 2 or greater.
Then finally found electron-find resolved my problem. Using with Electron 4.
You just add the component to your project:
npm install electron-find --save
Add a global shortcut in your Electron main process to send an event to the renderer in a ctrl+f:
globalShortcut.register('CommandOrControl+F', () => {
window.webContents.send('on-find');
});
And then you can add this to your page (the renderer process)
const remote = require('electron').remote;
const FindInPage = require('electron-find').FindInPage;
let findInPage = new FindInPage(remote.getCurrentWebContents());
ipcRenderer.on('on-find', (e, args) => {
findInPage.openFindWindow()
})
Hope that helps.
Try webContents.findInPage just added in the latest version.
There is an issue with the solution Robson Hermes offered. globalShortcut is, by definition, global, so the shortcut will be detected even when the app is not focused. This will result in the Ctrl+F shortcut being "stolen" from everywhere else.
I have found no ideal solution (see this issue on the electron repository), but a hacky one can be achieved by doing what Robson said and adding
win.on('focus', () => {
globalShortcut.register('CommandOrControl+F', () => windows.main.send('on-find'))
})
win.on('blur', () => {
globalShortcut.unregister('CommandOrControl+F')
}
Note that as seen here, this is not ideal and can lead to several issues:
Other applications can get a lock on the shortcut when you lose focus, i.e. the shortcut will magically stop working when you switch back to the app later.
Some apps can appear on screen without taking focus (spotlight I believe has this behavior) and during the app's appearance the shortcuts will still be captured by your application.
There's also gonna be those weird one in a thousand situations where somehow you switch focus and the shortcut is not removed.
Instead of using global shortcuts , use Accelerators ( normal Keyboard shortcut )
{
label : 'help',
click : function(){.
electron.shell.openExternal('http://....').
},
accelerator : 'CmdOrCtrl+ Shift + H'
}
The above shown is just an example of How to use accelerator

Electron does not listen keydown event

I am a backend developer who got a little project to fix it.
So my boss gives me an electron project which runs on touch devices.
I know that I can listen any key events in Javascript if I use the document object, but in electron it does not work, it says the docuemnt cannot be found.
So implemented this when I or other support guy press the F12 button then the dev tools be rendered out in the electron app.
mainWindow = new BrowserWindow({
'web-preferences': {'web-security': false}
});
mainWindow.onkeydown = function (e) {
console.log("Key down");
if (e.which === 123) {
console.log("Key is F12");
mainWindow.webContents.openDevTools();
}
};
But this code is not working to me. I have no idea how I can listen the F12 button is pressed.
Unfortunately I cannot render out button to the UI which can show the devtools. Because of the customers mustn't press it.
Sometimes I need to see the realtime console tab in devtools on the device.
There is a known issue in Electron ( which has lately been marked as wontfix ) that prevents the usual approach to catch key events using the traditional JS approach.
There also is a small library called electron-localshortcut that circumvents this issue by hijacking the Electron global shortcuts API when the window is active.
Use like this in your main.js:
const electronLocalshortcut = require('electron-localshortcut');
electronLocalshortcut.register(mainWindow, 'F12', () => {
// Open DevTools
});
Without additional libraries you can use "globalShortcut" of electron
const { app, BrowserWindow, globalShortcut } = require("electron");
globalShortcut.register("CmdOrCtrl+F12", () => {
mainWindow.isFocused() && mainWindow.webContents.toggleDevTools();
});
I think F12 is preserved so I use ctrl+f12 which is not far off
You can use the library mousetrap to add global short cut, because it can be installed through node and could bypass the problem of electron mentioned in the accepted answer.
A code example in the render process would be:
var Mousetrap = require('mousetrap');
Mousetrap.bind('4', function() { console.log('4'); });

Firefox SDK : Listen for a change in non addon specific about:config entry

I am trying to listen for changes to settings in firefox's about:config that the user could have changed while my addon is running. The settings in question are part of the browser and not created by my addon.
I can read and set them manually when the user has used my addon with no problems using the "preferences/service" module, but I want to be able to make the appropriate changes in my addon if the user has changed a setting in about config independently of my addon.
The "simple-prefs" module provides a listener but that is only for settings specific to your application, like "extension.myaddon.mypreference" where as the settings I need to watch are like "network.someoptionhere"
If someone could point me in the right direction as to how I would go about this I would greatly appreciate it.
You'll need to use some XPCOM, namely nsIPrefService/nsIPrefBranch (e.g. via Services.jsm). This is the same stuff that preferences/service and simple-prefs wraps.
Here is a full example:
const {Ci, Cu} = require("chrome");
const {Services} = Cu.import("resource://gre/modules/Services.jsm", {});
function observe(subject, topic, data) {
// instanceof actually also "casts" subject
if (!(subject instanceof Ci.nsIPrefBranch)) {
return;
}
console.error(subject.root, "has a value of", subject.getIntPref(""), "now");
}
var branch = Services.prefs.getBranch("network.http.max-connections")
branch.addObserver("", observe, false);
exports.onUnload = function() {
// Need to remove our observer again! This isn't automatic and will leak
// otherwise.
branch.removeObserver("", observe);
};

Categories

Resources