- 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.
179 lines
No EOL
4.8 KiB
TypeScript
179 lines
No EOL
4.8 KiB
TypeScript
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 {
|
|
privkey: string
|
|
pubkey: string
|
|
}
|
|
|
|
export const useNostrStore = defineStore('nostr', () => {
|
|
// Connection state
|
|
const isConnected = ref(false)
|
|
const isConnecting = ref(false)
|
|
const error = ref<Error | null>(null)
|
|
|
|
// Configuration
|
|
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
|
|
|
|
// Get or create client instance
|
|
function getClient(): NostrClient {
|
|
if (!client) {
|
|
client = new NostrClient({ relays: relayUrls.value })
|
|
}
|
|
return client
|
|
}
|
|
|
|
// Connection management
|
|
async function connect(): Promise<void> {
|
|
try {
|
|
error.value = null
|
|
isConnecting.value = true
|
|
|
|
const nostrClient = getClient()
|
|
await nostrClient.connect()
|
|
|
|
isConnected.value = nostrClient.isConnected
|
|
} catch (err) {
|
|
error.value = err instanceof Error ? err : new Error('Failed to connect')
|
|
isConnected.value = false
|
|
throw err
|
|
} finally {
|
|
isConnecting.value = false
|
|
}
|
|
}
|
|
|
|
function disconnect(): void {
|
|
if (client) {
|
|
client.disconnect()
|
|
client = null
|
|
}
|
|
isConnected.value = false
|
|
isConnecting.value = false
|
|
error.value = null
|
|
}
|
|
|
|
// Configuration setters
|
|
function setConnected(value: boolean) {
|
|
isConnected.value = value
|
|
}
|
|
|
|
function setRelayUrls(urls: string[]) {
|
|
relayUrls.value = urls
|
|
// Recreate client with new relays
|
|
if (client) {
|
|
client.disconnect()
|
|
client = null
|
|
}
|
|
}
|
|
|
|
function setAccount(nostrAccount: NostrAccount | null) {
|
|
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,
|
|
isConnecting,
|
|
error,
|
|
relayUrls,
|
|
account,
|
|
pushSubscription,
|
|
notificationsEnabled,
|
|
|
|
// Actions
|
|
connect,
|
|
disconnect,
|
|
getClient,
|
|
setConnected,
|
|
setRelayUrls,
|
|
setAccount,
|
|
enablePushNotifications,
|
|
disablePushNotifications,
|
|
checkPushNotificationStatus,
|
|
sendTestNotification,
|
|
}
|
|
})
|