refactor Notifications rc
This commit is contained in:
parent
b48c9817fd
commit
1a8b3d3f91
@ -207,15 +207,24 @@ export function Email() {
|
|||||||
|
|
||||||
// Dispatch event for Outlook-style notifications (only for new emails)
|
// Dispatch event for Outlook-style notifications (only for new emails)
|
||||||
if (previousCount >= 0 && currentUnreadCount > previousCount) {
|
if (previousCount >= 0 && currentUnreadCount > previousCount) {
|
||||||
|
// Get only the newly arrived emails (the difference)
|
||||||
const newEmails = transformedEmails
|
const newEmails = transformedEmails
|
||||||
.filter(e => !e.read)
|
.filter(e => !e.read)
|
||||||
.slice(0, currentUnreadCount - previousCount); // Only the new ones
|
.slice(0, currentUnreadCount - previousCount); // Only the new ones
|
||||||
|
|
||||||
if (newEmails.length > 0) {
|
if (newEmails.length > 0) {
|
||||||
|
console.log('[Email Widget] 📧 Dispatching new emails event', {
|
||||||
|
newEmailsCount: newEmails.length,
|
||||||
|
previousCount,
|
||||||
|
currentCount: currentUnreadCount,
|
||||||
|
});
|
||||||
|
|
||||||
window.dispatchEvent(new CustomEvent('new-emails-detected', {
|
window.dispatchEvent(new CustomEvent('new-emails-detected', {
|
||||||
detail: {
|
detail: {
|
||||||
emails: transformedEmails,
|
emails: transformedEmails,
|
||||||
accountMap: accountMap,
|
accountMap: accountMap,
|
||||||
|
previousCount,
|
||||||
|
currentCount: currentUnreadCount,
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|||||||
@ -11,6 +11,7 @@ import { clearAuthCookies, clearKeycloakCookies } from "@/lib/session";
|
|||||||
import { useRocketChatCalls } from "@/hooks/use-rocketchat-calls";
|
import { useRocketChatCalls } from "@/hooks/use-rocketchat-calls";
|
||||||
import { IncomingCallNotification } from "@/components/incoming-call-notification";
|
import { IncomingCallNotification } from "@/components/incoming-call-notification";
|
||||||
import { useEmailNotifications } from "@/hooks/use-email-notifications";
|
import { useEmailNotifications } from "@/hooks/use-email-notifications";
|
||||||
|
import { useRocketChatMessageNotifications } from "@/hooks/use-rocketchat-message-notifications";
|
||||||
import { OutlookNotification } from "@/components/outlook-notification";
|
import { OutlookNotification } from "@/components/outlook-notification";
|
||||||
import { NotificationStack } from "@/components/notification-stack";
|
import { NotificationStack } from "@/components/notification-stack";
|
||||||
|
|
||||||
@ -244,6 +245,15 @@ export function LayoutWrapper({ children, isSignInPage, isAuthenticated }: Layou
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
{messageNotification && (
|
||||||
|
<OutlookNotification
|
||||||
|
notification={messageNotification}
|
||||||
|
onDismiss={() => {
|
||||||
|
console.log('[LayoutWrapper] RocketChat message notification dismissed');
|
||||||
|
setMessageNotification(null);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
</NotificationStack>
|
</NotificationStack>
|
||||||
)}
|
)}
|
||||||
</AuthCheck>
|
</AuthCheck>
|
||||||
|
|||||||
@ -87,6 +87,7 @@ export function Parole() {
|
|||||||
|
|
||||||
// Si le count a changé (ou premier chargement), déclencher notification
|
// Si le count a changé (ou premier chargement), déclencher notification
|
||||||
if (currentUnreadCount !== lastUnreadCountRef.current) {
|
if (currentUnreadCount !== lastUnreadCountRef.current) {
|
||||||
|
const previousCount = lastUnreadCountRef.current;
|
||||||
lastUnreadCountRef.current = currentUnreadCount;
|
lastUnreadCountRef.current = currentUnreadCount;
|
||||||
|
|
||||||
// Préparer les items pour les notifications (messages, max 10)
|
// Préparer les items pour les notifications (messages, max 10)
|
||||||
@ -104,12 +105,35 @@ export function Parole() {
|
|||||||
},
|
},
|
||||||
}));
|
}));
|
||||||
|
|
||||||
// Déclencher notification update
|
// Déclencher notification update (for badge)
|
||||||
await triggerNotification({
|
await triggerNotification({
|
||||||
source: 'rocketchat',
|
source: 'rocketchat',
|
||||||
count: currentUnreadCount,
|
count: currentUnreadCount,
|
||||||
items: notificationItems,
|
items: notificationItems,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Dispatch event for Outlook-style notifications (only for new messages)
|
||||||
|
// We detect new messages by comparing message count, not unread count
|
||||||
|
// because new messages might be read immediately
|
||||||
|
if (previousCount >= 0 && data.messages.length > 0) {
|
||||||
|
// Get the most recent messages (first ones in the array, sorted by date desc)
|
||||||
|
// We'll let the hook determine which are truly new
|
||||||
|
const totalMessages = data.messages.length;
|
||||||
|
|
||||||
|
console.log('[Parole Widget] 💬 Dispatching messages event', {
|
||||||
|
totalMessages,
|
||||||
|
previousUnreadCount: previousCount,
|
||||||
|
currentUnreadCount,
|
||||||
|
});
|
||||||
|
|
||||||
|
window.dispatchEvent(new CustomEvent('new-messages-detected', {
|
||||||
|
detail: {
|
||||||
|
messages: data.messages,
|
||||||
|
previousCount: previousCount,
|
||||||
|
currentCount: currentUnreadCount,
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
setMessages(data.messages);
|
setMessages(data.messages);
|
||||||
|
|||||||
@ -10,30 +10,44 @@ export function useEmailNotifications() {
|
|||||||
const lastEmailIdsRef = useRef<Set<string>>(new Set());
|
const lastEmailIdsRef = useRef<Set<string>>(new Set());
|
||||||
const notificationQueueRef = useRef<OutlookNotificationData[]>([]);
|
const notificationQueueRef = useRef<OutlookNotificationData[]>([]);
|
||||||
const isShowingRef = useRef(false);
|
const isShowingRef = useRef(false);
|
||||||
|
const isInitializedRef = useRef(false);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
// Listen for new emails via custom event
|
// Listen for new emails via custom event
|
||||||
const handleNewEmails = (event: CustomEvent) => {
|
const handleNewEmails = (event: CustomEvent) => {
|
||||||
const emails = event.detail?.emails || [];
|
const emails = event.detail?.emails || [];
|
||||||
const accountMap = event.detail?.accountMap || new Map();
|
const accountMap = event.detail?.accountMap || new Map();
|
||||||
|
const previousCount = event.detail?.previousCount ?? -1;
|
||||||
|
const currentCount = event.detail?.currentCount ?? 0;
|
||||||
|
|
||||||
if (!emails || emails.length === 0) return;
|
if (!emails || emails.length === 0) return;
|
||||||
|
|
||||||
// Find new emails (not in lastEmailIdsRef)
|
// On first load, just store all email IDs without showing notifications
|
||||||
const newEmails = emails.filter((email: any) => {
|
if (!isInitializedRef.current) {
|
||||||
const emailId = email.id;
|
console.log('[useEmailNotifications] Initializing - storing existing email IDs without notifications');
|
||||||
if (!lastEmailIdsRef.current.has(emailId) && !email.read) {
|
lastEmailIdsRef.current = new Set(emails.map((e: any) => e.id));
|
||||||
lastEmailIdsRef.current.add(emailId);
|
isInitializedRef.current = true;
|
||||||
return true;
|
return;
|
||||||
}
|
}
|
||||||
return false;
|
|
||||||
});
|
// Only show notifications if the count increased (new emails arrived)
|
||||||
|
// AND we have a previous count to compare with
|
||||||
|
if (previousCount >= 0 && currentCount > previousCount) {
|
||||||
|
// Find new emails (not in lastEmailIdsRef) - these are the ones that just arrived
|
||||||
|
const newEmails = emails
|
||||||
|
.filter((email: any) => {
|
||||||
|
const emailId = email.id;
|
||||||
|
return !lastEmailIdsRef.current.has(emailId) && !email.read;
|
||||||
|
})
|
||||||
|
.slice(0, 5); // Limit to 5 most recent new emails
|
||||||
|
|
||||||
// Update lastEmailIdsRef with all current emails
|
// Update lastEmailIdsRef with all current emails
|
||||||
lastEmailIdsRef.current = new Set(emails.map((e: any) => e.id));
|
lastEmailIdsRef.current = new Set(emails.map((e: any) => e.id));
|
||||||
|
|
||||||
// If there are new unread emails, queue them for notification
|
// If there are new unread emails, queue them for notification
|
||||||
if (newEmails.length > 0) {
|
if (newEmails.length > 0) {
|
||||||
|
console.log('[useEmailNotifications] 📧 New emails detected:', newEmails.length);
|
||||||
|
|
||||||
newEmails.forEach((email: any) => {
|
newEmails.forEach((email: any) => {
|
||||||
const account = accountMap.get(email.accountId);
|
const account = accountMap.get(email.accountId);
|
||||||
const notification: OutlookNotificationData = {
|
const notification: OutlookNotificationData = {
|
||||||
@ -69,6 +83,10 @@ export function useEmailNotifications() {
|
|||||||
showNextNotification();
|
showNextNotification();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
// Just update the email IDs without showing notifications
|
||||||
|
lastEmailIdsRef.current = new Set(emails.map((e: any) => e.id));
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
window.addEventListener('new-emails-detected', handleNewEmails as EventListener);
|
window.addEventListener('new-emails-detected', handleNewEmails as EventListener);
|
||||||
|
|||||||
128
hooks/use-rocketchat-message-notifications.ts
Normal file
128
hooks/use-rocketchat-message-notifications.ts
Normal file
@ -0,0 +1,128 @@
|
|||||||
|
import { useState, useEffect, useRef } from 'react';
|
||||||
|
import { MessageSquare } from 'lucide-react';
|
||||||
|
import { OutlookNotificationData } from '@/components/outlook-notification';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hook to manage RocketChat message notifications and show Outlook-style notifications
|
||||||
|
*/
|
||||||
|
export function useRocketChatMessageNotifications() {
|
||||||
|
const [messageNotification, setMessageNotification] = useState<OutlookNotificationData | null>(null);
|
||||||
|
const lastMessageIdsRef = useRef<Set<string>>(new Set());
|
||||||
|
const notificationQueueRef = useRef<OutlookNotificationData[]>([]);
|
||||||
|
const isShowingRef = useRef(false);
|
||||||
|
const isInitializedRef = useRef(false);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
// Listen for new messages via custom event
|
||||||
|
const handleNewMessages = (event: CustomEvent) => {
|
||||||
|
const messages = event.detail?.messages || [];
|
||||||
|
const previousCount = event.detail?.previousCount ?? -1;
|
||||||
|
const currentCount = event.detail?.currentCount ?? 0;
|
||||||
|
|
||||||
|
if (!messages || messages.length === 0) return;
|
||||||
|
|
||||||
|
// On first load, just store all message IDs without showing notifications
|
||||||
|
if (!isInitializedRef.current) {
|
||||||
|
console.log('[useRocketChatMessageNotifications] Initializing - storing existing message IDs without notifications');
|
||||||
|
lastMessageIdsRef.current = new Set(messages.map((m: any) => m.id));
|
||||||
|
isInitializedRef.current = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only show notifications if the count increased (new messages arrived)
|
||||||
|
// AND we have a previous count to compare with
|
||||||
|
if (previousCount >= 0 && currentCount > previousCount) {
|
||||||
|
// Find new messages (not in lastMessageIdsRef) - these are the ones that just arrived
|
||||||
|
const newMessages = messages
|
||||||
|
.filter((message: any) => {
|
||||||
|
const messageId = message.id;
|
||||||
|
return !lastMessageIdsRef.current.has(messageId);
|
||||||
|
})
|
||||||
|
.slice(0, 5); // Limit to 5 most recent new messages
|
||||||
|
|
||||||
|
// Update lastMessageIdsRef with all current messages
|
||||||
|
lastMessageIdsRef.current = new Set(messages.map((m: any) => m.id));
|
||||||
|
|
||||||
|
// If there are new messages, queue them for notification
|
||||||
|
if (newMessages.length > 0) {
|
||||||
|
console.log('[useRocketChatMessageNotifications] 💬 New messages detected:', newMessages.length);
|
||||||
|
|
||||||
|
newMessages.forEach((message: any) => {
|
||||||
|
const senderName = message.sender?.name || message.sender?.username || 'Inconnu';
|
||||||
|
const roomName = message.roomName || 'Chat';
|
||||||
|
const messageText = message.text || message.message || '';
|
||||||
|
|
||||||
|
const notification: OutlookNotificationData = {
|
||||||
|
id: `rocketchat-${message.id}-${Date.now()}`,
|
||||||
|
source: 'rocketchat',
|
||||||
|
title: 'Parole',
|
||||||
|
subtitle: 'Nouveau message',
|
||||||
|
message: `${senderName} dans ${roomName}: ${messageText.length > 50 ? messageText.substring(0, 50) + '...' : messageText}`,
|
||||||
|
icon: MessageSquare,
|
||||||
|
iconColor: 'text-purple-600',
|
||||||
|
iconBgColor: 'bg-purple-100',
|
||||||
|
borderColor: 'border-purple-500',
|
||||||
|
link: '/parole',
|
||||||
|
timestamp: new Date(message.rawTimestamp || message.timestamp),
|
||||||
|
autoDismiss: 10000, // 10 seconds for messages
|
||||||
|
actions: [
|
||||||
|
{
|
||||||
|
label: 'Ouvrir',
|
||||||
|
onClick: () => {
|
||||||
|
window.location.href = '/parole';
|
||||||
|
},
|
||||||
|
variant: 'default',
|
||||||
|
className: 'bg-purple-600 hover:bg-purple-700 text-white',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
notificationQueueRef.current.push(notification);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Show the first notification if none is currently showing
|
||||||
|
if (!isShowingRef.current && notificationQueueRef.current.length > 0) {
|
||||||
|
showNextNotification();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Just update the message IDs without showing notifications
|
||||||
|
lastMessageIdsRef.current = new Set(messages.map((m: any) => m.id));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
window.addEventListener('new-messages-detected', handleNewMessages as EventListener);
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
window.removeEventListener('new-messages-detected', handleNewMessages as EventListener);
|
||||||
|
};
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const showNextNotification = () => {
|
||||||
|
if (notificationQueueRef.current.length === 0) {
|
||||||
|
isShowingRef.current = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const nextNotification = notificationQueueRef.current.shift();
|
||||||
|
if (nextNotification) {
|
||||||
|
isShowingRef.current = true;
|
||||||
|
setMessageNotification(nextNotification);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleDismiss = () => {
|
||||||
|
setMessageNotification(null);
|
||||||
|
isShowingRef.current = false;
|
||||||
|
|
||||||
|
// Show next notification after a short delay
|
||||||
|
setTimeout(() => {
|
||||||
|
showNextNotification();
|
||||||
|
}, 500);
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
messageNotification,
|
||||||
|
setMessageNotification: handleDismiss,
|
||||||
|
};
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user