import React, { useEffect, useRef, useState } from 'react'; import { useChatStore } from '../store/chatStore'; import { ChatMessageComponent } from './ChatMessage'; import { useChat } from '../hooks/useChat'; import { useWebRTC } from '../hooks/useWebRTC'; import { MessageSearch } from './MessageSearch'; import { TypingIndicator } from './TypingIndicator'; import { CallButton } from './CallButton'; import { IncomingCallModal } from './IncomingCallModal'; import { ActiveCallBar } from './ActiveCallBar'; import { Search, X, MessageSquare, UserPlus, Users, } from 'lucide-react'; import { Button } from '@/components/ui/button'; import { cn } from '@/lib/utils'; import { InviteRoomModal } from './InviteRoomModal'; import { RoomMembersModal } from './RoomMembersModal'; import { useUser } from '@/features/auth/hooks/useUser'; import { adminService } from '@/services/adminService'; interface ChatRoomProps { conversationId: string; } export const ChatRoom: React.FC = ({ conversationId }) => { const { messages, conversations, userId, incomingCall, activeCall } = useChatStore(); const { fetchHistory, sendRawMessage, wsStatus } = useChat(); const { data: _user } = useUser(); const webrtc = useWebRTC({ sendMessage: sendRawMessage }); const messagesEndRef = useRef(null); const [showSearch, setShowSearch] = useState(false); const [showInviteModal, setShowInviteModal] = useState(false); const [showMembersModal, setShowMembersModal] = useState(false); const [webrtcEnabled, setWebrtcEnabled] = useState(true); const [highlightedMessageId, setHighlightedMessageId] = useState< string | null >(null); const highlightTimeoutRef = useRef | null>(null); useEffect(() => { let cancelled = false; adminService.getClientFeatureFlags().then((flags) => { if (cancelled) return; const webrtc = flags.find((f) => f.name === 'WEBRTC_CALLS'); setWebrtcEnabled(webrtc?.enabled ?? true); }).catch(() => { if (!cancelled) setWebrtcEnabled(true); }); return () => { cancelled = true; }; }, []); // Cleanup highlight timeout on unmount useEffect(() => { return () => { if (highlightTimeoutRef.current) { clearTimeout(highlightTimeoutRef.current); } }; }, []); const currentMessages = messages[conversationId] || []; const fetchingRef = useRef<{ [key: string]: boolean }>({}); useEffect(() => { if ( conversationId && !messages[conversationId] && !fetchingRef.current[conversationId] ) { fetchingRef.current[conversationId] = true; fetchHistory(conversationId).finally(() => { // Fetch complete }); } }, [conversationId, messages[conversationId], fetchHistory]); useEffect(() => { if (messagesEndRef.current) { messagesEndRef.current.scrollIntoView({ behavior: 'smooth' }); } }, [currentMessages.length, conversationId]); // Scroll on new messages or channel switch const handleMessageSelect = (messageId: string) => { setHighlightedMessageId(messageId); const messageElement = document.getElementById(`message-${messageId}`); if (messageElement) { messageElement.scrollIntoView({ behavior: 'smooth', block: 'center' }); if (highlightTimeoutRef.current) { clearTimeout(highlightTimeoutRef.current); } highlightTimeoutRef.current = setTimeout(() => setHighlightedMessageId(null), 3000); } }; const conversation = conversations.find((c) => c.id === conversationId); const isDM = conversation?.type === 'direct' && conversation.participants.length === 2; const isGroupRoom = conversation && conversation.type !== 'direct'; const targetUserId = isDM && userId ? conversation.participants.find((p) => p !== userId) ?? null : null; const remoteUserName = conversation?.name && conversation.name !== 'direct' ? conversation.name : 'Utilisateur'; if (!conversationId) { return (

No conversation selected

Pick a channel from the sidebar to start chatting.

); } return (
incomingCall && webrtc.acceptCall( incomingCall.conversationId, incomingCall.callerUserId, incomingCall.sdp, ) } onReject={() => incomingCall && webrtc.rejectCall( incomingCall.conversationId, incomingCall.callerUserId, ) } /> {activeCall && (
webrtc.hangup(activeCall.conversationId, activeCall.remoteUserId) } />
)} {/* Search Header Overlay */}
{showSearch ? (
) : (
{isGroupRoom && ( <> )} {isDM && targetUserId && webrtcEnabled && ( webrtc.startCall(conversationId, targetUserId, 'audio') } disabled={wsStatus !== 'connected'} hasTurn={webrtc.nat.loaded ? webrtc.nat.hasTurn : undefined} /> )}
)}
{/* Welcome Message for Empty Room */} {currentMessages.length === 0 && (

No messages yet

Send the first message to start the conversation.

)} {/* Message Stream */} {currentMessages.map((msg) => { return (
); })}
{isGroupRoom && ( <> )}
); };