- Add a notification manager to handle push notifications and integrate with Nostr events. - Create a push notification service to manage subscription and permission requests. - Introduce components for notification settings and permission prompts in the UI. - Update Nostr store to manage push notification state and enable/disable functionality. - Enhance NostrFeed to send notifications for new admin announcements. - Implement test notification functionality for development purposes.
126 lines
No EOL
3.3 KiB
JavaScript
126 lines
No EOL
3.3 KiB
JavaScript
// Custom service worker for push notifications
|
|
// This will be merged with Workbox generated SW
|
|
|
|
import { precacheAndRoute, cleanupOutdatedCaches } from 'workbox-precaching'
|
|
import { clientsClaim, skipWaiting } from 'workbox-core'
|
|
|
|
// Precache and route static assets
|
|
precacheAndRoute(self.__WB_MANIFEST)
|
|
cleanupOutdatedCaches()
|
|
|
|
// Take control of all pages immediately
|
|
skipWaiting()
|
|
clientsClaim()
|
|
|
|
// Push notification event handler
|
|
self.addEventListener('push', (event) => {
|
|
console.log('Push event received:', event)
|
|
|
|
let notificationData = {
|
|
title: 'New Announcement',
|
|
body: 'You have a new admin announcement',
|
|
icon: '/pwa-192x192.png',
|
|
badge: '/pwa-192x192.png',
|
|
data: {
|
|
url: '/',
|
|
timestamp: Date.now()
|
|
},
|
|
tag: 'admin-announcement',
|
|
requireInteraction: true,
|
|
actions: [
|
|
{
|
|
action: 'view',
|
|
title: 'View',
|
|
icon: '/pwa-192x192.png'
|
|
},
|
|
{
|
|
action: 'dismiss',
|
|
title: 'Dismiss'
|
|
}
|
|
]
|
|
}
|
|
|
|
// Parse push data if available
|
|
if (event.data) {
|
|
try {
|
|
const pushData = event.data.json()
|
|
notificationData = {
|
|
...notificationData,
|
|
...pushData
|
|
}
|
|
} catch (error) {
|
|
console.warn('Failed to parse push data:', error)
|
|
// Use default notification data
|
|
}
|
|
}
|
|
|
|
event.waitUntil(
|
|
self.registration.showNotification(notificationData.title, notificationData)
|
|
)
|
|
})
|
|
|
|
// Notification click handler
|
|
self.addEventListener('notificationclick', (event) => {
|
|
console.log('Notification clicked:', event)
|
|
|
|
event.notification.close()
|
|
|
|
const action = event.action
|
|
const notificationData = event.notification.data || {}
|
|
|
|
if (action === 'dismiss') {
|
|
return // Just close the notification
|
|
}
|
|
|
|
// Default action or 'view' action - open the app
|
|
const urlToOpen = notificationData.url || '/'
|
|
|
|
event.waitUntil(
|
|
clients.matchAll({ type: 'window', includeUncontrolled: true })
|
|
.then((clientList) => {
|
|
// Try to find an existing window with the app
|
|
for (const client of clientList) {
|
|
if (client.url.includes(self.location.origin) && 'focus' in client) {
|
|
client.focus()
|
|
// Navigate to the notification URL if different
|
|
if (client.url !== urlToOpen) {
|
|
client.navigate(urlToOpen)
|
|
}
|
|
return
|
|
}
|
|
}
|
|
// If no existing window, open a new one
|
|
if (clients.openWindow) {
|
|
return clients.openWindow(urlToOpen)
|
|
}
|
|
})
|
|
)
|
|
})
|
|
|
|
// Background sync for offline notification queue (future enhancement)
|
|
self.addEventListener('sync', (event) => {
|
|
if (event.tag === 'notification-queue') {
|
|
event.waitUntil(
|
|
// Process any queued notifications when back online
|
|
console.log('Background sync: notification-queue')
|
|
)
|
|
}
|
|
})
|
|
|
|
// Message handler for communication with main app
|
|
self.addEventListener('message', (event) => {
|
|
console.log('Service worker received message:', event.data)
|
|
|
|
if (event.data && event.data.type === 'SHOW_NOTIFICATION') {
|
|
const { title, body, data } = event.data.payload
|
|
|
|
self.registration.showNotification(title, {
|
|
body,
|
|
icon: '/pwa-192x192.png',
|
|
badge: '/pwa-192x192.png',
|
|
data,
|
|
tag: 'manual-notification',
|
|
requireInteraction: false
|
|
})
|
|
}
|
|
}) |