UNPKG

@churchapps/apphelper

Version:

Library of helper functions for React and NextJS ChurchApps

176 lines 6.57 kB
import { SocketHelper } from "./SocketHelper"; import { ApiHelper } from "@churchapps/helpers"; export class NotificationService { constructor() { this.counts = { notificationCount: 0, pmCount: 0 }; this.listeners = []; this.isInitialized = false; this.currentPersonId = null; this.loadTimeout = null; } static getInstance() { if (!NotificationService.instance) { NotificationService.instance = new NotificationService(); } return NotificationService.instance; } /** * Initialize the notification service with user context */ async initialize(context) { if (this.isInitialized) return; try { // Store current person ID for conversation counting this.currentPersonId = context?.person?.id || null; // Initialize WebSocket connection await SocketHelper.init(); // Set person/church context for websocket if (context?.person?.id && context?.userChurch?.church?.id) { SocketHelper.setPersonChurch({ personId: context.person.id, churchId: context.userChurch.church.id }); } // Register handlers for notification updates this.registerWebSocketHandlers(); // Load initial notification counts await this.loadNotificationCounts(); this.isInitialized = true; } catch (error) { console.error("❌ Failed to initialize NotificationService:", error); throw error; } } /** * Register websocket handlers for real-time notification updates */ registerWebSocketHandlers() { // Handler for new private messages SocketHelper.addHandler("privateMessage", "NotificationService-PM", (data) => { console.log('🔔 NotificationService: New private message received, updating counts'); this.debouncedLoadNotificationCounts(); }); // Handler for general notifications SocketHelper.addHandler("notification", "NotificationService-Notification", (data) => { console.log('🔔 NotificationService: New notification received, updating counts'); this.debouncedLoadNotificationCounts(); }); // Handler for message updates that could affect notification counts SocketHelper.addHandler("message", "NotificationService-MessageUpdate", (data) => { // Only update counts if the message update involves the current person if (data?.message?.personId === this.currentPersonId || data?.notifyPersonId === this.currentPersonId) { console.log('🔔 NotificationService: Message update affecting current user, updating counts'); this.debouncedLoadNotificationCounts(); } }); // Handler for reconnect events SocketHelper.addHandler("reconnect", "NotificationService-Reconnect", (data) => { console.log('🔔 NotificationService: WebSocket reconnected, refreshing counts'); this.loadNotificationCounts(); // Don't debounce reconnect - need immediate update }); } /** * Load notification counts from the API with debouncing */ debouncedLoadNotificationCounts() { if (this.loadTimeout) { clearTimeout(this.loadTimeout); } this.loadTimeout = setTimeout(() => { this.loadNotificationCounts(); }, 300); // 300ms debounce } /** * Load notification counts from the API */ async loadNotificationCounts() { try { // Use the unreadCount endpoint which returns both notification and PM counts const counts = await ApiHelper.get("/notifications/unreadCount", "MessagingApi"); const newCounts = { notificationCount: counts?.notificationCount || 0, pmCount: counts?.pmCount || 0 }; // Update counts and notify listeners this.updateCounts(newCounts); } catch (error) { console.error("❌ Failed to load notification counts:", error); // Don't throw - just log the error and keep existing counts } } /** * Update counts and notify all listeners */ updateCounts(newCounts) { const countsChanged = this.counts.notificationCount !== newCounts.notificationCount || this.counts.pmCount !== newCounts.pmCount; if (countsChanged) { this.counts = { ...newCounts }; // Notify all listeners this.listeners.forEach(listener => { try { listener(this.counts); } catch (error) { console.error("❌ Error in notification listener:", error); } }); } } /** * Subscribe to notification count changes */ subscribe(listener) { this.listeners.push(listener); // Immediately call with current counts listener(this.counts); // Return unsubscribe function return () => { this.listeners = this.listeners.filter(l => l !== listener); }; } /** * Get current notification counts */ getCounts() { return { ...this.counts }; } /** * Manually refresh notification counts */ async refresh() { await this.loadNotificationCounts(); } /** * Cleanup the service */ cleanup() { // Clear any pending timeout if (this.loadTimeout) { clearTimeout(this.loadTimeout); this.loadTimeout = null; } // Remove websocket handlers SocketHelper.removeHandler("NotificationService-PM"); SocketHelper.removeHandler("NotificationService-Notification"); SocketHelper.removeHandler("NotificationService-MessageUpdate"); SocketHelper.removeHandler("NotificationService-Reconnect"); // Clear listeners this.listeners = []; // Reset state this.counts = { notificationCount: 0, pmCount: 0 }; this.currentPersonId = null; this.isInitialized = false; } /** * Check if service is initialized */ isReady() { return this.isInitialized && SocketHelper.isConnected(); } } //# sourceMappingURL=NotificationService.js.map