import { useVoiceStore } from '../stores/voice.ts'; import { useAuthStore } from '../stores/auth.ts'; import { usePermissions } from '../lib/usePermissions.ts'; import { useChannelStore } from '../stores/channel.ts'; import { api } from '../lib/api.ts'; interface VoiceChannelProps { channelId: string; channelName: string; } export function VoiceChannel({ channelId, channelName }: VoiceChannelProps) { const currentRoom = useVoiceStore((state) => state.currentRoom); const isConnected = useVoiceStore((state) => state.isConnected); const joinVoice = useVoiceStore((state) => state.joinVoice); const participants = useVoiceStore((state) => state.participants); const currentUserId = useAuthStore((state) => state.user?.id); const activeChannelId = useChannelStore((s) => s.activeChannelId); const channelsByServer = useChannelStore((s) => s.channelsByServer); const serverId = activeChannelId ? Object.entries(channelsByServer).find(([_, channels]) => channels.some(c => c.id === activeChannelId))?.[0] : null; const { canMute } = usePermissions(serverId || null); const handleMute = async (identity: string) => { if (!currentRoom) return; try { await api.post(`/voice/rooms/${currentRoom}/participants/${identity}/mute`); } catch (err) { console.error('Failed to mute participant:', err); } }; const whisperTo = (identity: string, username: string) => { useVoiceStore.getState().whisperTo(identity, username); }; const isActive = currentRoom === channelId; const handleClick = () => { if (!isActive) { console.log("[VoiceChannel] joining voice:", channelId, channelName); joinVoice(channelId, channelName).catch((err) => { console.error("[VoiceChannel] joinVoice failed:", err); }); } }; const error = useVoiceStore((state) => state.error); return (
{error && (
! {error}
)} {isActive && (
{participants.map((p) => { const isMe = p.identity === currentUserId; return (
{p.isMuted ? '○' : '●'} {p.username} {!isMe && (
{canMute && !p.isMuted && ( )}
)}
); })}
)}
); }