@raphab3/hermes-notifier
Version:
JavaScript/React plugin for Hermes notifications system with SSE support
161 lines (160 loc) • 5.42 kB
JavaScript
/**
* React hooks for Hermes notifications
*/
import { useEffect, useState, useCallback, useRef } from 'react';
import { HermesNotifier } from './index';
/**
* Hook for managing Hermes notifications in React components
*/
export function useHermesNotifications(config) {
const [notifications, setNotifications] = useState([]);
const [connectionStatus, setConnectionStatus] = useState({
connected: false,
reconnecting: false,
});
const [unreadCount, setUnreadCount] = useState(0);
const notifierRef = useRef(null);
// Initialize the notifier
useEffect(() => {
notifierRef.current = new HermesNotifier(config);
return () => {
if (notifierRef.current) {
notifierRef.current.disconnect();
}
};
}, [config]);
// Set up event handlers
useEffect(() => {
const notifier = notifierRef.current;
if (!notifier)
return;
// Handle new notifications
const unsubscribeNotifications = notifier.onNotification((notification) => {
setNotifications(prev => [notification, ...prev]);
// Update unread count if notification is unread
if (!notification.is_read) {
setUnreadCount(prev => prev + 1);
}
});
// Handle connection status changes
const unsubscribeConnection = notifier.onConnectionChange((status) => {
setConnectionStatus(status);
});
// Handle errors
const unsubscribeErrors = notifier.onError((error) => {
console.error('Hermes notification error:', error);
});
return () => {
unsubscribeNotifications();
unsubscribeConnection();
unsubscribeErrors();
};
}, []);
// Connect to notifications
const connect = useCallback(async () => {
if (notifierRef.current) {
await notifierRef.current.connect();
// Get initial unread count
try {
const count = await notifierRef.current.getUnreadCount();
setUnreadCount(count);
}
catch (error) {
console.error('Failed to get initial unread count:', error);
}
}
}, []);
// Disconnect from notifications
const disconnect = useCallback(() => {
if (notifierRef.current) {
notifierRef.current.disconnect();
}
}, []);
// Mark notification as read
const markAsRead = useCallback(async (notificationId) => {
if (notifierRef.current) {
try {
await notifierRef.current.markAsRead(notificationId);
// Update local state
setNotifications(prev => prev.map(n => n.id === notificationId
? { ...n, is_read: true, read_at: new Date().toISOString() }
: n));
// Update unread count
setUnreadCount(prev => Math.max(0, prev - 1));
}
catch (error) {
console.error('Failed to mark notification as read:', error);
throw error;
}
}
}, []);
// Clear all notifications from local state
const clearNotifications = useCallback(() => {
setNotifications([]);
}, []);
// Send test notification (for development)
const sendTestNotification = useCallback(async (title, body) => {
if (notifierRef.current) {
await notifierRef.current.sendTestNotification(title, body);
}
}, []);
return {
notifications,
connectionStatus,
unreadCount,
connect,
disconnect,
markAsRead,
clearNotifications,
sendTestNotification,
isConnected: connectionStatus.connected,
};
}
/**
* Hook for simple notification display (just the latest notification)
*/
export function useLatestNotification(config) {
const [latestNotification, setLatestNotification] = useState(null);
const [connectionStatus, setConnectionStatus] = useState({
connected: false,
reconnecting: false,
});
const notifierRef = useRef(null);
useEffect(() => {
notifierRef.current = new HermesNotifier(config);
const unsubscribeNotifications = notifierRef.current.onNotification((notification) => {
setLatestNotification(notification);
});
const unsubscribeConnection = notifierRef.current.onConnectionChange((status) => {
setConnectionStatus(status);
});
return () => {
if (notifierRef.current) {
notifierRef.current.disconnect();
}
unsubscribeNotifications();
unsubscribeConnection();
};
}, [config]);
const connect = useCallback(async () => {
if (notifierRef.current) {
await notifierRef.current.connect();
}
}, []);
const disconnect = useCallback(() => {
if (notifierRef.current) {
notifierRef.current.disconnect();
}
}, []);
const clearLatest = useCallback(() => {
setLatestNotification(null);
}, []);
return {
latestNotification,
connectionStatus,
connect,
disconnect,
clearLatest,
isConnected: connectionStatus.connected,
};
}