243 lines
7.1 KiB
JavaScript
243 lines
7.1 KiB
JavaScript
import React, { useEffect, useRef, useState } from "react";
|
||
import { useModalStore } from "../../../stores/modalStore.js";
|
||
|
||
export function VoiceCallModal() {
|
||
const { isOpen, type, data, onClose } = useModalStore();
|
||
const [isConnecting, setIsConnecting] = useState(true);
|
||
const [participants, setParticipants] = useState([]);
|
||
const videoRef = useRef(null);
|
||
|
||
const isModalOpen = isOpen && type === "voiceCall";
|
||
|
||
useEffect(() => {
|
||
if (isModalOpen) {
|
||
// Simulate connection
|
||
setTimeout(() => {
|
||
setIsConnecting(false);
|
||
setParticipants([
|
||
{ id: 1, name: "You", isMuted: false, isVideoOff: false },
|
||
]);
|
||
}, 1500);
|
||
}
|
||
}, [isModalOpen]);
|
||
|
||
if (!isModalOpen) return null;
|
||
|
||
const handleEndCall = () => {
|
||
setIsConnecting(true);
|
||
setParticipants([]);
|
||
onClose();
|
||
};
|
||
|
||
return (
|
||
<div
|
||
className="modal-overlay"
|
||
style={{
|
||
position: "fixed",
|
||
inset: 0,
|
||
backgroundColor: "rgba(0,0,0,0.9)",
|
||
display: "flex",
|
||
alignItems: "center",
|
||
justifyContent: "center",
|
||
zIndex: 1000,
|
||
}}
|
||
>
|
||
<div
|
||
className="modal-content"
|
||
style={{
|
||
background: "#0a0a0a",
|
||
border: "1px solid #1a1a1a",
|
||
borderRadius: "12px",
|
||
padding: "24px",
|
||
width: "90%",
|
||
maxWidth: "900px",
|
||
height: "80vh",
|
||
display: "flex",
|
||
flexDirection: "column",
|
||
}}
|
||
>
|
||
{/* Header */}
|
||
<div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", marginBottom: "20px" }}>
|
||
<div>
|
||
<h2 style={{ fontSize: "1.5rem", fontWeight: "bold", color: "#fff", marginBottom: "4px" }}>
|
||
{data?.roomName || "Voice Channel"}
|
||
</h2>
|
||
<p style={{ fontSize: "0.875rem", color: "#666" }}>
|
||
{isConnecting ? "Connecting..." : `${participants.length} participant(s)`}
|
||
</p>
|
||
</div>
|
||
<button
|
||
onClick={onClose}
|
||
style={{
|
||
background: "none",
|
||
border: "none",
|
||
color: "#666",
|
||
fontSize: "1.5rem",
|
||
cursor: "pointer",
|
||
}}
|
||
>
|
||
✕
|
||
</button>
|
||
</div>
|
||
|
||
{/* Video Grid */}
|
||
<div
|
||
style={{
|
||
flex: 1,
|
||
display: "grid",
|
||
gridTemplateColumns: "repeat(auto-fit, minmax(300px, 1fr))",
|
||
gap: "16px",
|
||
marginBottom: "20px",
|
||
overflow: "auto",
|
||
}}
|
||
>
|
||
{isConnecting ? (
|
||
<div
|
||
style={{
|
||
display: "flex",
|
||
alignItems: "center",
|
||
justifyContent: "center",
|
||
background: "#0f0f0f",
|
||
borderRadius: "8px",
|
||
minHeight: "200px",
|
||
}}
|
||
>
|
||
<div style={{ textAlign: "center", color: "#666" }}>
|
||
<div style={{ fontSize: "2rem", marginBottom: "12px" }}>🔊</div>
|
||
<p>Connecting to voice channel...</p>
|
||
</div>
|
||
</div>
|
||
) : (
|
||
participants.map((participant) => (
|
||
<div
|
||
key={participant.id}
|
||
style={{
|
||
background: "#0f0f0f",
|
||
border: "2px solid #1a1a1a",
|
||
borderRadius: "8px",
|
||
padding: "16px",
|
||
display: "flex",
|
||
flexDirection: "column",
|
||
alignItems: "center",
|
||
justifyContent: "center",
|
||
minHeight: "200px",
|
||
position: "relative",
|
||
}}
|
||
>
|
||
<div
|
||
style={{
|
||
width: "80px",
|
||
height: "80px",
|
||
borderRadius: "50%",
|
||
background: "linear-gradient(135deg, #0066ff, #00ccff)",
|
||
display: "flex",
|
||
alignItems: "center",
|
||
justifyContent: "center",
|
||
fontSize: "2rem",
|
||
marginBottom: "12px",
|
||
}}
|
||
>
|
||
{participant.name[0]}
|
||
</div>
|
||
<p style={{ color: "#fff", fontWeight: "bold", marginBottom: "4px" }}>
|
||
{participant.name}
|
||
</p>
|
||
<div style={{ display: "flex", gap: "8px", fontSize: "0.875rem", color: "#666" }}>
|
||
{participant.isMuted && <span>🔇 Muted</span>}
|
||
{participant.isVideoOff && <span>📹 Video Off</span>}
|
||
{!participant.isMuted && !participant.isVideoOff && <span>🎤 Speaking</span>}
|
||
</div>
|
||
</div>
|
||
))
|
||
)}
|
||
</div>
|
||
|
||
{/* Controls */}
|
||
<div
|
||
style={{
|
||
display: "flex",
|
||
justifyContent: "center",
|
||
gap: "16px",
|
||
padding: "16px",
|
||
background: "#0f0f0f",
|
||
borderRadius: "8px",
|
||
}}
|
||
>
|
||
<button
|
||
style={{
|
||
width: "50px",
|
||
height: "50px",
|
||
borderRadius: "50%",
|
||
background: "#2a2a2a",
|
||
border: "none",
|
||
color: "#fff",
|
||
fontSize: "1.25rem",
|
||
cursor: "pointer",
|
||
transition: "background 0.2s",
|
||
}}
|
||
title="Toggle Microphone"
|
||
>
|
||
🎤
|
||
</button>
|
||
<button
|
||
style={{
|
||
width: "50px",
|
||
height: "50px",
|
||
borderRadius: "50%",
|
||
background: "#2a2a2a",
|
||
border: "none",
|
||
color: "#fff",
|
||
fontSize: "1.25rem",
|
||
cursor: "pointer",
|
||
transition: "background 0.2s",
|
||
}}
|
||
title="Toggle Video"
|
||
>
|
||
📹
|
||
</button>
|
||
<button
|
||
style={{
|
||
width: "50px",
|
||
height: "50px",
|
||
borderRadius: "50%",
|
||
background: "#2a2a2a",
|
||
border: "none",
|
||
color: "#fff",
|
||
fontSize: "1.25rem",
|
||
cursor: "pointer",
|
||
transition: "background 0.2s",
|
||
}}
|
||
title="Share Screen"
|
||
>
|
||
🖥️
|
||
</button>
|
||
<button
|
||
onClick={handleEndCall}
|
||
style={{
|
||
width: "50px",
|
||
height: "50px",
|
||
borderRadius: "50%",
|
||
background: "#ff0000",
|
||
border: "none",
|
||
color: "#fff",
|
||
fontSize: "1.25rem",
|
||
cursor: "pointer",
|
||
transition: "background 0.2s",
|
||
}}
|
||
title="End Call"
|
||
>
|
||
✕
|
||
</button>
|
||
</div>
|
||
|
||
{/* LiveKit Debug Info */}
|
||
{data?.token && (
|
||
<div style={{ marginTop: "12px", padding: "8px", background: "#0f0f0f", borderRadius: "4px", fontSize: "0.75rem", color: "#666" }}>
|
||
<p>LiveKit URL: {data.liveKitUrl}</p>
|
||
<p>Room: {data.roomName}</p>
|
||
</div>
|
||
)}
|
||
</div>
|
||
</div>
|
||
);
|
||
}
|