Electron + Vue tray wrong icon path - vue.js

I'm trying to create a Windows applications using Electron and Vue. I want to send the application to the Tray and show an icon to maximize it again when clicked. It works fine in DEV but when I build the app, the Tray icon is not working.
The app it's executing, but when minimized the tray is not showing and there is not option to open it again (need to kill the process).
This is the code I'm trying to use:
app.on("ready", async () => {
if (isDevelopment && !process.env.IS_TEST) {
try {
await installExtension(VUEJS_DEVTOOLS);
} catch (e) {
console.error("Vue Devtools failed to install:", e.toString());
}
}
createWindow();
createTray()
});
const createTray = () => {
const tray = new Tray(resolve(process.resourcesPath, '\\resources\\homeico.ico'))
const contextMenu = Menu.buildFromTemplate([
{
label: 'Show App', click: function () {
app.show()
}
},
{
label: 'Quit', click: function () {
app.isQuiting = true
app.quit()
}
}
])
tray.setToolTip('This is my application.')
tray.setContextMenu(contextMenu)
tray.on('click', () => {
console.log('clicked')
})
}
And in my vue.config.js:
pluginOptions: {
electronBuilder: {
nodeIntegration: true,
builderOptions: {
"extraResources": [
{
"from": "extraResources",
"to": "resources",
"filter": [
"**/*"
]
}
]
}
},
},
The resolve(process.resourcesPath, '\resources\homeico.ico') line is pointing to a existing file, I'm printing this route in the App and I can open it in my Windows Explorer, but when I want to show the Image in the app, I can see next error in the DevTools:
Not allowed to load local resource: file:///C:/Users/mysUser/AppData/Local/Programs/business-config-tool/resources/resources/homeico.ico
The path is accesible, but not in the App.
What's the correct way to configure the path to the icon? there is another path I can configure for assets? I also tried with __dirname and other icon formats (ico, png..)
Thank you.

I ran into the same issue. I searched for a solution for hours, and I finally found one.
This solution is made for app using electron-vue (I personally used this Vue Cli electron plugin). And I tested it on Windows only.
The Tray must be initialised with an icon Path, wich needs be different wether you are running a built version of your app (yarn electron:build), or serving your app (yarn electron:serve).
I am using a function that I called isServeMode, wich basically tells me if I am using the serve mode or the buid mode. Here is what the function looks like :
// utils.js file
const isServeMode = () => {
return process.env.WEBPACK_DEV_SERVER_URL
}
You don't need to create this function, but it might be usefull somewhere else in your app so I suggest you to put it in a file that you can import from anywhere in your app. In my case, I created a utils.js file where I write those functions.
Then, put your tray icon in the public folder, it can not work if you put the icon in the src/assets folder, since we have to access it from the Node environnement and not from Vue. In my case, I put my icon in public/tray/icon.png.
Finally, we can use the electron Tray with Electron vue like this
import { Tray } from "electron"
import path from "path"
import { isServeMode } from "./utils" // Path depends on where you wrote your function
// Some Electron code...
let tray
createTray = () => {
const iconPath = isServeMode()
? path.join(__dirname, "/bundled/tray/icon.png")
: path.join(__dirname, "/tray/icon.png")
tray = new Tray(iconPath)
}
I will soon release a new version of my Unlighter app, wich is an electron-vue app that will include a Tray example. Feel free to take a look at this "real world app example" if you're interested.

Related

React Native Fetch Blob/React Native Blob Util Fail in Production but not in Developer time

