/** * Notifications Service - Polls and manages user notifications */ import { directus } from './directus.js' import { client } from './directus/client.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 if (!auth.isLoggedIn()) { this.destroy() 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) { if (e.status === 401 || e.status === 403) { this.stopPolling() } } } 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 = async () => { if (document.visibilityState === 'visible') { if (client._refreshPromise) { await client._refreshPromise } 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()