'use client'; import { useState, useEffect, useCallback, useRef } from 'react'; import { useSignalRContext } from '@/contexts/signalrProvider'; import type { ChatMessage } from '@/types/chat'; export type SystemMessage = { id: number; content: string; receivedAt: string; }; export type ChatParticipant = { memberName: string; isGuest: boolean; }; let systemMsgId = 0; export default function useChat() { const { chatConnection, chatConnected } = useSignalRContext(); const [messages, setMessages] = useState([]); const [systemMessages, setSystemMessages] = useState([]); const [participantCount, setParticipantCount] = useState(0); const [participants, setParticipants] = useState([]); const prevConnectionRef = useRef(null); useEffect(() => { if (!chatConnection || !chatConnected) return; // 같은 connection 객체면 중복 등록 방지 if (prevConnectionRef.current === chatConnection) return; prevConnectionRef.current = chatConnection; chatConnection.on('ReceiveHistory', (history: ChatMessage[]) => { setMessages(history); }); chatConnection.on('ReceiveMessage', (message: ChatMessage) => { setMessages((prev) => [...prev, message]); }); chatConnection.on('ReceiveSystemMessage', (content: string) => { setSystemMessages((prev) => [ ...prev, { id: ++systemMsgId, content, receivedAt: new Date().toISOString() } ]); }); chatConnection.on('ReceiveParticipantCount', (count: number) => { setParticipantCount(count); }); chatConnection.on('ReceiveParticipants', (list: ChatParticipant[]) => { setParticipants(list); }); // 핸들러 등록 후 명시적으로 히스토리 + 접속자 수 요청 chatConnection.invoke('RequestHistory').catch(() => {}); chatConnection.invoke('RequestParticipantCount').catch(() => {}); return () => { chatConnection.off('ReceiveHistory'); chatConnection.off('ReceiveMessage'); chatConnection.off('ReceiveSystemMessage'); chatConnection.off('ReceiveParticipantCount'); chatConnection.off('ReceiveParticipants'); prevConnectionRef.current = null; }; }, [chatConnection, chatConnected]); const sendMessage = useCallback(async (content: string) => { if (!chatConnection || !chatConnected) return; const trimmed = content.trim(); if (!trimmed || trimmed.length > 500) return; try { await chatConnection.invoke('SendMessage', trimmed); } catch (error) { console.error('메시지 전송 실패:', error); } }, [chatConnection, chatConnected]); const clearMessages = useCallback(() => { setMessages([]); setSystemMessages([]); }, []); const refreshChat = useCallback(async () => { if (!chatConnection || !chatConnected) return; setMessages([]); setSystemMessages([]); try { await chatConnection.invoke('RequestHistory'); await chatConnection.invoke('RequestParticipantCount'); } catch { // ignore } }, [chatConnection, chatConnected]); const requestParticipants = useCallback(async () => { if (!chatConnection || !chatConnected) return; try { await chatConnection.invoke('RequestParticipants'); } catch { // ignore } }, [chatConnection, chatConnected]); return { messages, systemMessages, participantCount, participants, sendMessage, clearMessages, refreshChat, requestParticipants, chatConnected }; }