Closed heymartinadams closed 2 years ago
This is still the case even if I do a bare-bones function:
<button onClick={() => {
const beamsClient = new PusherPushNotifications.Client({
instanceId: process.env.NEXT_PUBLIC_PUSHER
})
beamsClient.start().then(response => console.log(response))
}}>
Enable Notifications
</button>
I've been able to replicate this when using Safari and the code snippet provided. Interestingly the code does work on Firefox, which also has the same restrictions on when Push Notification permission can be granted (in response to a user gesture) so this looks to be specific to Safari. I'll keep digging.
I have been able to resolve this - although I am not certain precisely why this works.
Removing the instantiation of the beamsClient
from the onClick
handler prevents the error from showing. For example, the below works:
let beamsClient;
useEffect(() => {
beamsClient = new PusherPushNotifications.Client({
instanceId: process.env.NEXT_PUBLIC_PUSHER
})
if("serviceWorker" in navigator) {
window.addEventListener("load", function () {
navigator.serviceWorker.register("/service-worker.js").then(
function (registration) {
console.log("Service Worker registration successful with scope: ", registration.scope);
},
function (err) {
console.log("Service Worker registration failed: ", err);
}
);
});
}
}, []);
<button onClick={() => {
beamsClient.start()
.then(response => console.log(response))
.then(() => beamsClient.addDeviceInterest("debug-hello"))
}}>Enable Notifications
</button>
Are you able to attempt a similar pattern?
@benw-pusher adding the service worker script to the useEffect
, as well as instantiating beamsClient
did the trick! I also had to make sure that none of the initialization (beamsClient.start()
) was appearing in a useEffect
as well. Appears that Safari is quite finicky like that. Including a full reproduction below for authenticated user push notifications in case someone else is running into the same issue.
Thanks again! š
let beamsClient
const DesignLayoutsTodosNotifications = () => {
// This `useEffect` apparently must remain in this file, otherwise `beamsClient` is undefined, even if passed into hook file and then exported back
useEffect(() => {
beamsClient = new PusherPushNotifications.Client({
instanceId: process.env.NEXT_PUBLIC_PUSHER
})
if ('serviceWorker' in navigator)
window.addEventListener('load', () =>
navigator.serviceWorker.register('/service-worker.js').then(
registration =>
console.log('Service Worker registration successful with scope: ', registration.scope),
err => console.log('Service Worker registration failed: ', err)
)
)
}, [])
return (
<div>
<h3>Reminders</h3>
<button
onClick={() => {
// Must remain here and not placed inside a hook so that Safari recognizes this as a user gesture
const beamsTokenProvider = new PusherPushNotifications.TokenProvider({
url: `/api/push/register`,
queryParams: {
userId: userId // `userId` provided from elsewhere
},
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
...(token ? { Authorization: `Bearer ${token}` } : {}) // `token` provided from elsewhere
}
})
beamsClient
.start()
.then(() => beamsClient.setUserId(userId, beamsTokenProvider))
.then(() => console.log('Push enabled š'))
}}
>
Enable Notifications
</button>
</div>
)
}
export default DesignLayoutsTodosNotifications
Issue
In my
React
app, Iām triggering push notifications via a user gestureonClick
in Safari, but I still receive the following error:What am I doing wrong?
Replication
1. User Interface
2. Function