137 lines
4.7 KiB
TypeScript
137 lines
4.7 KiB
TypeScript
import { useState, useEffect, useCallback } from 'react'
|
|
import { notificationService } from '@/lib/notificationService'
|
|
import type { Notification } from '@/lib/notificationService'
|
|
|
|
const MAX_NOTIFICATIONS = 100
|
|
const POLL_INTERVAL_MS = 30_000
|
|
|
|
export function useNotifications(userPubkey: string | null): {
|
|
notifications: Notification[]
|
|
unreadCount: number
|
|
loading: boolean
|
|
markAsRead: (notificationId: string) => void
|
|
markAllAsRead: () => void
|
|
deleteNotification: (notificationId: string) => void
|
|
} {
|
|
const [notifications, setNotifications] = useState<Notification[]>([])
|
|
const [loading, setLoading] = useState(true)
|
|
|
|
useNotificationsPoller({ userPubkey, setNotifications, setLoading })
|
|
|
|
const effectiveNotifications = userPubkey ? notifications : []
|
|
const effectiveLoading = userPubkey ? loading : false
|
|
const unreadCount = effectiveNotifications.filter((n) => !n.read).length
|
|
const actions = useNotificationActions({ userPubkey, setNotifications })
|
|
|
|
return {
|
|
notifications: effectiveNotifications,
|
|
unreadCount,
|
|
loading: effectiveLoading,
|
|
markAsRead: actions.markAsRead,
|
|
markAllAsRead: actions.markAllAsRead,
|
|
deleteNotification: actions.deleteNotification,
|
|
}
|
|
}
|
|
|
|
function useNotificationsPoller(params: {
|
|
userPubkey: string | null
|
|
setNotifications: (value: Notification[]) => void
|
|
setLoading: (value: boolean) => void
|
|
}): void {
|
|
useEffect(() => {
|
|
if (!params.userPubkey) {
|
|
return
|
|
}
|
|
void loadAndSetNotifications({ setNotifications: params.setNotifications, setLoading: params.setLoading })
|
|
const interval = setInterval(() => {
|
|
void loadAndSetNotifications({ setNotifications: params.setNotifications, setLoading: params.setLoading })
|
|
}, POLL_INTERVAL_MS)
|
|
return () => clearInterval(interval)
|
|
}, [params.userPubkey, params.setNotifications, params.setLoading])
|
|
}
|
|
|
|
function useNotificationActions(params: {
|
|
userPubkey: string | null
|
|
setNotifications: (value: Notification[]) => void
|
|
}): {
|
|
markAsRead: (notificationId: string) => void
|
|
markAllAsRead: () => void
|
|
deleteNotification: (notificationId: string) => void
|
|
} {
|
|
const markAsRead = useCallback((notificationId: string): void => {
|
|
if (!params.userPubkey) {
|
|
return
|
|
}
|
|
void markAsReadAndRefresh({ notificationId, setNotifications: params.setNotifications })
|
|
}, [params.userPubkey, params.setNotifications])
|
|
|
|
const markAllAsRead = useCallback((): void => {
|
|
if (!params.userPubkey) {
|
|
return
|
|
}
|
|
void markAllAsReadAndRefresh({ setNotifications: params.setNotifications })
|
|
}, [params.userPubkey, params.setNotifications])
|
|
|
|
const deleteNotification = useCallback((notificationId: string): void => {
|
|
if (!params.userPubkey) {
|
|
return
|
|
}
|
|
void deleteNotificationAndRefresh({ notificationId, setNotifications: params.setNotifications })
|
|
}, [params.userPubkey, params.setNotifications])
|
|
|
|
return { markAsRead, markAllAsRead, deleteNotification }
|
|
}
|
|
|
|
async function loadAndSetNotifications(params: {
|
|
setNotifications: (value: Notification[]) => void
|
|
setLoading: (value: boolean) => void
|
|
}): Promise<void> {
|
|
try {
|
|
params.setLoading(true)
|
|
params.setNotifications(await notificationService.getAllNotifications(MAX_NOTIFICATIONS))
|
|
} catch (error) {
|
|
console.error('[useNotifications] Error loading notifications:', error)
|
|
} finally {
|
|
params.setLoading(false)
|
|
}
|
|
}
|
|
|
|
async function refreshNotifications(params: { setNotifications: (value: Notification[]) => void }): Promise<void> {
|
|
params.setNotifications(await notificationService.getAllNotifications(MAX_NOTIFICATIONS))
|
|
}
|
|
|
|
async function markAsReadAndRefresh(params: {
|
|
notificationId: string
|
|
setNotifications: (value: Notification[]) => void
|
|
}): Promise<void> {
|
|
try {
|
|
await notificationService.markAsRead(params.notificationId)
|
|
await refreshNotifications({ setNotifications: params.setNotifications })
|
|
} catch (error) {
|
|
console.error('[useNotifications] Error marking notification as read:', error)
|
|
}
|
|
}
|
|
|
|
async function markAllAsReadAndRefresh(params: {
|
|
setNotifications: (value: Notification[]) => void
|
|
}): Promise<void> {
|
|
try {
|
|
await notificationService.markAllAsRead()
|
|
await refreshNotifications({ setNotifications: params.setNotifications })
|
|
} catch (error) {
|
|
console.error('[useNotifications] Error marking all as read:', error)
|
|
}
|
|
}
|
|
|
|
async function deleteNotificationAndRefresh(params: {
|
|
notificationId: string
|
|
setNotifications: (value: Notification[]) => void
|
|
}): Promise<void> {
|
|
try {
|
|
await notificationService.deleteNotification(params.notificationId)
|
|
await refreshNotifications({ setNotifications: params.setNotifications })
|
|
} catch (error) {
|
|
console.error('[useNotifications] Error deleting notification:', error)
|
|
}
|
|
}
|