How can I catch with serviceworker or simple js code, when user who previously allowed the web push notifications for my site disable them? For Firefox and Chrome browsers.
You can use the Permissions API to detect the current state of given permissions, as well as listen for changes.
This article has more detail. Here's a relevant code snippet:
navigator.permissions.query({name: 'push'}).then(function(status) {
// Initial permission status is `status.state`
status.onchange = function() {
// Status changed to `this.state`
};
});
You can try this:
navigator.permissions.query({name:'notifications'}).then(function(status) {
//alert(status.state); // status.state == { "prompt", "granted", "denied" }
status.onchange = function() {
if(this.state=="denied" || this.state=="prompt"){ push_unsubscribe(); }
};
});
or this:
navigator.permissions.query({name:'push', userVisibleOnly:true}).then(function(status) {
//alert(status.state); // status.state == { "prompt", "granted", "denied" }
status.onchange = function() {
if(this.state=="denied" || this.state=="prompt"){ push_unsubscribe(); }
};
});
I use it to send information to the server that the user has canceled or disabled notifications. Note that the code is not executed if the user does so in the site settings.
Related
My website currently sends push notifications to users when accessing the site for the first time, is there a way to remove this push notification request?
TIA
Use this in your .js file
Notification.requestPermission();
Create a button for "Enable Notification" in .html file
<button id="enable">Enable notifications</button>
When pressing this button app requests notification for the app (.js file)
function askNotificationPermission() {
// Asking for permissions
function handlePermission(permission) {
// button set for shown or hidden, depending on the user's selection
if(Notification.permission === 'denied' || Notification.permission === 'default') {
notificationBtn.style.display = 'block';
} else {
notificationBtn.style.display = 'none';
}
}
// Check if the browser actually supports notifications
if (!('Notification' in window)) {
console.log("This browser does not support notifications.");
} else {
if(checkNotificationPromise()) {
Notification.requestPermission()
.then((permission) => {
handlePermission(permission);
})
} else {
Notification.requestPermission(function(permission) {
handlePermission(permission);
});
}
}
}
I'll start my saying I'm a JavaScript newbie (I'm more of a Bash guy)...
I'm trying to create a Firefox WebExtension to disable the Ctrl+Q shortcut and play a sound when Ctrl+Q is pressed. I'd also like to have a user choose from a small list of sounds in an options menu. So far, all of that is working.
The only snag I'm hitting is when the user changes a sound and clicks "Save", the new sound isn't played on Ctrl+Q until the extension is reloaded.
Doing some Googling, I think the problem is related to the fact that storage API is asynchronous. From what I can gather, I need to use a callback to get the sound option after it is set. Is that not what I'm doing below? The option is set in options.js and then background.js plays the sound.
I'd appreciate any help.
options.js
// Saves options to browser.storage
function save_options() {
browser.storage.local.set({
favoriteSound: document.getElementById('CtrlQSound').value,
}, function() {
// Update status to let user know options were saved.
var status = document.getElementById('status');
status.textContent = 'Options saved.';
setTimeout(function() {
status.textContent = '';
}, 750);
});
};
// Restores select box state using the preferences stored in browser.storage
function restore_options() {
// Use default value sound = 'Sound0'
browser.storage.local.get({
favoriteSound: 'Sound0',
}, function(items) {
document.getElementById('CtrlQSound').value = items.favoriteSound;
});
};
document.addEventListener('DOMContentLoaded', restore_options);
document.getElementById('save').addEventListener('click', save_options);
background.js
browser.storage.local.get("favoriteSound", function(result) {
browser.commands.onCommand.addListener(function(SoundToggle) {
if (result.favoriteSound == "Sound0"){
new Audio("Sound0.ogg").play();
}
else if (result.favoriteSound == "Sound1"){
new Audio("Sound1.ogg").play();
}
else if (result.favoriteSound == "Sound2"){
new Audio("Sound2.ogg").play();
}
});
});
Firefox uses Promise objects, not callbacks. On a Promise, you can call "then" with a success and failure handler. Like this:
browser.storage.local.set({
favoriteSound: document.getElementById('CtrlQSound').value
}).then(onSuccess, onError);
function onSuccess() {
// Saving into storage.local succeeded
// Update status to let user know options were saved.
var status = document.getElementById('status');
status.textContent = 'Options saved.';
setTimeout(function() {
status.textContent = '';
}, 750);
function onError() {
// Saving into storage local failed.
// You might want to use a notification to display this error / warning to the user.
});
If you're developing for Chrome, you have to use callbacks. Or you could use "chrome." instead of "browser." if you want to use callbacks instead of Promises.
I want to add a joyride or guided tour for my React App. I want to show it when the users first uses it and disable for subsequent frequent visits.
I have found this library https://github.com/gilbarbara/react-joyride but couldn't figure out how to disable on subsequent visits by same user?
Can I use localstorage or cookies to deal with this issue? How?
Yes adding it to localStorage is a good solution. I use the following function for this to trigger the check:
checkForInitialTour() {
if (!localStorage.getItem('tourDone')) {
localStorage.setItem('tourDone', true);
this.joyride.reset();
this.joyride.start(true);
}
}
Also possible to set in localstorage after tour by using the callback parameter
callback={(e) => { if (e.type === 'finished') { window.scrollTo(0, 0); localStorage.setItem('tourDone', true); } }}
If you're using nextjs or server-side rendering, here's my approach:
State is initialized:
runJoyride: (typeof window === 'undefined')? false : window.localStorage.getItem('onboarded') === null,
And you callback:
handleJoyrideCallback = data => {
const { action, index, status, type } = data;
if ([STATUS.FINISHED, STATUS.SKIPPED].includes(status)) {
this.setState({ runJoyride: false });
window.localStorage.setItem('onboarded', true);
}
};
I am trying to get the User's groups list with the following code:
$(document).ready(function() {
$("#fetchButton").click(function() {
console.log('fetch button');
FB.getLoginStatus(function(res){
if( res.status == "connected" ){ // check if logged in
// get user data first, which will be handled by an anonymours fucntion passed inline
FB.api('/me', function(meResponse) {
//console.log(meResponse);
UID = meResponse.id;
getGroups();
console.log(meResponse);
});
} else { // if not logged in, call login procedure
FB.login(function(){
$("#fetchButton").click();
}, {scope: 'publish_actions, publish_actions, read_stream, user_groups'});
}
});
});
});
function getGroups() {
FB.api('/me/groups', function(groupResponse) {
console.log(groupResponse);
});
}
This code used to work with some old version of FB SDK. But not now.
Any help!
read_stream and user_groups are deprecated and you are using publish_actions two times. In order to get a list of all the groups you manage, you need to use user_managed_groups now.
More information: https://developers.facebook.com/docs/apps/changelog#v2_4
I'm having a tough time getting push notifications (using the ngCordova plugin) to work. I have followed their sample code exactly as is documented on the site: http://ngcordova.com/docs/plugins/pushNotifications/
(the only difference is that I don't have a deviceready listener, instead, my code is inside the ionicPlatform.ready listener.)
Here is my code:
angular.module('myApp', ['ionic', 'ngCordova'])
.run(function($ionicPlatform, $rootScope, $state, $cordovaPush) {
$ionicPlatform.ready(function() {
var config = {
"senderID": "myID100001000"
};
$cordovaPush.register(config).then(function(result) {
alert(result);
}, function(err) {
alert(err);
})
});
$rootScope.$on('$cordovaPush:notificationReceived', function(event, notification) {
switch(notification.event) {
case 'registered':
if (notification.regid.length > 0 ) {
alert('registration ID = ' + notification.regid);
}
break;
default:
alert('An unknown GCM event has occurred');
break;
}
});
})
When my app starts I do get the "OK" alert, so I know it successfully goes through the $cordovaPush.register call. However, I was expecting to get a "registered" notification event, right after, but I never get notified.
Any help would be appreciated.
The solution is in the comments but this needs a proper answer.
First of all, the register callback always returns OK as long as you pass a senderID, but if the $cordovaPush:notificationReceived event is never called (it may take a few seconds), this ID is probably wrong.
You must use the Project Number, not the Project ID.
To get the number, go to the API Console, select the project and you'll be on the Overview page. On top of this page, you'll see something like this:
Project ID: your-project-id Project Number: 0123456789
Just copy and use the project number and everything should work.
I have suffered with this a lot and I have found out, that there are in fact two versions of the cordova push plugin currently:
https://github.com/phonegap-build/PushPlugin (deprecated)
https://github.com/phonegap/phonegap-plugin-push (new one)
Both are supported by ngCordova, but only the deprecated version is documented.
The deprecated version is $cordovaPush
and the newer one is $cordovaPushV5, and they have completely different methods.
For me the problem was that I downloaded the cordova-plugin-push and tried to implement it with the old documentation on ngCordova site.
The code is:
/*
* Non deprecated version of Push notification events
*/
function registerV5() {
$ionicLoading.show({
template: '<ion-spinner></ion-spinner>'
});
if (ionic.Platform.is('browser')) {
alert("You are running on broswer, please switch to your device. Otherwise you won't get notifications");
$ionicLoading.hide();
return;
}
/**
* Configuration doc:
* https://github.com/phonegap/phonegap-plugin-push/blob/master/docs/API.md#pushnotificationinitoptions
*/
var GCM_PROJECT_ID = 'xxxxxx';
$cordovaPushV5.initialize({
"android": {
"clearNotifications": false,
"senderID" : GCM_PROJECT_ID
}
});
$cordovaPushV5.register().then(function (deviceToken) {
console.log("Successfully registered", deviceToken);
$scope.data.deviceToken = deviceToken;
// Below code required to configure $cordovaPushV5 notifications emitter.
// Don't pass function it's not handler.
$cordovaPushV5.onNotification();
$cordovaPushV5.onError();
$ionicLoading.hide();
}, function (error) {
console.log("Failed to registered");
console.log("error object : ", error);
$ionicLoading.hide();
});
}
$rootScope.$on('$cordovaPushV5:notificationReceived', function(event, data) {
console.log("notification received");
console.log("data object: ", data);
var foreground = data.additionalData.foreground || false;
var threadID = data.additionalData.payload.threadID || '';
var group = data.additionalData.payload.group || false;
if (foreground) {
// Do something if the app is in foreground while receiving to push - handle in app push handling
console.log('Receive notification in foreground');
} else {
// Handle push messages while app is in background or not started
console.log('Receive notification in background');
// Open FB messanger app when user clicks notification UI when app is in background.
if (typeof data.additionalData.coldstart != "undefined" && data.additionalData.coldstart == false)
if (!group)
// Open FB Messenger of specific user chat window
window.open('fb-messenger://user/' + threadID, '_system', 'location=no');
else
// Open FB Messenger of specific group chat window
window.open('fb-messenger://groupthreadfbid/' + threadID, '_system', 'location=no');
}
});
$rootScope.$on('$cordovaPushV5:errorOccurred', function(event, error) {
console.log("notification error occured");
console.log("event object: ", event);
console.log("error object: ", error);
});
More on this github article: https://github.com/driftyco/ng-cordova/issues/1125 (code from here) and in this article: https://github.com/yafraorg/yafra/wiki/Blog-Ionic-PushV5