'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('/api/auth/me', fetcher); const { data: conversations } = useSWR( currentUser ? '/api/conversations' : null, fetcher, { refreshInterval: 3000, // Vérifier toutes les 3 secondes } ); const lastMessageIdsRef = useRef>(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(() => { if (conversations && Array.isArray(conversations) && !initializedRef.current) { conversations.forEach((conversation) => { if (conversation.lastMessage) { lastMessageIdsRef.current.set(conversation.id, conversation.lastMessage.id); } }); initializedRef.current = true; } }, [conversations]); // Détecter les nouveaux messages useEffect(() => { if (!conversations || !Array.isArray(conversations) || !currentUser || !initializedRef.current) return; 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 }