feat(pwa): register service worker

This commit is contained in:
Julien Oculi 2024-06-13 12:42:41 +02:00
parent 908c820cb0
commit bdbe932872
4 changed files with 114 additions and 2 deletions

View file

@ -1,8 +1,39 @@
import { requestApi } from '../src/utils.ts'
export default function RegisterServiceWorker() { export default function RegisterServiceWorker() {
if ('serviceWorker' in navigator) { if ('serviceWorker' in navigator) {
import('./StartServiceWorker.tsx').then((mod) => { import('./StartServiceWorker.tsx').then(async (mod) => {
const href = mod.default() const href = mod.default()
navigator.serviceWorker.register(href, { scope: '/', type: 'module' }) const registration = await navigator.serviceWorker.register(href, {
scope: '/',
type: 'module',
})
// Notification.requestPermission().then((permission) => {
// if (permission !== 'granted') return
// registration.showNotification('Notification permission granted', {
// body: 'Notification is ok.',
// })
// })
const subscription = await (async () => {
const currentSubscription = await registration.pushManager
.getSubscription()
if (currentSubscription) return currentSubscription
const applicationServerKey = await requestApi<void, string>(
'webpush/vapid',
'GET',
)
return await registration.pushManager.subscribe({
userVisibleOnly: true,
applicationServerKey,
})
})()
await requestApi('webpush/subscription', 'POST', subscription)
}) })
} }

View file

@ -0,0 +1,27 @@
import { Handlers } from '$fresh/server.ts'
import { respondApi } from '../../../src/utils.ts'
export const handler: Handlers = {
async POST(request: Request) {
const subscription = await request.json() as PushSubscriptionJSON
saveSubscription(subscription)
return respondApi('success', 'ok')
},
}
function saveSubscription(subscription: PushSubscriptionJSON) {
const itemKey = 'webpush-subscription'
const subscriptions = JSON.parse(
localStorage.getItem(itemKey) ?? '[]',
) as PushSubscriptionJSON[]
// Prevent duplicate
const auth = subscription.keys?.auth
if (subscriptions.some((sub) => sub.keys?.auth === auth)) {
return
}
// Store subscription
subscriptions.push(subscription)
localStorage.setItem(itemKey, JSON.stringify(subscriptions))
}

View file

@ -0,0 +1,9 @@
import { Handlers } from '$fresh/server.ts'
import { respondApi } from '../../../src/utils.ts'
import { publicKey } from '../../../src/webpush/mod.ts'
export const handler: Handlers = {
GET() {
return respondApi('success', publicKey)
},
}

45
src/webpush/mod.ts Normal file
View file

@ -0,0 +1,45 @@
//@deno-types="npm:@types/web-push@^3.6.3"
import webpush from 'web-push'
// DEV mode
// localStorage.clear()
const vapidKeys = getVapidKeys()
export const { publicKey } = vapidKeys
webpush.setVapidDetails(
'mailto:contact@example.com',
vapidKeys.publicKey,
vapidKeys.privateKey,
)
// const itemKey = 'webpush-subscription'
// setInterval(async () => {
// const subscriptions = JSON.parse(localStorage.getItem(itemKey) ?? '[]') as PushSubscriptionJSON[]
// for (const subscription of subscriptions) {
// try {
// // console.log('PUSH NOTIFICATION', subscription)
// const payload: { title: string, options?: Partial<NotificationOptions> } = { title: `This is a test @ ${new Date().toLocaleTimeString()}` }
// //@ts-ignore TODO check endpoint is defined
// const a = await webpush.sendNotification(subscription, JSON.stringify(payload))
// console.log(a)
// } catch (error) {
// console.error(error)
// }
// }
// }, 10_000)
function getVapidKeys(): webpush.VapidKeys {
const itemKey = 'webpush-vapid-keys'
const item = localStorage.getItem(itemKey)
if (item) {
const vapidKeys = JSON.parse(item) as webpush.VapidKeys
return vapidKeys
}
const vapidKeys = webpush.generateVAPIDKeys()
localStorage.setItem(itemKey, JSON.stringify(vapidKeys))
return vapidKeys
}