feat(pwa): ✨ register service worker
This commit is contained in:
parent
908c820cb0
commit
bdbe932872
|
@ -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)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
27
routes/api/webpush/subscription.ts
Normal file
27
routes/api/webpush/subscription.ts
Normal 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))
|
||||||
|
}
|
9
routes/api/webpush/vapid.ts
Normal file
9
routes/api/webpush/vapid.ts
Normal 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
45
src/webpush/mod.ts
Normal 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
|
||||||
|
}
|
Loading…
Reference in a new issue