import React from 'react'; import { useVoiceStore } from '../../stores/voiceStore'; import { useAuthStore } from '../../stores/authStore'; const EMPTY_VOICE_USERS: string[] = []; import { useServerStore } from '../../stores/serverStore'; import { Avatar } from '../ui/Avatar'; interface VoiceChannelProps { channelId: string; channelName: string; onClick: () => void; } export function VoiceChannel({ channelId, channelName, onClick }: VoiceChannelProps) { const voiceUsers = useVoiceStore((s) => s.voiceUsers.get(channelId)) ?? EMPTY_VOICE_USERS; const currentVoiceChannel = useVoiceStore((s) => s.currentVoiceChannelId); const participants = useVoiceStore((s) => s.participants); const localIsDeafened = useVoiceStore((s) => s.isDeafened); const localIsMuted = useVoiceStore((s) => s.isMuted); const voiceUserStates = useVoiceStore((s) => s.voiceUserStates); const currentUserId = useAuthStore((s) => s.user?.id); const members = useServerStore((s) => s.members); const isActive = currentVoiceChannel === channelId; return (
{/* Connected users */} {voiceUsers.length > 0 && (
{voiceUsers.map((userId) => { const member = members.find(m => m.userId === userId); const participant = participants.find(p => p.userId === userId); const displayName = member?.user.displayName ?? member?.user.username ?? participant?.username ?? userId; const avatar = member?.user.avatar ?? null; const status = member?.user.status; // Resolve status: for local user use store directly, for remote users // try LiveKit participant first, then fall back to WebSocket voiceUserStates const wsStatus = voiceUserStates.get(userId); const isParticipantDeafened = userId === currentUserId ? localIsDeafened : (participant?.isDeafened ?? wsStatus?.isDeafened ?? false); const isMuted = userId === currentUserId ? localIsMuted : (participant?.isMuted ?? wsStatus?.isMuted ?? false); const hasCamera = participant?.isCameraOn ?? wsStatus?.isCameraOn ?? false; const isScreenSharing = participant?.isScreenSharing ?? wsStatus?.isScreenSharing ?? false; return (
{displayName} {/* Status badges */}
{isMuted && ( )} {isParticipantDeafened && ( )} {hasCamera && ( )} {isScreenSharing && ( LIVE )}
); })}
)}
); }