Improve push notification registration

This commit is contained in:
Dorian
2026-05-15 13:45:07 -05:00
parent 80f1718baa
commit 54e8892603
3 changed files with 42 additions and 24 deletions

View File

@@ -9,6 +9,7 @@
"orientation": "portrait",
"background_color": "#000000",
"theme_color": "#000000",
"gcm_sender_id": "103953800507",
"icons": [
{
"src": "/images/app-icon-192.png",

View File

@@ -1,4 +1,4 @@
const CACHE_NAME = 'l484-pwa-v3'
const CACHE_NAME = 'l484-pwa-v4'
const APP_SHELL = [
'/',
'/manifest.webmanifest',

View File

@@ -19,29 +19,7 @@ export const notificationSupport = () => ({
secure: window.isSecureContext || window.location.hostname === 'localhost' || window.location.hostname === '127.0.0.1',
})
export const subscribeToNotifications = async () => {
const support = notificationSupport()
if (!support.supported) throw new Error('Push notifications are not supported in this browser.')
if (!support.secure) throw new Error('Push notifications require HTTPS.')
const keyResponse = await fetch('/api/notifications/vapid-public-key')
const keyData = await keyResponse.json().catch(() => ({}))
if (!keyResponse.ok || !keyData.publicKey) throw new Error('VAPID public key is not configured.')
const requested = await Notification.requestPermission()
permission.value = requested
if (requested !== 'granted') throw new Error('Notification permission was not granted.')
const registration = await navigator.serviceWorker.register('/sw.js')
await navigator.serviceWorker.ready
const existing = await registration.pushManager.getSubscription()
if (existing) await existing.unsubscribe()
const subscription = await registration.pushManager.subscribe({
userVisibleOnly: true,
applicationServerKey: urlBase64ToUint8Array(keyData.publicKey),
})
const saveSubscription = async (subscription) => {
const response = await fetch('/api/notifications/subscribe', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
@@ -51,3 +29,42 @@ export const subscribeToNotifications = async () => {
if (!response.ok) throw new Error(data.error || 'Could not save notification subscription.')
return data
}
const subscribeWithRetry = async (registration, applicationServerKey) => {
try {
return await registration.pushManager.subscribe({ userVisibleOnly: true, applicationServerKey })
} catch (error) {
await registration.update().catch(() => {})
await new Promise((resolve) => window.setTimeout(resolve, 350))
try {
return await registration.pushManager.subscribe({ userVisibleOnly: true, applicationServerKey })
} catch {
const message = error instanceof Error ? error.message : 'Push service error.'
throw new Error(`Push registration failed: ${message}`)
}
}
}
export const subscribeToNotifications = async () => {
const support = notificationSupport()
if (!support.supported) throw new Error('Push notifications are not supported in this browser.')
if (!support.secure) throw new Error('Push notifications require HTTPS.')
const keyResponse = await fetch('/api/notifications/vapid-public-key')
const keyData = await keyResponse.json().catch(() => ({}))
if (!keyResponse.ok || !keyData.publicKey) throw new Error('VAPID public key is not configured.')
if (!keyData.configured) throw new Error('VAPID private key is not configured on the server.')
const applicationServerKey = urlBase64ToUint8Array(keyData.publicKey)
const requested = await Notification.requestPermission()
permission.value = requested
if (requested !== 'granted') throw new Error('Notification permission was not granted.')
const registration = await navigator.serviceWorker.register('/sw.js')
await navigator.serviceWorker.ready
const existing = await registration.pushManager.getSubscription()
if (existing) return saveSubscription(existing)
const subscription = await subscribeWithRetry(registration, applicationServerKey)
return saveSubscription(subscription)
}