I am trying to download a pdf generated through an own api that worked normally for me until yesterday, since then it has stopped working without any modification. Reviewing in developer mode through the metro everything seems to work correctly without any problems (I download the pdf normally), but when deploying the application in the playstore it closes unexpectedly, leaving me without knowing why this happens.
First I was using the React Native Fetch Blob, then I used React Native Blob Util hoping it would solve the problem but it keeps happening. Do you guys have any ideas for why does this happen?
The PDF file download this function:
const generarReciboPdf = async (datosDeuda:FormularioScreenParams,formaPago:ReactText,nroCheque?:string) =>{
const{config,fs} = ReactNativeBlobUtil
if (formaPago === 4 && (nroCheque == ""|| undefined)) {
return console.log('debe llenar todos los campos');
}
const { DownloadDir } = fs.dirs;
const token = await AsyncStorage.getItem('token');
let datosDeudaCompleto= {
...datosDeuda,
forma_pago:formaPago,
nro_cheque:nroCheque
}
let url = 'https://sys.arco.com.py/api/appRecibos/generarReciboPdf/'+JSON.stringify(datosDeudaCompleto)
// return console.log(url);
const options = {
fileCache: true,
addAndroidDownloads: {
useDownloadManager: true, // true will use native manager and be shown on notification bar.
notification: true,
mime:'application/pdf',
path: `${DownloadDir}/recibo_${datosDeuda.mes_deuda.replace(/ /g, "")}_${datosDeuda.razon_social.replace(/ /g, "")}.pdf`,
description: 'Downloading.',
},
};
config(options).fetch('GET', url,{Authorization :'Bearer '+token}).then((res) => {
console.log('se imprimio correctamte el pdf');
setErrorPdf(1)
}).catch((error)=>{
console.log(error);
setErrorPdf(-1);
});
}
Also, this error appears in Play Console: "PlayConsole Error Image".
PlayConsole Error Image

How to turn off console.info messages from Nuxt server?

I am running tests and receive unnecessary console.info texts in terminal, I would like to get rid of:
console.info
Download the Vue Devtools extension for a better development experience:
https://github.com/vuejs/vue-devtools
at node_modules/vue/dist/vue.common.dev.js:9051:47
console.info
You are running Vue in development mode.
Make sure to turn on production mode when deploying for production.
See more tips at https://vuejs.org/guide/deployment.html
at node_modules/vue/dist/vue.common.dev.js:9060:45
const { Nuxt } = require('nuxt')
const nuxtConfig = require('../../../../nuxt.config.js')
let nuxt = null
beforeAll(async () => {
nuxt = new Nuxt({
...nuxtConfig,
buildDir: constants.buildDir
})
await nuxt.server.listen(constants.port, 'localhost')
}, 300000)
I've tried to put vue.config silent property in various places in code above, but also into nuxt.config.js, but I got no luck doing so. I've tried this snippet: https://nuxtjs.org/docs/2.x/configuration-glossary/configuration-vue-config/
export default {
vue: {
config: {
productionTip: true,
devtools: false
}
}
}
How to turn off console.info messages?
You could right click on the message in your devtools console and go with Hide messages from vue.runtime.esm.js. It will hide it from your console thanks to a filter. Do not solves the real problem, but a nice and quick fix.
Pretty much as here: https://superuser.com/a/995289/850722

Capacitor / Ionic / Vue Local Notification eventlistener

