T.ME/BIBIL_0DAY
CasperSecurity


Server : Apache/2
System : Linux server-15-235-50-60 5.15.0-164-generic #174-Ubuntu SMP Fri Nov 14 20:25:16 UTC 2025 x86_64
User : gositeme ( 1004)
PHP Version : 8.2.29
Disable Function : exec,system,passthru,shell_exec,proc_close,proc_open,dl,popen,show_source,posix_kill,posix_mkfifo,posix_getpwuid,posix_setpgid,posix_setsid,posix_setuid,posix_setgid,posix_seteuid,posix_setegid,posix_uname
Directory :  /home/gositeme/domains/lavocat.ca/public_html/src/components/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Current File : /home/gositeme/domains/lavocat.ca/public_html/src/components/IncomingCallNotification.tsx
import React, { useEffect, useState, useRef } from 'react';
import { useWebSocket } from '../context/StableWebSocketContext';
import { motion, AnimatePresence } from 'framer-motion';
import { Phone, PhoneOff, Video, Check, X } from 'lucide-react';

const IncomingCallNotification: React.FC = () => {
  const { incomingVideoCall, acceptVideoCall, declineVideoCall, videoCallActive } = useWebSocket();
  const [isRinging, setIsRinging] = useState(false);
  const [isHandled, setIsHandled] = useState(false);
  const timeoutRef = useRef<NodeJS.Timeout | null>(null);

  // Start ringing animation when call comes in
  useEffect(() => {
    if (incomingVideoCall && !isHandled) {
      setIsRinging(true);
      
      // Auto-decline after 30 seconds
      timeoutRef.current = setTimeout(() => {
        console.log('📞 [DEBUG] Auto-declining call after 30 seconds');
        setIsHandled(true);
        setIsRinging(false);
        declineVideoCall();
      }, 30000);
    } else {
      setIsRinging(false);
      if (timeoutRef.current) {
        clearTimeout(timeoutRef.current);
        timeoutRef.current = null;
      }
    }

    return () => {
      if (timeoutRef.current) {
        clearTimeout(timeoutRef.current);
        timeoutRef.current = null;
      }
    };
  }, [incomingVideoCall, isHandled, declineVideoCall]);

  // ✅ Listen for call cancellation events
  useEffect(() => {
    const handleCallCancelled = (event: CustomEvent) => {
      const { senderId, senderName, reason } = event.detail;
      
      console.log('📞 [DEBUG] Received call cancellation:', { senderId, senderName, reason });
      
      // If there's an active incoming call from this sender, dismiss it
      if (incomingVideoCall && incomingVideoCall.senderId === senderId) {
        console.log('📞 [DEBUG] Dismissing incoming call notification due to cancellation');
        setIsHandled(true);
        setIsRinging(false);
        
        // Clear the timeout
        if (timeoutRef.current) {
          clearTimeout(timeoutRef.current);
          timeoutRef.current = null;
        }
      }
    };

    window.addEventListener('video-call-cancelled', handleCallCancelled as EventListener);

    return () => {
      window.removeEventListener('video-call-cancelled', handleCallCancelled as EventListener);
    };
  }, [incomingVideoCall]);

  const handleAccept = () => {
    if (incomingVideoCall && !isHandled) {
      console.log('📞 [SIMPLE] YES pressed - accepting call');
      
      setIsHandled(true);
      setIsRinging(false);
      
      // Clear the timeout
      if (timeoutRef.current) {
        clearTimeout(timeoutRef.current);
        timeoutRef.current = null;
      }
      
      // ✅ DEAD SIMPLE: Just call the accept function
      // The WebSocket context will handle EVERYTHING
      acceptVideoCall(incomingVideoCall);
      
      console.log('📞 [SIMPLE] Done - video call should be starting');
    }
  };

  const handleDecline = () => {
    if (incomingVideoCall && !isHandled) {
      setIsHandled(true);
      setIsRinging(false);
      
      // Clear the timeout
      if (timeoutRef.current) {
        clearTimeout(timeoutRef.current);
        timeoutRef.current = null;
      }
      
      // Notify the caller that the call was rejected
      window.dispatchEvent(new CustomEvent('video-call-rejected', {
        detail: {
          senderId: incomingVideoCall.senderId,
          senderName: incomingVideoCall.senderName
        }
      }));
      
      declineVideoCall();
    }
  };

  // ✅ Don't show notification if video call is already active
  if (!incomingVideoCall || videoCallActive) return null;

  return (
    <AnimatePresence>
      <motion.div
        initial={{ opacity: 0, scale: 0.8 }}
        animate={{ opacity: 1, scale: 1 }}
        exit={{ opacity: 0, scale: 0.8 }}
        className="fixed inset-0 z-50 flex items-center justify-center bg-black bg-opacity-50"
      >
        <motion.div
          initial={{ opacity: 0, y: -50 }}
          animate={{ opacity: 1, y: 0 }}
          exit={{ opacity: 0, y: -50 }}
          className="bg-white dark:bg-gray-900 rounded-2xl shadow-2xl p-8 max-w-md w-full mx-4 text-center"
        >
          {/* Video call icon */}
          <motion.div
            animate={isRinging ? { scale: [1, 1.1, 1] } : {}}
            transition={{ duration: 1, repeat: Infinity }}
            className="w-20 h-20 bg-blue-500 rounded-full flex items-center justify-center mx-auto mb-6"
          >
            <Video className="h-10 w-10 text-white" />
          </motion.div>

          {/* Call info */}
          <h2 className="text-2xl font-bold text-gray-900 dark:text-white mb-2">
            📞 Incoming Video Call
          </h2>
          <p className="text-xl text-gray-600 dark:text-gray-300 mb-8">
            <strong>{incomingVideoCall.senderName}</strong> is calling you
          </p>

          {/* Large Yes/No buttons */}
          <div className="flex gap-6 justify-center">
            {/* NO Button */}
            <motion.button
              whileHover={{ scale: 1.05 }}
              whileTap={{ scale: 0.95 }}
              onClick={handleDecline}
              className="flex flex-col items-center gap-3 px-8 py-6 bg-red-500 hover:bg-red-600 text-white rounded-2xl font-bold text-xl transition-colors min-w-[120px]"
            >
              <X className="h-8 w-8" />
              NO
            </motion.button>
            
            {/* YES Button */}
            <motion.button
              whileHover={{ scale: 1.05 }}
              whileTap={{ scale: 0.95 }}
              onClick={handleAccept}
              className="flex flex-col items-center gap-3 px-8 py-6 bg-green-500 hover:bg-green-600 text-white rounded-2xl font-bold text-xl transition-colors min-w-[120px]"
            >
              <Check className="h-8 w-8" />
              YES
            </motion.button>
          </div>

          {/* Timer */}
          <div className="mt-6">
            <p className="text-sm text-gray-500 dark:text-gray-400">
              ⏰ Auto-declines in 30 seconds
            </p>
          </div>
        </motion.div>
      </motion.div>
    </AnimatePresence>
  );
};

export default IncomingCallNotification; 

CasperSecurity Mini