feat: Implement push notification system for admin announcements

- 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.
This commit is contained in:
padreug 2025-07-03 08:34:05 +02:00
parent 6c1caac84b
commit c05f40f1ec
17 changed files with 1316 additions and 13 deletions

View file

@ -2,6 +2,7 @@ import { defineStore } from 'pinia'
import { ref } from 'vue'
import { NostrClient } from '@/lib/nostr/client'
import { config } from '@/lib/config'
import { pushService, type PushSubscriptionData } from '@/lib/notifications/push'
// Define an interface for the account object
interface NostrAccount {
@ -19,6 +20,10 @@ export const useNostrStore = defineStore('nostr', () => {
const relayUrls = ref<string[]>(config.nostr.relays)
const account = ref<NostrAccount | null>(null)
// Push notifications
const pushSubscription = ref<PushSubscriptionData | null>(null)
const notificationsEnabled = ref(false)
// Singleton client instance
let client: NostrClient | null = null
@ -77,6 +82,78 @@ export const useNostrStore = defineStore('nostr', () => {
account.value = nostrAccount
}
// Push notification management
async function enablePushNotifications(): Promise<PushSubscriptionData> {
try {
const subscription = await pushService.subscribe()
pushSubscription.value = subscription
notificationsEnabled.value = true
// Store subscription in localStorage for persistence
localStorage.setItem('push-subscription', JSON.stringify(subscription))
localStorage.setItem('notifications-enabled', 'true')
return subscription
} catch (error) {
console.error('Failed to enable push notifications:', error)
throw error
}
}
async function disablePushNotifications(): Promise<void> {
try {
await pushService.unsubscribe()
pushSubscription.value = null
notificationsEnabled.value = false
// Remove from localStorage
localStorage.removeItem('push-subscription')
localStorage.removeItem('notifications-enabled')
} catch (error) {
console.error('Failed to disable push notifications:', error)
throw error
}
}
async function checkPushNotificationStatus(): Promise<void> {
try {
// Check localStorage first
const storedEnabled = localStorage.getItem('notifications-enabled') === 'true'
const storedSubscription = localStorage.getItem('push-subscription')
if (storedEnabled && storedSubscription) {
pushSubscription.value = JSON.parse(storedSubscription)
notificationsEnabled.value = true
}
// Verify with push service
const currentSubscription = await pushService.getSubscription()
if (currentSubscription) {
pushSubscription.value = currentSubscription
notificationsEnabled.value = true
} else if (storedEnabled) {
// Stored state says enabled but no actual subscription - clear stored state
await disablePushNotifications()
}
} catch (error) {
console.error('Failed to check push notification status:', error)
}
}
// Send test notification
async function sendTestNotification(): Promise<void> {
await pushService.showLocalNotification({
title: '🚨 Test Admin Announcement',
body: 'This is a test notification to verify push notifications are working correctly.',
icon: '/pwa-192x192.png',
tag: 'test-notification',
data: {
url: '/',
type: 'admin-announcement'
}
})
}
return {
// State
isConnected,
@ -84,6 +161,8 @@ export const useNostrStore = defineStore('nostr', () => {
error,
relayUrls,
account,
pushSubscription,
notificationsEnabled,
// Actions
connect,
@ -92,5 +171,9 @@ export const useNostrStore = defineStore('nostr', () => {
setConnected,
setRelayUrls,
setAccount,
enablePushNotifications,
disablePushNotifications,
checkPushNotificationStatus,
sendTestNotification,
}
})