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() } } }