Files
hotelsync/public/sw.js
HotelSync 1641b14f29 feat: PWA push notifications — service worker, VAPID, subscription management
- Add web-push VAPID backend with push_subscriptions table (migration 078)
- Backend push module with sendPushToUser/sendPushToRoom helpers
- Push routes: GET vapid-key, POST subscribe, DELETE unsubscribe
- Trigger push on new chat messages in direct/group rooms
- PWA manifest, service worker, and icons (72–512px)
- Frontend push lib: SW registration, subscribe/unsubscribe helpers
- Push API in api.ts, SW registered in main.tsx
- usePushSubscription hook for auto-subscribe on permission grant
- PushPermissionRow component in ChatWidget settings view

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-15 12:14:03 +03:00

36 lines
1.1 KiB
JavaScript

const CACHE_NAME = 'hotelsync-v1'
self.addEventListener('install', () => self.skipWaiting())
self.addEventListener('activate', event => event.waitUntil(self.clients.claim()))
self.addEventListener('push', event => {
if (!event.data) return
let data
try { data = event.data.json() } catch { data = { title: 'HotelSync', body: event.data.text() } }
const title = data.title ?? 'HotelSync'
const options = {
body: data.body ?? '',
icon: data.icon ?? '/icons/icon-192.png',
badge: '/icons/icon-72.png',
tag: data.tag,
renotify: !!data.tag,
data: { url: data.url ?? '/' },
vibrate: [200, 100, 200],
}
event.waitUntil(self.registration.showNotification(title, options))
})
self.addEventListener('notificationclick', event => {
event.notification.close()
const url = event.notification.data?.url ?? '/'
event.waitUntil(
self.clients.matchAll({ type: 'window', includeUncontrolled: true }).then(clients => {
const existing = clients.find(c => c.url.includes(self.location.origin))
if (existing) { existing.focus(); existing.navigate(url) }
else self.clients.openWindow(url)
})
)
})