I am using electron 5.0.0 and I am trying to use windows JumpList and the Task category to quit my electron application.
{
program: process.execPath,
arguments: '--new-window',
iconPath: process.execPath,
iconIndex: 0,
title: 'New Window',
description: 'Create a new window'
}
])
I am trying to modify the example code from the electron website and i need to change the arguments
"arguments String - The command line arguments when program is executed."
I know windows has built in arguments like --new-window
So my question is does windows have something that will quit the application or do i need to make a custom argument if so how would i go about doing that
I want it to have the same functionality of skype see image
EDIT:
I tried using second-instance event but it does not seem to be called when the user clicks on the task
app.setUserTasks([
{
program: process.execPath,
arguments: '--force-quit',
iconPath: process.execPath,
iconIndex: 0,
title: 'Force Quit App',
description: 'This will close the app instead of minimizing it.'
}
])
app.on('second-instance', (e, argv)=>{
console.log("secinst" + argv)
if(argv === '--force-quit'){
win.destroy();
}
})
If you set tasks like this:
app.setUserTasks([
{
program: process.execPath,
arguments: '--force-quit',
iconPath: process.execPath,
iconIndex: 0,
title: 'Force Quit App',
description: 'This will close the app instead of minimizing it.'
}
])
When clicked, this will launch a new instance of your application with the command line argument --force-quit. You should handle that argument.
Your use case makes sense only if you allow a single instance of your application to be running. You need to get argv from the second-instance event.
const { app } = require('electron')
let myWindow = null
const gotTheLock = app.requestSingleInstanceLock()
if (!gotTheLock) {
app.quit()
} else {
app.on('second-instance', (event, argv, workingDirectory) => {
// Someone tried to run a second instance
const forceQuit = argv.indexOf("--force-quit") > -1;
if (forceQuit) app.quit()
})
// Create myWindow, load the rest of the app, etc...
app.on('ready', () => {
})
}
Related
In my React Native app, I'm using react-native-geolocation-service to track location changes. In iOS, the background location tracking works perfectly just by following these instructions. The problem arises in Android which causes the tracking to stop or work randomly when the app goes into background.
Let me emphasize that I don't want the location to be tracked when the app is fully closed. I ONLY want the tracking to work when the app is in the foreground (active) and background states.
I've followed the instructions given in the package's own example project to configure and start the tracking service and just like them I use react-native-foreground-service.
This is the function responsible for tracking the user location with the watchPosition method of Geolocation:
// Track location updates
export const getLocationUpdates = async (watchId, dispatch) => {
// Check if app has permissed
const hasPermission = await hasLocationPermission();
// Show no location modal and return if it hasn't
if (!hasPermission) {
dispatch(setAvailability(false));
return;
}
// Start the location foreground service if platform is Android
if (Platform.OS === 'android') {
await startForegroundService();
}
// Track and update the location refernce value without re-rendering
watchId.current = Geolocation.watchPosition(
position => {
// Hide no location modal
dispatch(setAvailability(true));
// Set coordinates
dispatch(
setCoordinates({
latitude: position?.coords.latitude,
longitude: position?.coords.longitude,
heading: position?.coords?.heading,
}),
);
},
error => {
// Show no location modal
dispatch(setAvailability(false));
},
{
accuracy: {
android: 'high',
ios: 'best',
},
distanceFilter: 100,
interval: 5000,
fastestInterval: 2000,
enableHighAccuracy: true,
forceRequestLocation: true,
showLocationDialog: true,
},
);
};
And this is how the foreground service of react-native-foreground-service is initialized:
// Start the foreground service and display a notification with the defined configuration
export const startForegroundService = async () => {
// Create a notification channel for the foreground service
// For Android 8+ the notification channel should be created before starting the foreground service
if (Platform.Version >= 26) {
await VIForegroundService.getInstance().createNotificationChannel({
id: 'locationChannel',
name: 'Location Tracking Channel',
description: 'Tracks location of user',
enableVibration: false,
});
}
// Start service
return VIForegroundService.getInstance().startService({
channelId: 'locationChannel',
id: 420,
title: 'Sample',
text: 'Tracking location updates',
icon: 'ic_launcher',
});
};
And this is how it's supposed to stop:
// Stop the foreground service
export const stopLocationUpdates = watchId => {
if (Platform.OS === 'android') {
VIForegroundService.getInstance()
.stopService()
.catch(err => {
Toast.show({
type: 'error',
text1: err,
});
});
}
// Stop watching for location updates
if (watchId.current !== null) {
Geolocation.clearWatch(watchId.current);
watchId.current = null;
}
};
The way I start the tracking is just when the Map screen mounts:
const watchId = useRef(null); // Location tracking reference value
const dispatch = useDispatch();
// Start the location foreground service and track user location upon screen mount
useMemo(() => {
getLocationUpdates(watchId, dispatch);
// Stop the service upon unmount
return () => stopLocationUpdates(watchId);
}, []);
I still haven't found a way to keep tracking the location when the app goes into background and have become frustrated with react-native-foreground-service since its service won't stop even after the app is fully closed (The problem is that the cleanup function of useMemo never gets called upon closing the app).
I have heard about react-native-background-geolocation (The free one) but don't know if it will still keep tracking after closing the app (A feature I DON'T want) and am trying my best not to use two different packages to handle the location service (react-native-background-geolocation and react-native-geolocation-service).
Another option would be Headless JS but even with that I'm not quite sure if it would stop tracking after the app is closed.
I welcome and appreciate any help that might guide me to a solution for this frustrating issue.
I want to create a simple test with Seleinium and Cucumber to login to my webapp and then verify that all is as it should be on the main page. All three tests immediately return true even before the page has been fetched, but the When step fails to find the input element because it begins before the get request has been completed. I'm new to this framework so I could be doing everything completely wrong.
const capabilities = {
browserName: 'IE',
browser_version: '11.0',
os: 'Windows',
os_version: '10',
resolution: '1024x768',
'browserstack.user': 'henry',
'browserstack.key': 'pass',
name: 'Bstack-[Node] Sample Test'
};
const driver = new webdriver.Builder()
.usingServer('http://hub-cloud.browserstack.com/wd/hub')
.withCapabilities(capabilities)
.build();
Given('The login page loads', () => {
driver.get('https://example.com/').then(() => {
driver.getTitle().then((title) => {
expect(title).to.eql('My webapp');
});
});
});
When('I login', () => {
driver.findElement(webdriver.By.name('username')).sendKeys('henry#example.com');
});
Then('I should see the dashboard', () => {
});
Feature: Login
Login to the Petasense webapp
Scenario: Scenario name
Given The login page loads
When I login
Then I should see the dashboard
Please use wait before performing any action. For e.g
WebDriverWait wait = new WebDriverWait(driver, 10);
wait.until(ExpectedConditions.or(
ExpectedConditions.visibilityOfElementLocated(By.id("id1")),
ExpectedConditions.visibilityOfElementLocated(By.id("id2"))
));
Or use sleep before next step. e.g
Thread.sleep
Sentry by defaults has integration for console.log to make it part of breadcrumbs:
Link: Import name: Sentry.Integrations.Console
How can we make it to work for bunyan logger as well, like:
const koa = require('koa');
const app = new koa();
const bunyan = require('bunyan');
const log = bunyan.createLogger({
name: 'app',
..... other settings go here ....
});
const Sentry = require('#sentry/node');
Sentry.init({
dsn: MY_DSN_HERE,
integrations: integrations => {
// should anything be handled here & how?
return [...integrations];
},
release: 'xxxx-xx-xx'
});
app.on('error', (err) => {
Sentry.captureException(err);
});
// I am trying all to be part of sentry breadcrumbs
// but only console.log('foo'); is working
console.log('foo');
log.info('bar');
log.warn('baz');
log.debug('any');
log.error('many');
throw new Error('help!');
P.S. I have already tried bunyan-sentry-stream but no success with #sentry/node, it just pushes entries instead of treating them as breadcrumbs.
Bunyan supports custom streams, and those streams are just function calls. See https://github.com/trentm/node-bunyan#streams
Below is an example custom stream that simply writes to the console. It would be straight forward to use this example to instead write to the Sentry module, likely calling Sentry.addBreadcrumb({}) or similar function.
Please note though that the variable record in my example below is a JSON string, so you would likely want to parse it to get the log level, message, and other data out of it for submission to Sentry.
{
level: 'debug',
stream:
(function () {
return {
write: function(record) {
console.log('Hello: ' + record);
}
}
})()
}
I want to learn and develop a desktop app by using electron + rxdb.
My file structure:
main.js (the main process of electron)
/js-server/db.js (all about rxdb database, include creation)
/js-client/ui.js (renderer process of electron)
index.html (html home page)
main.js code:
const electron = require('electron')
const dbjs = require('./js-server/db.js')
const {ipcMain} = require('electron')
ipcMain.on('search-person', (event, userInput) => {
event.returnValue = dbjs.searchPerson(userInput);
})
db.js code:
var rxdb = require('rxdb');
var rxjs = require('rxjs');
rxdb.plugin(require('pouchdb-adapter-idb'));
const personSchema = {
title: 'person schema',
description: 'describes a single person',
version: 0,
type: 'object',
properties: {
Name: {type: 'string',primary: true},
Age: {type: 'string'},
},
required: ['Age']
};
var pdb;
rxdb.create({
name: 'persondb',
password: '123456789',
adapter: 'idb',
multiInstance: false
}).then(function(db) {
pdb = db;
return pdb.collection({name: 'persons', schema: personSchema})
});
function searchPerson(userInput) {
pdb.persons.findOne().where('Name').eq(userInput)
.exec().then(function(doc){return doc.Age});
}
module.exports = {
searchPerson: searchPerson
}
ui.js code:
const {ipcRenderer} = require('electron');
function getFormValue() {
let userInput = document.getElementById('searchbox').value;
displayResults(ipcRenderer.sendSync("search-person",userInput));
document.getElementById('searchbox').value = "";
}
Whenever I run this app, I got these errors:
(node:6084) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 2): Error: RxError:
RxDatabase.create(): Adapter not added. (I am sure I've installed the pouched-adapter-idb module successfully)
Type error, cannot read property "persons" of undefined. (this error pops out when I search and hit enter to the form in index.html)
I am new to programming, especially js, I've been stuck on these errors for a week, just can't get it to work. Any help? Thanks.
The problem is that this line is in main.js:
const dbjs = require('./js-server/db.js')
Why? Because you're requiring RxDB inside the main process and using the IndexedDB adapter. IndexedDB is a browser API and thus can only be used in a rendering process. In Electron, the main process is a pure Node/Electron environment with no access to the Chromium API's.
Option #1
If you want to keep your database in a separate thread then consider spawning a new hidden browser window:
import {BrowserWindow} from 'electron'
const dbWindow = new BrowserWindow({..., show: false})
And then use IPC to communicate between the two windows similarly to how you have already done.
Option #2
Use a levelDB adapter that only requires NodeJS API's so you can keep your database in the main process.
I used the electron-quick-start to create an Electron app, and I want the only native menu to show to be the 'Edit' menu, with the usual suspects inside.
However, after searching and exhausting all relevant Google results for 'electron menu not working', I'm at a loss.
My current main.js file:
const {app, Menu, BrowserWindow} = require('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 mainWindow;
app.setName('mathulator');
function createWindow () {
// Create the browser window.
mainWindow = new BrowserWindow({width: 900, height: 550})
// and load the index.html of the app.
mainWindow.loadURL(`file://${__dirname}/index.html`)
// 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.
const template = [
{
label: 'Mathulator',
submenu: [
{
role: 'quit'
}
]
},
{
label: 'Edit',
submenu: [
{
role: 'undo'
},
{
role: 'redo'
},
{
type: 'separator'
},
{
role: 'cut'
},
{
role: 'copy'
},
{
role: 'paste'
},
{
role: 'pasteandmatchstyle'
},
{
role: 'delete'
},
{
role: 'selectall'
}
]
}
]
mainWindow.setMenu(Menu.buildFromTemplate(template))
// Emitted when the window is closed.
mainWindow.on('closed', function () {
// 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.
mainWindow = 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', function () {
// 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', function () {
// 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've also packaged it up with electron-packager, to no avail.
I'm running it in the main.js file, which from what I can gather from the masses of either vague or convoluted information around the web, is the main process and therefore one in which I should create the menus.
I also tried doing it in render.js, which I saw suggested. To no avail. It'll either show up with the default electron-quick-start menu, or just a simple menu named after the app, containing one item labelled 'Quit'.
What might I be doing wrong, and what might I have misunderstood from the available information?
Edit: I actually attached the wrong file, tried using Menu.setApplicationMenu() the first time, like so:
const {app, Menu, BrowserWindow} = require('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 mainWindow;
app.setName('mathulator');
function createWindow () {
// Create the browser window.
mainWindow = new BrowserWindow({width: 900, height: 550});
// and load the index.html of the app.
mainWindow.loadURL(`file://${__dirname}/index.html`);
// Emitted when the window is closed.
mainWindow.on('closed', function () {
// 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.
mainWindow = 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', function () {
// 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', function () {
// 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();
}
})
const template = [
{
label: 'Mathulator',
submenu: [
{
role: 'quit'
}
]
},
{
label: 'Edit',
submenu: [
{
role: 'undo'
},
{
role: 'redo'
},
{
type: 'separator'
},
{
role: 'cut'
},
{
role: 'copy'
},
{
role: 'paste'
},
{
role: 'pasteandmatchstyle'
},
{
role: 'delete'
},
{
role: 'selectall'
}
]
}
];
Menu.setApplicationMenu(Menu.buildFromTemplate(template));
The issue here is that BrowserWindow.setMenu() is only available on Windows and Linux. On macOS you should use Menu.setApplicationMenu().
Note that on OSX the menu is not on the window itself but on the top of dosktop.
I lost bunch of time trying to troubleshoot why it was not showing up.
As #Vadim Macagon stated in comment, make sure that the call to Menu.setApplicationMenu() is in createWindow(). For me it fixed the problem.
maybe you set LSUIElement to 1, that means an agent app, that is, an app that should not appear in the Dock. Change the LSUIElement to 0, the build app's menu will show up.
electron build config
mac: {
icon: 'build/icons/icon.icons',
extendInfo: {
LSUIElement: 0
}
}
detail of LSUIElement is here
https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/LaunchServicesKeys.html#//apple_ref/doc/uid/20001431-108256