import React, { useEffect, useRef, useCallback } from 'react'; import { useCallState } from '@custom/shared/contexts/CallProvider'; const EMOJI_MAP = { fire: '🔥', squid: '🦑', laugh: '🤣', }; export const FlyingEmojisOverlay = () => { const { callObject } = useCallState(); const overlayRef = useRef(); // -- Handlers const handleRemoveFlyingEmoji = useCallback((node) => { if (!overlayRef.current) return; overlayRef.current.removeChild(node); }, []); const handleDisplayFlyingEmoji = useCallback( (emoji) => { if (!overlayRef.current) { return; } console.log(`⭐ Displaying flying emoji: ${emoji}`); const node = document.createElement('div'); node.appendChild(document.createTextNode(EMOJI_MAP[emoji])); node.className = Math.random() * 1 > 0.5 ? 'emoji wiggle-1' : 'emoji wiggle-2'; node.style.transform = `rotate(${-30 + Math.random() * 60}deg)`; node.style.left = `${Math.random() * 100}%`; node.src = ''; overlayRef.current.appendChild(node); node.addEventListener('animationend', (e) => handleRemoveFlyingEmoji(e.target) ); }, [handleRemoveFlyingEmoji] ); const handleReceiveFlyingEmoji = useCallback( (e) => { if (!overlayRef.current) { return; } console.log(`🚨 New emoji message received: ${e.data.message}`); handleDisplayFlyingEmoji(e.data.message); }, [handleDisplayFlyingEmoji] ); // -- Effects // Listen for new app messages and show new flying emojis useEffect(() => { if (!callObject) { return false; } console.log(`⭐ Listening for flying emojis...`); callObject.on('app-message', handleReceiveFlyingEmoji); return () => callObject.off('app-message', handleReceiveFlyingEmoji); }, [callObject, handleReceiveFlyingEmoji]); // Listen to window events to show local user emojis and send the emoji to all participants on the call useEffect(() => { if (!callObject) { return false; } function handleSendFlyingEmoji(e) { const { emoji } = e.detail; console.log(`⭐ Sending flying emoji: ${emoji}`); if (emoji) { callObject.sendAppMessage({ message: `${emoji}` }, '*'); handleDisplayFlyingEmoji(emoji); } } window.addEventListener('reaction_added', handleSendFlyingEmoji); return () => window.removeEventListener('reaction_added', handleSendFlyingEmoji); }, [callObject, handleDisplayFlyingEmoji]); // Remove all event listeners on unmount to prevent console warnings useEffect( () => () => overlayRef.current?.childNodes.forEach((n) => n.removeEventListener('animationend', handleRemoveFlyingEmoji) ), [handleRemoveFlyingEmoji] ); return (