diff --git a/src/apis/chatRoomList.ts b/src/apis/chatRoomList.ts index 85c51e95..ba8fc11d 100644 --- a/src/apis/chatRoomList.ts +++ b/src/apis/chatRoomList.ts @@ -3,13 +3,23 @@ import { useSuspenseInfiniteQuery } from '@tanstack/react-query'; import { ROOMS_CHATS_MY_GAMES_API_URL } from '@/constants/apiRoutes'; import { CHAT_LIST_QUERY_KEY } from '@/constants/queryKey'; +import { MessageType } from './chatRoomMessages'; import { api } from './core'; +export interface LastChatMessage { + roomId: number; + content: string; + messageType: MessageType; + createdAt: string; +} + export interface ChatRoom { id: number; title: string; imageUrl: string | null; headCount: number; + unreadChatCount: number; + lastChatMessage: LastChatMessage; } interface ChatRoomListResponse { diff --git a/src/hooks/useSendChatMessage.ts b/src/hooks/useSendChatMessage.ts index aaa592d0..9ee4fac5 100644 --- a/src/hooks/useSendChatMessage.ts +++ b/src/hooks/useSendChatMessage.ts @@ -1,17 +1,16 @@ import { useCallback, useEffect, useRef, useState } from 'react'; import { Client, IMessage } from '@stomp/stompjs'; -import { useQueryClient } from '@tanstack/react-query'; import SockJS from 'sockjs-client'; -import { type ChatMessage, type MessageType } from '@/apis/chatRoomMessages'; +import type { LastChatMessage } from '@/apis/chatRoomList'; +import type { ChatMessage, MessageType } from '@/apis/chatRoomMessages'; import { CHAT_CONNECT_SOCKET_URL, CHAT_EXIT_SOCKET_URL, CHAT_SEND_SOCKET_URL, CHAT_SUBSCRIBE_SOCKET_URL, } from '@/constants/apiRoutes'; -import { CHATS_QUERY_KEY } from '@/constants/queryKey'; import { STORAGE_KEY_ACCESS_TOKEN } from '@/constants/storageKeys'; export interface MessageRequest { @@ -27,18 +26,45 @@ export interface MessageRequest { * */ -const useSendChatMessage = ( - gatheringId: number, +interface SendChatMessageParams { + rawMessages?: ChatMessage[]; + gatheringId: number; + isPublishExitMessage?: boolean; + rawLastChatMessage?: LastChatMessage; + unreadChatCount?: number; +} + +const useSendChatMessage = ({ + rawMessages = [], + gatheringId, isPublishExitMessage = false, - rawLastChatMessage: ChatMessage | undefined = undefined, -) => { + rawLastChatMessage, + unreadChatCount = 0, +}: SendChatMessageParams) => { const client = useRef(null); - const [lastChatMessage, setLastChatMessage] = useState< - ChatMessage | undefined - >(rawLastChatMessage); + const [lastMessage, setLastMessage] = useState(rawLastChatMessage); + const [messages, setMessages] = useState(rawMessages); + const [unreadMessagesCount, setUnreadMessagesCount] = + useState(unreadChatCount); const accessToken = localStorage.getItem(STORAGE_KEY_ACCESS_TOKEN); - const queryClient = useQueryClient(); + + const subscribe = () => { + client.current?.subscribe( + `${CHAT_SUBSCRIBE_SOCKET_URL}/${gatheringId}`, + (message: IMessage) => { + const newMessage = JSON.parse(message.body); + + setMessages(prevState => [newMessage, ...prevState]); + setLastMessage(newMessage); + setUnreadMessagesCount(prevState => prevState + 1); + }, + { + Authorization: `Bearer ${accessToken}`, + RoomId: String(gatheringId), + }, + ); + }; const connect = () => { const socket = new SockJS( @@ -47,21 +73,8 @@ const useSendChatMessage = ( client.current = new Client({ webSocketFactory: () => socket, - onConnect: () => - client.current?.subscribe( - `${CHAT_SUBSCRIBE_SOCKET_URL}/${gatheringId}`, - (message: IMessage) => { - queryClient.invalidateQueries({ - queryKey: [CHATS_QUERY_KEY, gatheringId], - }); - - setLastChatMessage(JSON.parse(message.body)); - }, - { - Authorization: `Bearer ${accessToken}`, - RoomId: String(gatheringId), - }, - ), + debug: str => console.log(str), + onConnect: () => subscribe(), onStompError: frame => { throw new Error(`Broker reported error: ${frame.headers.message}`); }, @@ -81,12 +94,9 @@ const useSendChatMessage = ( RoomId: gatheringId.toString(), }, }); - - queryClient.invalidateQueries({ - queryKey: [CHATS_QUERY_KEY, gatheringId], - }); } + setUnreadMessagesCount(0); client.current.deactivate(); }; @@ -121,7 +131,13 @@ const useSendChatMessage = ( // eslint-disable-next-line react-hooks/exhaustive-deps }, []); - return { lastChatMessage, sendMessage }; + return { + messages, + lastMessage, + unreadMessagesCount, + sendMessage, + subscribe, + }; }; export default useSendChatMessage; diff --git a/src/pages/ChatRoomList/components/ChatRoomList/ChatRoomListItem.tsx b/src/pages/ChatRoomList/components/ChatRoomList/ChatRoomListItem.tsx index d866e508..ac4b51d1 100644 --- a/src/pages/ChatRoomList/components/ChatRoomList/ChatRoomListItem.tsx +++ b/src/pages/ChatRoomList/components/ChatRoomList/ChatRoomListItem.tsx @@ -1,10 +1,6 @@ import { Link } from 'react-router-dom'; -import type { ChatRoom } from '@/apis/chatRoomList'; -import { - ChatMessage, - useGetChatRoomMessagesApi, -} from '@/apis/chatRoomMessages'; +import type { ChatRoom, LastChatMessage } from '@/apis/chatRoomList'; import defaultThumbnailImage from '@/assets/default-thumbnail-image.png'; import Button from '@/components/Button'; import Chip from '@/components/Chip'; @@ -17,24 +13,30 @@ interface ChatRoomListItemProps { chatRoom: ChatRoom; } -const MAX_UNCHECKED_MESSAGE_NUMBER = 50; - const ChatRoomListItem = ({ chatRoom }: ChatRoomListItemProps) => { - const { id, imageUrl, title, headCount } = chatRoom; + const { id, imageUrl, title, headCount, unreadChatCount, lastChatMessage } = + chatRoom; - const { lastChatMessage: rawLastChatMessage, uncheckedMessagesCount } = - useGetChatRoomMessagesApi(id, MAX_UNCHECKED_MESSAGE_NUMBER); - const { lastChatMessage } = useSendChatMessage(id, false, rawLastChatMessage); + const { lastMessage, unreadMessagesCount } = useSendChatMessage({ + gatheringId: id, + rawLastChatMessage: lastChatMessage, + unreadChatCount, + }); - const getLastChatMessageText = (lastChatMessage: ChatMessage | undefined) => { + const getLastChatMessageText = (lastChatMessage: LastChatMessage) => { if (!lastChatMessage) { return EMPTY_CHAT_ROOM_MESSAGE; } - const { nickname, type, content } = lastChatMessage; + const { messageType, content } = lastChatMessage; + console.log(lastChatMessage); - if (type === 'UNFIX' || type === 'PARTICIPANT' || type === 'EXIT') { - return `${nickname}${content}`; + if ( + messageType === 'UNFIX' || + messageType === 'PARTICIPANT' || + messageType === 'EXIT' + ) { + return content.replace('님이', '참가자가'); } return content; @@ -56,20 +58,16 @@ const ChatRoomListItem = ({ chatRoom }: ChatRoomListItemProps) => { {headCount}
- {getLastChatMessageText(lastChatMessage)} + {getLastChatMessageText(lastMessage as LastChatMessage)}
- {lastChatMessage && ( + {lastMessage && (
- {formatToTimeUntilTodayThenDate(lastChatMessage.createdAt)} + {formatToTimeUntilTodayThenDate(lastMessage.createdAt)}
- {uncheckedMessagesCount !== 0 && ( - - {uncheckedMessagesCount === MAX_UNCHECKED_MESSAGE_NUMBER - ? `${MAX_UNCHECKED_MESSAGE_NUMBER}+` - : uncheckedMessagesCount} - + {unreadMessagesCount !== 0 && ( + {unreadMessagesCount} )}
)}