Remove unnecessary service worker message types (#2268)
* Remove service worker logger * Use async/await for togglePushSubscription * Remove commented out logger calls in service worker * Remove message channel between service worker and app The listener for messages from the service worker was removed in a previous commit. * Remove unused OS detection for service worker * Formatting * Remove unnecessary service worker message types These messages types were meant to debug or fix push notifications getting lost. We figured out the issue: push notifications were lost because of silent pushes. So these message types are no longer needed. --------- Co-authored-by: Keyan <34140557+huumn@users.noreply.github.com>
This commit is contained in:
parent
8382dda231
commit
ec902ebc55
@ -7,11 +7,8 @@ const applicationServerKey = process.env.NEXT_PUBLIC_VAPID_PUBKEY
|
|||||||
const ServiceWorkerContext = createContext()
|
const ServiceWorkerContext = createContext()
|
||||||
|
|
||||||
// message types for communication between app and service worker
|
// message types for communication between app and service worker
|
||||||
export const ACTION_PORT = 'ACTION_PORT' // message to exchange action channel on which service worker will send actions back to app
|
export const DELETE_SUBSCRIPTION = 'DELETE_SUBSCRIPTION'
|
||||||
export const SYNC_SUBSCRIPTION = 'SYNC_SUBSCRIPTION' // trigger onPushSubscriptionChange event in service worker manually
|
export const STORE_SUBSCRIPTION = 'STORE_SUBSCRIPTION'
|
||||||
export const RESUBSCRIBE = 'RESUBSCRIBE' // trigger resubscribing to push notifications (sw -> app)
|
|
||||||
export const DELETE_SUBSCRIPTION = 'DELETE_SUBSCRIPTION' // delete subscription in IndexedDB (app -> sw)
|
|
||||||
export const STORE_SUBSCRIPTION = 'STORE_SUBSCRIPTION' // store subscription in IndexedDB (app -> sw)
|
|
||||||
|
|
||||||
export const ServiceWorkerProvider = ({ children }) => {
|
export const ServiceWorkerProvider = ({ children }) => {
|
||||||
const [registration, setRegistration] = useState(null)
|
const [registration, setRegistration] = useState(null)
|
||||||
@ -35,12 +32,12 @@ export const ServiceWorkerProvider = ({ children }) => {
|
|||||||
`)
|
`)
|
||||||
const [deletePushSubscription] = useMutation(
|
const [deletePushSubscription] = useMutation(
|
||||||
gql`
|
gql`
|
||||||
mutation deletePushSubscription($endpoint: String!) {
|
mutation deletePushSubscription($endpoint: String!) {
|
||||||
deletePushSubscription(endpoint: $endpoint) {
|
deletePushSubscription(endpoint: $endpoint) {
|
||||||
id
|
id
|
||||||
}
|
|
||||||
}
|
}
|
||||||
`)
|
}
|
||||||
|
`)
|
||||||
|
|
||||||
// I am not entirely sure if this is needed since at least in Brave,
|
// I am not entirely sure if this is needed since at least in Brave,
|
||||||
// using `registration.pushManager.subscribe` also prompts the user.
|
// using `registration.pushManager.subscribe` also prompts the user.
|
||||||
@ -94,8 +91,6 @@ export const ServiceWorkerProvider = ({ children }) => {
|
|||||||
await subscription.unsubscribe()
|
await subscription.unsubscribe()
|
||||||
const { endpoint } = subscription
|
const { endpoint } = subscription
|
||||||
await deletePushSubscription({ variables: { endpoint } })
|
await deletePushSubscription({ variables: { endpoint } })
|
||||||
// also delete push subscription in IndexedDB so we can tell if the user disabled push subscriptions
|
|
||||||
// or we lost the push subscription due to a bug
|
|
||||||
navigator.serviceWorker.controller.postMessage({ action: DELETE_SUBSCRIPTION })
|
navigator.serviceWorker.controller.postMessage({ action: DELETE_SUBSCRIPTION })
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -130,23 +125,6 @@ export const ServiceWorkerProvider = ({ children }) => {
|
|||||||
})
|
})
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
// wait until successful registration
|
|
||||||
if (!registration) return
|
|
||||||
// setup channel between app and service worker
|
|
||||||
const channel = new MessageChannel()
|
|
||||||
navigator?.serviceWorker?.controller?.postMessage({ action: ACTION_PORT }, [channel.port2])
|
|
||||||
channel.port1.onmessage = (event) => {
|
|
||||||
if (event.data.action === RESUBSCRIBE && permission.notification === 'granted') {
|
|
||||||
return subscribeToPushNotifications()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// since (a lot of) browsers don't support the pushsubscriptionchange event,
|
|
||||||
// we sync with server manually by checking on every page reload if the push subscription changed.
|
|
||||||
// see https://medium.com/@madridserginho/how-to-handle-webpush-api-pushsubscriptionchange-event-in-modern-browsers-6e47840d756f
|
|
||||||
navigator?.serviceWorker?.controller?.postMessage?.({ action: SYNC_SUBSCRIPTION })
|
|
||||||
}, [registration, permission.notification])
|
|
||||||
|
|
||||||
const contextValue = useMemo(() => ({
|
const contextValue = useMemo(() => ({
|
||||||
registration,
|
registration,
|
||||||
support,
|
support,
|
||||||
|
@ -1,15 +1,11 @@
|
|||||||
import ServiceWorkerStorage from 'serviceworker-storage'
|
import ServiceWorkerStorage from 'serviceworker-storage'
|
||||||
import { numWithUnits } from '@/lib/format'
|
import { numWithUnits } from '@/lib/format'
|
||||||
import { CLEAR_NOTIFICATIONS, clearAppBadge, setAppBadge } from '@/lib/badge'
|
import { CLEAR_NOTIFICATIONS, clearAppBadge, setAppBadge } from '@/lib/badge'
|
||||||
import { ACTION_PORT, DELETE_SUBSCRIPTION, STORE_SUBSCRIPTION, SYNC_SUBSCRIPTION } from '@/components/serviceworker'
|
import { DELETE_SUBSCRIPTION, STORE_SUBSCRIPTION } from '@/components/serviceworker'
|
||||||
|
|
||||||
// we store existing push subscriptions and OS to keep them in sync with server
|
// we store existing push subscriptions for the onpushsubscriptionchange event
|
||||||
const storage = new ServiceWorkerStorage('sw:storage', 1)
|
const storage = new ServiceWorkerStorage('sw:storage', 1)
|
||||||
|
|
||||||
// for communication between app and service worker
|
|
||||||
// see https://developer.mozilla.org/en-US/docs/Web/API/MessageChannel
|
|
||||||
let actionChannelPort
|
|
||||||
|
|
||||||
// current push notification count for badge purposes
|
// current push notification count for badge purposes
|
||||||
let activeCount = 0
|
let activeCount = 0
|
||||||
|
|
||||||
@ -130,28 +126,14 @@ export function onNotificationClick (sw) {
|
|||||||
|
|
||||||
export function onPushSubscriptionChange (sw) {
|
export function onPushSubscriptionChange (sw) {
|
||||||
// https://medium.com/@madridserginho/how-to-handle-webpush-api-pushsubscriptionchange-event-in-modern-browsers-6e47840d756f
|
// https://medium.com/@madridserginho/how-to-handle-webpush-api-pushsubscriptionchange-event-in-modern-browsers-6e47840d756f
|
||||||
// `isSync` is passed if function was called because of 'SYNC_SUBSCRIPTION' event
|
return async (event) => {
|
||||||
// this makes sure we can differentiate between 'pushsubscriptionchange' events and our custom 'SYNC_SUBSCRIPTION' event
|
|
||||||
return async (event, isSync) => {
|
|
||||||
let { oldSubscription, newSubscription } = event
|
let { oldSubscription, newSubscription } = event
|
||||||
// https://developer.mozilla.org/en-US/docs/Web/API/ServiceWorkerGlobalScope/pushsubscriptionchange_event
|
// https://developer.mozilla.org/en-US/docs/Web/API/ServiceWorkerGlobalScope/pushsubscriptionchange_event
|
||||||
// fallbacks since browser may not set oldSubscription and newSubscription
|
// fallbacks since browser may not set oldSubscription and newSubscription
|
||||||
oldSubscription ??= await storage.getItem('subscription')
|
oldSubscription ??= await storage.getItem('subscription')
|
||||||
newSubscription ??= await sw.registration.pushManager.getSubscription()
|
newSubscription ??= await sw.registration.pushManager.getSubscription()
|
||||||
if (!newSubscription) {
|
if (!newSubscription || oldSubscription?.endpoint === newSubscription.endpoint) {
|
||||||
if (isSync && oldSubscription?.swVersion === 2) {
|
// no subscription exists at the moment or subscription did not change
|
||||||
// service worker lost the push subscription somehow, we assume this is a bug -> resubscribe
|
|
||||||
// see https://github.com/stackernews/stacker.news/issues/411#issuecomment-1790675861
|
|
||||||
// NOTE: this is only run on IndexedDB subscriptions stored under service worker version 2 since this is not backwards compatible
|
|
||||||
// see discussion in https://github.com/stackernews/stacker.news/pull/597
|
|
||||||
actionChannelPort?.postMessage({ action: 'RESUBSCRIBE' })
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// no subscription exists at the moment
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if (oldSubscription?.endpoint === newSubscription.endpoint) {
|
|
||||||
// subscription did not change. no need to sync with server
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// convert keys from ArrayBuffer to string
|
// convert keys from ArrayBuffer to string
|
||||||
@ -182,16 +164,9 @@ export function onPushSubscriptionChange (sw) {
|
|||||||
|
|
||||||
export function onMessage (sw) {
|
export function onMessage (sw) {
|
||||||
return async (event) => {
|
return async (event) => {
|
||||||
if (event.data.action === ACTION_PORT) {
|
|
||||||
actionChannelPort = event.ports[0]
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if (event.data.action === STORE_SUBSCRIPTION) {
|
if (event.data.action === STORE_SUBSCRIPTION) {
|
||||||
return event.waitUntil(storage.setItem('subscription', { ...event.data.subscription, swVersion: 2 }))
|
return event.waitUntil(storage.setItem('subscription', { ...event.data.subscription, swVersion: 2 }))
|
||||||
}
|
}
|
||||||
if (event.data.action === SYNC_SUBSCRIPTION) {
|
|
||||||
return event.waitUntil(onPushSubscriptionChange(sw)(event, true))
|
|
||||||
}
|
|
||||||
if (event.data.action === DELETE_SUBSCRIPTION) {
|
if (event.data.action === DELETE_SUBSCRIPTION) {
|
||||||
return event.waitUntil(storage.removeItem('subscription'))
|
return event.waitUntil(storage.removeItem('subscription'))
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user