e45af16bf9
* feat: Push notifications * feat: Feature-detect push notifications support * feat: Prompt user to reauthenticate when missing push scope * fix(service-worker): Add tags to notifications * feat: Push notification actions for mentions
90 lines
3.3 KiB
JavaScript
90 lines
3.3 KiB
JavaScript
import { getSubscription, deleteSubscription, postSubscription, putSubscription } from '../_api/pushSubscription'
|
|
import { store } from '../_store/store'
|
|
import { urlBase64ToUint8Array } from '../_utils/base64'
|
|
|
|
const dummyApplicationServerKey = 'BImgAz4cF_yvNFp8uoBJCaGpCX4d0atNIFMHfBvAAXCyrnn9IMAFQ10DW_ZvBCzGeR4fZI5FnEi2JVcRE-L88jY='
|
|
|
|
export async function updatePushSubscriptionForInstance (instanceName) {
|
|
const { loggedInInstances, pushSubscription } = store.get()
|
|
const accessToken = loggedInInstances[instanceName].access_token
|
|
|
|
if (pushSubscription === null) {
|
|
return
|
|
}
|
|
|
|
const registration = await navigator.serviceWorker.ready
|
|
const subscription = await registration.pushManager.getSubscription()
|
|
|
|
if (subscription === null) {
|
|
store.set({ pushSubscription: null })
|
|
store.save()
|
|
return
|
|
}
|
|
|
|
try {
|
|
const backendSubscription = await getSubscription(instanceName, accessToken)
|
|
|
|
// Check if applicationServerKey changed (need to get another subscription from the browser)
|
|
if (btoa(urlBase64ToUint8Array(backendSubscription.server_key).buffer) !== btoa(subscription.options.applicationServerKey)) {
|
|
await subscription.unsubscribe()
|
|
await deleteSubscription(instanceName, accessToken)
|
|
await updateAlerts(instanceName, pushSubscription.alerts)
|
|
} else {
|
|
store.set({ pushSubscription: backendSubscription })
|
|
store.save()
|
|
}
|
|
} catch (e) {
|
|
// TODO: Better way to detect 404
|
|
if (e.message.startsWith('404:')) {
|
|
await subscription.unsubscribe()
|
|
store.set({ pushSubscription: null })
|
|
store.save()
|
|
}
|
|
}
|
|
}
|
|
|
|
export async function updateAlerts (instanceName, alerts) {
|
|
const { loggedInInstances } = store.get()
|
|
const accessToken = loggedInInstances[instanceName].access_token
|
|
|
|
const registration = await navigator.serviceWorker.ready
|
|
let subscription = await registration.pushManager.getSubscription()
|
|
|
|
if (subscription === null) {
|
|
// We need applicationServerKey in order to register a push subscription
|
|
// but the API doesn't expose it as a constant (as it should).
|
|
// So we need to register a subscription with a dummy applicationServerKey,
|
|
// send it to the backend saves it and return applicationServerKey, which
|
|
// we use to register a new subscription.
|
|
// https://github.com/tootsuite/mastodon/issues/8785
|
|
subscription = await registration.pushManager.subscribe({
|
|
applicationServerKey: urlBase64ToUint8Array(dummyApplicationServerKey),
|
|
userVisibleOnly: true
|
|
})
|
|
|
|
let backendSubscription = await postSubscription(instanceName, accessToken, subscription, alerts)
|
|
|
|
await subscription.unsubscribe()
|
|
|
|
subscription = await registration.pushManager.subscribe({
|
|
applicationServerKey: urlBase64ToUint8Array(backendSubscription.server_key),
|
|
userVisibleOnly: true
|
|
})
|
|
|
|
backendSubscription = await postSubscription(instanceName, accessToken, subscription, alerts)
|
|
|
|
store.set({ pushSubscription: backendSubscription })
|
|
store.save()
|
|
} else {
|
|
try {
|
|
const backendSubscription = await putSubscription(instanceName, accessToken, alerts)
|
|
store.set({ pushSubscription: backendSubscription })
|
|
store.save()
|
|
} catch (e) {
|
|
const backendSubscription = await postSubscription(instanceName, accessToken, subscription, alerts)
|
|
store.set({ pushSubscription: backendSubscription })
|
|
store.save()
|
|
}
|
|
}
|
|
}
|