Files
MAD-Platform/components/MessageNotifications.tsx

170 lines
5.7 KiB
TypeScript
Raw Normal View History

2026-01-21 18:13:35 +01:00
'use client';
import { useEffect, useRef } from 'react';
import useSWR from 'swr';
interface User {
id: string;
email: string;
name: string | null;
}
interface LastMessage {
id: string;
content: string | null;
senderId: string;
senderName: string;
createdAt: string;
hasFiles: boolean;
}
interface Conversation {
id: string;
name: string | null;
type: string;
displayName: string;
participants: Array<{ id: string; email: string; name: string | null }>;
lastMessage: LastMessage | null;
updatedAt: string;
createdAt: string;
}
const fetcher = (url: string) => fetch(url).then((res) => res.json());
export default function MessageNotifications() {
const { data: currentUser } = useSWR<User>('/api/auth/me', fetcher);
const { data: conversations } = useSWR<Conversation[]>(
currentUser ? '/api/conversations' : null,
fetcher,
{
refreshInterval: 3000, // Vérifier toutes les 3 secondes
}
);
const lastMessageIdsRef = useRef<Map<string, string>>(new Map());
const initializedRef = useRef(false);
// Fonction pour jouer le son de notification
const playNotificationSound = () => {
try {
const AudioContext = window.AudioContext || (window as any).webkitAudioContext;
const audioContext = new AudioContext();
const oscillator = audioContext.createOscillator();
const gainNode = audioContext.createGain();
oscillator.connect(gainNode);
gainNode.connect(audioContext.destination);
// Son de notification agréable (deux tons)
oscillator.frequency.value = 800;
oscillator.type = 'sine';
gainNode.gain.setValueAtTime(0.3, audioContext.currentTime);
gainNode.gain.exponentialRampToValueAtTime(0.01, audioContext.currentTime + 0.2);
oscillator.start(audioContext.currentTime);
oscillator.stop(audioContext.currentTime + 0.2);
// Deuxième ton après une courte pause
setTimeout(() => {
const oscillator2 = audioContext.createOscillator();
const gainNode2 = audioContext.createGain();
oscillator2.connect(gainNode2);
gainNode2.connect(audioContext.destination);
oscillator2.frequency.value = 1000;
oscillator2.type = 'sine';
gainNode2.gain.setValueAtTime(0.3, audioContext.currentTime);
gainNode2.gain.exponentialRampToValueAtTime(0.01, audioContext.currentTime + 0.2);
oscillator2.start(audioContext.currentTime);
oscillator2.stop(audioContext.currentTime + 0.2);
}, 150);
} catch (error) {
console.error('Erreur lors de la lecture du son:', error);
}
};
// Demander la permission pour les notifications
useEffect(() => {
if ('Notification' in window && Notification.permission === 'default') {
Notification.requestPermission().catch(console.error);
}
}, []);
// Initialiser les IDs des messages au premier chargement
useEffect(() => {
2026-01-22 16:49:51 +01:00
if (conversations && Array.isArray(conversations) && !initializedRef.current) {
2026-01-21 18:13:35 +01:00
conversations.forEach((conversation) => {
if (conversation.lastMessage) {
lastMessageIdsRef.current.set(conversation.id, conversation.lastMessage.id);
}
});
initializedRef.current = true;
}
}, [conversations]);
// Détecter les nouveaux messages
useEffect(() => {
2026-01-22 16:49:51 +01:00
if (!conversations || !Array.isArray(conversations) || !currentUser || !initializedRef.current) return;
2026-01-21 18:13:35 +01:00
conversations.forEach((conversation) => {
if (!conversation.lastMessage) return;
const lastMessageId = lastMessageIdsRef.current.get(conversation.id);
const currentMessageId = conversation.lastMessage.id;
// Nouveau message détecté
if (lastMessageId && lastMessageId !== currentMessageId) {
// Vérifier si le message n'est pas de l'utilisateur actuel
if (conversation.lastMessage.senderId !== currentUser.id) {
// Vérifier si on est sur la page de messagerie
const isOnMessagingPage = window.location.pathname === '/dashboard/messagerie';
// Jouer le son seulement si on n'est pas sur la page de messagerie
// (sur la page de messagerie, on voit déjà les messages en temps réel)
if (!isOnMessagingPage) {
playNotificationSound();
}
// Afficher la notification si on n'est pas sur la page de messagerie
if (!isOnMessagingPage && 'Notification' in window && Notification.permission === 'granted') {
const messageContent = conversation.lastMessage.hasFiles && !conversation.lastMessage.content
? '📎 Fichier'
: conversation.lastMessage.content || '📎 Fichier';
const notification = new Notification(
conversation.type === 'group' ? conversation.displayName : conversation.lastMessage.senderName,
{
body: messageContent.length > 100
? messageContent.substring(0, 100) + '...'
: messageContent,
icon: '/logo.svg',
badge: '/logo.svg',
tag: conversation.id, // Permet de remplacer les notifications de la même conversation
requireInteraction: false,
}
);
notification.onclick = () => {
window.focus();
window.location.href = '/dashboard/messagerie';
notification.close();
};
// Fermer automatiquement après 5 secondes
setTimeout(() => {
notification.close();
}, 5000);
}
}
}
// Mettre à jour l'ID du dernier message
lastMessageIdsRef.current.set(conversation.id, currentMessageId);
});
}, [conversations, currentUser]);
return null; // Ce composant ne rend rien visuellement
}