I'm trying to get Local Notifications working in an Ionic Vue app (using capacitor).
I did get scheduling notifications working, but now i want to listen to clicks on the notification.
in main.js I bind LocalNotifications to this.$LocalNotifications:
import { Plugins } from '#capacitor/core';
const { LocalNotifications } = Plugins;
Vue.prototype.$LocalNotifications = LocalNotifications;
in my Root component App I have this:
created() {
console.log('Created!')
document.addEventListener('deviceready', () => {
console.log('ready');
this.$LocalNotifications.addListener('localNotificationReceived', (notification) => {
console.log('Notification action received', notification);
});
}, false);
}
When I build and run on the ios-emulator, i get the following output in my log:
APP ACTIVE
To Native Cordova -> Badge load Badge1248600129 ["options": []]
⚡️ [log] - onscript loading complete
To Native Cordova -> Device getDeviceInfo Device1248600130 ["options": []]
⚡️ To Native -> Storage get 90127150
⚡️ TO JS {"value":null}
⚡️ [log] - Created!
To Native Cordova -> LocalNotification launch LocalNotification1248600131 ["options": []]
To Native Cordova -> LocalNotification ready INVALID ["options": []]
⚡️ To Native -> LocalNotifications addListener ⚡️ [log] - ready
90127151
⚡️ WebView loaded
⚡️ To Native -> App addListener 90127152
When I schedule a Notification, the notification does show up, but I think something doesn't go quite well when i'm adding the listener:
INVALID ["options":[]]
Does anyone have any idea how to solve this?
Or does anyone have a code example of working notifications in an Ionic Vue app?
Kind regards,
Bram
To sum up:
You should use localNotificationActionPerformed instead of localNotificationReceived. The latter is called when notifications are displayed, while the other is listening to actions performed on a notification (as it's stated in the docs), that of course includes clicking / tapping on it.
So your code would look like this:
this.$LocalNotifications.addListener('localNotificationActionPerformed', (notification) => {
console.log('Notification action received', notification.actionId);
});
...which would output "tap". Since you did write 'Notification action received', I assume you wanted to get the action, so I added .actionId after 'notification', which only by itself would be logged as [object Object] or as the object tree.
You also asked for code example, so here it comes:
// 1.
import { LocalNotifications } from '#capacitor/local-notifications';
// 2.
await LocalNotifications.requestPermissions();
// 3.
await LocalNotifications.registerActionTypes({
types: [
{
id: 'your_choice',
actions: [
{
id: 'dismiss',
title: 'Dismiss',
destructive: true
},
{
id: 'open',
title: 'Open app'
},
{
id: 'respond',
title: 'Respond',
input: true
}
]
}
]
});
// 4.
LocalNotifications.schedule({
notifications: [
{
id: 1,
title: 'Sample title',
body: 'Sample body',
actionTypeId: 'your_choice'
}
]
});
// 5.
LocalNotifications.addListener('localNotificationActionPerformed', (notification) => {
console.log(`Notification ${notification.notification.title} was ${notification.actionId}ed.`);
});
1: Since your question, plugins have been placed into their own npm packages, so one needs to install #capacitor/local-notifications and import from there.
2: You should make sure that notifications are allowed, ask for permissions if needed.
3: Tapping was your question's topic, but you can define a lot more than that.
4: This is how you actually create & send a notification at once.
5: Logs "Notification Sample title was taped / opened / dismissed / responded.", according to the given action (but not always according to grammar).
Finally, if someone's just getting into local notifications, check out the really nice documentation on what else (a whole lot more!) can be done and also watching this video might give one a head start. At least that's what I did.

How do I display the captcha icon only on certain pages (VUE reCAPTCHA-v3)?

I use this package : https://www.npmjs.com/package/vue-recaptcha-v3
I add on my main.js :
import { VueReCaptcha } from 'vue-recaptcha-v3'
Vue.use(VueReCaptcha, { siteKey: 'xxxxxxx' })
I add this code :
await this.$recaptcha('login').then((token) => {
recaptcha = token
})
to my component to get token from google recapchta
My problem is the captcha icon in the lower right corner appears on all pages
I want it to only appear in certain components
Maybe I must to change this : Vue.use(VueReCaptcha, { siteKey: 'xxxxxxxxxxxxxxxxx' }). Seems it still mounting to Vue.use. I want to mount to a certain component instead of vue root instance
How can I solve this problem?
Update
I try like this :
Vue.use(VueReCaptcha, {
siteKey: 'xxxxxxx',
loaderOptions: {
useRecaptchaNet: true,
autoHideBadge: true
}
})
It hides the badge. I want the badge to still appear. But only on 1 page, the registration page. How can I do it?
I've had the same issue while using the npm package, it's pretty annoying.
At the end of the day, I've decided not to use the package & follow Google's documentation.
This line here :
grecaptcha.execute('_reCAPTCHA_site_key_', {action: 'login'}).then(function(token) {
recaptcha = token
})
Is equivalent to this line here from the npm package :
this.$recaptcha('login').then((token) => {
recaptcha = token
})
You just need to add this line into your < head > for recaptcha to work :
<script src="https://www.google.com/recaptcha/api.js?render=_reCAPTCHA_site_key"></script>
But as soon the script tag is in your < head >, you will be facing the same issue of it showing on every page.
The hack is that you only insert it into the < head > on components that you need.
There are ways to do this but I ended up referencing this.
You can put it in the methods of your component & call the method when the component is loaded.
That way it will only show up on the pages that you need it to.
in main.js set autoHideBadge true:
import { VueReCaptcha } from 'vue-recaptcha-v3'
Vue.use(VueReCaptcha, { siteKey: 'your site key',
loaderOptions:{autoHideBadge: true }})
in every page you want to show the badge you can show the badge in mounted,
for some reasons until a few seconds after mounted event this.$recaptchaInstance is null and you cant use it, so I use a timeout to showing the badge 5 second after page load in mounted.
mounted(){
setTimeout(()=>{
const recaptcha = this.$recaptchaInstance
recaptcha.showBadge()
},5000)
},
when you show it you have to hide it again in the same page.
beforeDestroy() {
const recaptcha = this.$recaptchaInstance
recaptcha.hideBadge()
},
If you are using composition API setup this is what you need:
const reCaptchaIn = useReCaptcha().instance
onMounted(() => {
setTimeout(() => {
reCaptchaIn.value.showBadge()
}, 3000)
})
Just use this code:
const recaptcha = this.$recaptchaInstance
// Hide reCAPTCHA badge:
recaptcha.value.hideBadge()
// Show reCAPTCHA badge:
recaptcha.value.showBadge()
vue-recaptcha-v3 npm
I stumbled upon this incredibly simple answer. It is excellent especially if you wish to hide the badge from all your pages. You can perhaps use scoped css to hide on some pages as well.
.grecaptcha-badge { visibility: hidden; }
You can read the post here

How to add a in-app browser in React Native (Expo)

How to open a web browser in expo rather than using the expo browser.I want open the browser in inside the app.
you can use the following library react-native-inappbrowser
follow the installation from the github page
import { Linking } from 'react-native'
import InAppBrowser from 'react-native-inappbrowser-reborn'
...
async openLink() {
try {
const url = 'https://www.google.com'
if (await InAppBrowser.isAvailable()) {
const result = await InAppBrowser.open(url, {
// iOS Properties
dismissButtonStyle: 'cancel',
preferredBarTintColor: '#453AA4',
preferredControlTintColor: 'white',
readerMode: false,
animated: true,
modalPresentationStyle: 'overFullScreen',
modalTransitionStyle: 'partialCurl',
modalEnabled: true,
// Android Properties
showTitle: true,
toolbarColor: '#6200EE',
secondaryToolbarColor: 'black',
enableUrlBarHiding: true,
enableDefaultShare: true,
forceCloseOnRedirection: false,
// Specify full animation resource identifier(package:anim/name)
// or only resource name(in case of animation bundled with app).
animations: {
startEnter: 'slide_in_right',
startExit: 'slide_out_left',
endEnter: 'slide_in_left',
endExit: 'slide_out_right'
},
headers: {
'my-custom-header': 'my custom header value'
},
waitForRedirectDelay: 0
})
Alert.alert(JSON.stringify(result))
}
else Linking.openURL(url)
} catch (error) {
Alert.alert(error.message)
}
}
...
you can check the example app here
for expo it becomes little bit complicated please check the related tutorial by Medium
if you want reading mode in ios please refer this link
reader-mode-webview-component-for-react-native
The expo-web-browser package opens an in app browser.
This worked for me with expo. I tried react-native-inappbrowser-reborn first, but isAvailable() was throwing an error.
import * as WebBrowser from 'expo-web-browser'
...
WebBrowser.openBrowserAsync(url, {showTitle: true})