116 lines
2.9 KiB
JavaScript
116 lines
2.9 KiB
JavaScript
/**
|
|
* Notifications Service - Polls and manages user notifications
|
|
*/
|
|
|
|
import { directus } from './directus.js'
|
|
import { auth } from './auth.js'
|
|
|
|
class NotificationsService {
|
|
constructor() {
|
|
this.unreadCount = 0
|
|
this.notifications = []
|
|
this.listeners = new Set()
|
|
this.pollTimer = null
|
|
this.pollInterval = 60 * 1000 // 60 seconds
|
|
this.userHash = null
|
|
}
|
|
|
|
async init() {
|
|
if (!auth.isLoggedIn()) return
|
|
|
|
this.userHash = await this._getUserHash()
|
|
if (!this.userHash) return
|
|
|
|
await this.refresh()
|
|
this.startPolling()
|
|
}
|
|
|
|
async _getUserHash() {
|
|
const user = await auth.getUser()
|
|
return user?.id || null
|
|
}
|
|
|
|
async refresh() {
|
|
if (!this.userHash) return
|
|
|
|
try {
|
|
const [count, notifications] = await Promise.all([
|
|
directus.getUnreadCount(this.userHash),
|
|
directus.getNotifications(this.userHash)
|
|
])
|
|
this.unreadCount = count
|
|
this.notifications = notifications
|
|
this.notify()
|
|
} catch (e) {
|
|
console.error('Failed to fetch notifications:', e)
|
|
}
|
|
}
|
|
|
|
startPolling() {
|
|
this.stopPolling()
|
|
this.pollTimer = setInterval(() => this.refresh(), this.pollInterval)
|
|
|
|
document.addEventListener('visibilitychange', this._onVisibility)
|
|
}
|
|
|
|
stopPolling() {
|
|
if (this.pollTimer) {
|
|
clearInterval(this.pollTimer)
|
|
this.pollTimer = null
|
|
}
|
|
document.removeEventListener('visibilitychange', this._onVisibility)
|
|
}
|
|
|
|
_onVisibility = () => {
|
|
if (document.visibilityState === 'visible') {
|
|
this.refresh()
|
|
}
|
|
}
|
|
|
|
async markRead(id) {
|
|
await directus.markNotificationRead(id)
|
|
const n = this.notifications.find(n => n.id === id)
|
|
if (n) {
|
|
n.read = true
|
|
this.unreadCount = Math.max(0, this.unreadCount - 1)
|
|
this.notify()
|
|
}
|
|
}
|
|
|
|
async markAllRead() {
|
|
if (!this.userHash) return
|
|
await directus.markAllNotificationsRead(this.userHash)
|
|
this.notifications.forEach(n => n.read = true)
|
|
this.unreadCount = 0
|
|
this.notify()
|
|
}
|
|
|
|
async remove(id) {
|
|
await directus.deleteNotification(id)
|
|
this.notifications = this.notifications.filter(n => n.id !== id)
|
|
this.unreadCount = this.notifications.filter(n => !n.read).length
|
|
this.notify()
|
|
}
|
|
|
|
subscribe(callback) {
|
|
this.listeners.add(callback)
|
|
return () => this.listeners.delete(callback)
|
|
}
|
|
|
|
notify() {
|
|
for (const cb of this.listeners) {
|
|
cb(this.unreadCount, this.notifications)
|
|
}
|
|
}
|
|
|
|
destroy() {
|
|
this.stopPolling()
|
|
this.listeners.clear()
|
|
this.notifications = []
|
|
this.unreadCount = 0
|
|
this.userHash = null
|
|
}
|
|
}
|
|
|
|
export const notificationsService = new NotificationsService()
|