| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120 |
- '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<ChatMessage[]>([]);
- const [systemMessages, setSystemMessages] = useState<SystemMessage[]>([]);
- const [participantCount, setParticipantCount] = useState(0);
- const [participants, setParticipants] = useState<ChatParticipant[]>([]);
- const prevConnectionRef = useRef<typeof chatConnection>(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
- };
- }
|