From ffc29da9ce036d64ba404b299df56dc6a7f1523c Mon Sep 17 00:00:00 2001 From: 42inshin Date: Tue, 25 Feb 2025 15:00:29 +0900 Subject: [PATCH 01/13] =?UTF-8?q?[FE]=20FEAT:=20iOS=20webview=20=EC=9A=A9?= =?UTF-8?q?=20=EC=BD=94=EB=93=9C=20=EC=B6=94=EA=B0=80=20#248?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Modal/RegisterSuccessModal/index.tsx | 3 +++ src/frontend/src/types/window.d.ts | 20 +++++++++++++++++++ 2 files changed, 23 insertions(+) create mode 100644 src/frontend/src/types/window.d.ts diff --git a/src/frontend/src/components/Modal/RegisterSuccessModal/index.tsx b/src/frontend/src/components/Modal/RegisterSuccessModal/index.tsx index 7eb3d9af..953c69de 100644 --- a/src/frontend/src/components/Modal/RegisterSuccessModal/index.tsx +++ b/src/frontend/src/components/Modal/RegisterSuccessModal/index.tsx @@ -12,6 +12,9 @@ export const RegisterSuccessModal = ({ onCancel }: IRegisterSuccessModal) => { const navigate = useNavigate(); const handleConfirm = () => { + if (window.webkit?.messageHandlers?.closeModal) { + window.webkit.messageHandlers.closeModal.postMessage('LoginSuccess'); + } navigate('/login'); onCancel(); }; diff --git a/src/frontend/src/types/window.d.ts b/src/frontend/src/types/window.d.ts new file mode 100644 index 00000000..37a38c74 --- /dev/null +++ b/src/frontend/src/types/window.d.ts @@ -0,0 +1,20 @@ +interface WebKitMessageHandler { + postMessage: (message: string) => void; +} + +interface WebKitMessageHandlers { + closeModal: WebKitMessageHandler; + [key: string]: WebKitMessageHandler; +} + +interface WebKit { + messageHandlers: WebKitMessageHandlers; +} + +declare global { + interface Window { + webkit?: WebKit; + } +} + +export {}; From 9b014a29945f3ff09c7499fb1a93f1ac13e6df20 Mon Sep 17 00:00:00 2001 From: 42inshin Date: Tue, 25 Feb 2025 15:00:58 +0900 Subject: [PATCH 02/13] =?UTF-8?q?[FE]=20FIX:=20=ED=86=A0=ED=81=B0=20?= =?UTF-8?q?=EC=8B=9C=EA=B0=84=20=EB=B3=80=EA=B2=BD=20#248?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/backend/auth-server/src/auth/constants/constants.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/backend/auth-server/src/auth/constants/constants.ts b/src/backend/auth-server/src/auth/constants/constants.ts index 2b25c54e..34b86597 100644 --- a/src/backend/auth-server/src/auth/constants/constants.ts +++ b/src/backend/auth-server/src/auth/constants/constants.ts @@ -17,10 +17,10 @@ export const TOKEN_TYPE = { } as const; export const TOKEN_EXPIRATION_TIME = { - ACCESS: 300, // 5분 - REFRESH: 3600, // 1시간 - // ACCESS: 3600, // 1시간 - // REFRESH: 604800, // 7일 + // ACCESS: 300, // 5분 + // REFRESH: 3600, // 1시간 + ACCESS: 3600, // 1시간 + REFRESH: 604800, // 7일 } as const; export const RAW_TOKEN_TYPE = { From 3099d889dacd4b97ff62c66fcdd1dbf44865c652 Mon Sep 17 00:00:00 2001 From: 42inshin Date: Tue, 25 Feb 2025 15:18:07 +0900 Subject: [PATCH 03/13] =?UTF-8?q?[FE]=20FIX:=20=EB=82=B4=20=EB=B0=A9=20?= =?UTF-8?q?=EA=B5=AC=EB=8F=85=20=EB=A1=9C=EC=A7=81=20store=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD=20#248?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/frontend/src/stores/useMyRoomsStore.ts | 39 +++++++++++++++++--- src/frontend/src/stores/useWebSocketStore.ts | 18 --------- 2 files changed, 34 insertions(+), 23 deletions(-) diff --git a/src/frontend/src/stores/useMyRoomsStore.ts b/src/frontend/src/stores/useMyRoomsStore.ts index 68e90ce4..83f468da 100644 --- a/src/frontend/src/stores/useMyRoomsStore.ts +++ b/src/frontend/src/stores/useMyRoomsStore.ts @@ -9,16 +9,21 @@ import { useCurrentRoomStore } from './useCurrentRoomStore'; interface MyRoomsStore { myRooms: MyRoomDto[]; + newChatCount: number; setMyRooms: (rooms: MyRoomDto[]) => void; fetchMyRooms: () => Promise; + subscribeRoom: (roomId: number) => void; + subscribeRooms: (roomIds: number[]) => void; + resetNewChatCount: () => void; clearMyRooms: () => void; } export const useMyRoomsStore = create( persist( - set => ({ + (set, get) => ({ myRooms: [], - + newChatCount: 0, + newChatRooms: {}, // 내 방 목록 설정 setMyRooms: (rooms: MyRoomDto[]) => set({ myRooms: rooms }), @@ -30,10 +35,11 @@ export const useMyRoomsStore = create( console.log('myRooms', myRooms); const myRoomIds = myRooms.map(room => room.roomId); const currentRoomId = useCurrentRoomStore.getState().roomId; - if (currentRoomId) { // 현재 /rooom에서 방을 보고 있다면 구독을 currentRoomStore에서 처리 + if (currentRoomId) { + // 현재 /rooom에서 방을 보고 있다면 구독을 currentRoomStore에서 처리 myRoomIds.splice(myRoomIds.indexOf(currentRoomId), 1); } - useWebSocketStore.getState().subscribeRooms(myRoomIds); + get().subscribeRooms(myRoomIds); return myRooms; } catch (error) { console.error('Failed to fetch rooms:', error); @@ -41,8 +47,31 @@ export const useMyRoomsStore = create( } }, + // 방 채팅 구독 + subscribeRoom: (roomId: number) => { + const destination = `/topic/room/${roomId}/chat`; + useWebSocketStore.getState().subTopic(destination, message => { + console.log('subscribeRoomChat', message); + set(state => ({ + newChatCount: state.newChatCount + 1, + })); + }); + }, + + // 내가 속한 방 채팅 구독 + subscribeRooms: (roomIds: number[]) => { + if (!roomIds) return; + roomIds.forEach(roomId => { + get().subscribeRoom(roomId); + }); + }, + + resetNewChatCount: () => { + set({ newChatCount: 0 }); + }, + // 내 방 목록 초기화 - clearMyRooms: () => set({ myRooms: [] }), + clearMyRooms: () => set({ myRooms: [], newChatCount: 0 }), }), { name: 'my-rooms-storage', diff --git a/src/frontend/src/stores/useWebSocketStore.ts b/src/frontend/src/stores/useWebSocketStore.ts index 0a49c645..fce3dd29 100644 --- a/src/frontend/src/stores/useWebSocketStore.ts +++ b/src/frontend/src/stores/useWebSocketStore.ts @@ -25,8 +25,6 @@ interface WebSocketStore { disconnect: () => void; subTopic: (destination: string, callback: (message: T) => void) => void; - subscribeRoom: (roomId: number) => void; - subscribeRooms: (roomIds: number[]) => void; subscribeInvitations: (userId: number, callback: (message: T) => void) => void; subscribeFriendConnection: (userId: number, callback: (message: T) => void) => void; subscribeRoomUserInfo: ( @@ -173,14 +171,6 @@ export const useWebSocketStore = create((set, get) => ({ get().subTopic(destination, callback); }, - // 방 채팅 구독 - subscribeRoom: (roomId: number) => { - const destination = `/topic/room/${roomId}/chat`; - get().subTopic(destination, message => { - console.log('subscribeRoomChat', message); - }); - }, - // 채팅방 내 신규 유저 정보 구독 subscribeRoomUserInfo: ( roomId: number, @@ -212,14 +202,6 @@ export const useWebSocketStore = create((set, get) => ({ get().subTopic(destination, callback); }, - // 내가 속한 방 채팅 구독 - subscribeRooms: (roomIds: number[]) => { - if (!roomIds) return; - roomIds.forEach(roomId => { - get().subscribeRoom(roomId); - }); - }, - // 구독 해제 unsubscribeAll: () => { get().subscriptions.forEach(sub => sub.unsubscribe()); From 256285a9fb15f88585852bdc1392e4c9e05a898a Mon Sep 17 00:00:00 2001 From: 42inshin Date: Tue, 25 Feb 2025 15:21:10 +0900 Subject: [PATCH 04/13] =?UTF-8?q?[FE]=20FIX:=20accessToken=20clear?= =?UTF-8?q?=EC=8B=9C=20store=20=EC=B4=88=EA=B8=B0=ED=99=94=20#248?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/frontend/src/stores/useAuthStore.ts | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/frontend/src/stores/useAuthStore.ts b/src/frontend/src/stores/useAuthStore.ts index 181c8270..dd8cda0f 100644 --- a/src/frontend/src/stores/useAuthStore.ts +++ b/src/frontend/src/stores/useAuthStore.ts @@ -1,6 +1,11 @@ import axios from 'axios'; import { create } from 'zustand'; import { persist } from 'zustand/middleware'; +import { useFriendStore } from './useFriendStore'; +import { useNotificationStore } from './useNotificationStore'; +import { useUserStore } from './useUserStore'; +import { useMyRoomsStore } from './useMyRoomsStore'; +import { useWebSocketStore } from './useWebSocketStore'; const instance = axios.create({ baseURL: import.meta.env.VITE_API_URL, @@ -31,6 +36,11 @@ export const useAuthStore = create( }, clear: () => { set({ accessToken: null }); + useFriendStore.getState().clear(); + useNotificationStore.getState().clear(); + useMyRoomsStore.getState().clearMyRooms(); + useUserStore.getState().clearProfile(); + useWebSocketStore.getState().disconnect(); }, }), { From 16dca133ba9c2ceeef274e3fa897ba073d4246bb Mon Sep 17 00:00:00 2001 From: 42inshin Date: Tue, 25 Feb 2025 15:22:32 +0900 Subject: [PATCH 05/13] =?UTF-8?q?[FE]=20FEAT:=20=EC=83=88=EB=A1=9C?= =?UTF-8?q?=EC=9A=B4=20=EC=B1=84=ED=8C=85=20=EC=99=94=EC=9D=84=20=EC=8B=9C?= =?UTF-8?q?=20=EB=82=B4=EB=B0=A9=20=EB=B2=84=ED=8A=BC=20=EC=B9=B4=EC=9A=B4?= =?UTF-8?q?=ED=8A=B8=20=EC=B6=94=EA=B0=80=20#248?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/components/LeftNavBar/index.css.ts | 1 + src/frontend/src/components/LeftNavBar/index.tsx | 5 +++++ src/frontend/src/pages/MyRoomPage/index.tsx | 3 ++- src/frontend/src/ui/Common.css.ts | 16 ++++++++++++++++ 4 files changed, 24 insertions(+), 1 deletion(-) diff --git a/src/frontend/src/components/LeftNavBar/index.css.ts b/src/frontend/src/components/LeftNavBar/index.css.ts index b8bed02d..43941b7a 100644 --- a/src/frontend/src/components/LeftNavBar/index.css.ts +++ b/src/frontend/src/components/LeftNavBar/index.css.ts @@ -30,6 +30,7 @@ export const ButtonWrapper = styled.div` `; export const ButtonBox = styled.div<{ $isActive: boolean }>` + position: relative; width: 40px; height: 40px; display: flex; diff --git a/src/frontend/src/components/LeftNavBar/index.tsx b/src/frontend/src/components/LeftNavBar/index.tsx index f5764111..cce757e0 100644 --- a/src/frontend/src/components/LeftNavBar/index.tsx +++ b/src/frontend/src/components/LeftNavBar/index.tsx @@ -6,12 +6,16 @@ import PlaylistLineIcon from '@/assets/img/PlaylistLine.svg'; import UsersFillIcon from '@/assets/img/UsersFill.svg'; import UsersLineIcon from '@/assets/img/UsersLine.svg'; import { ButtonBox, ButtonContainer, ButtonWrapper } from './index.css'; +import { NotificationCount } from '@/ui/Common.css'; +import { useMyRoomsStore } from '@/stores/useMyRoomsStore'; export const LeftNavBar = () => { const location = useLocation(); const isHome = location.pathname === '/'; const isMyRoom = location.pathname === '/my-room'; const isFriend = location.pathname === '/friend'; + const newChatCount = useMyRoomsStore((state) => state.newChatCount); + return ( @@ -27,6 +31,7 @@ export const LeftNavBar = () => { my Room + {newChatCount > 0 && {newChatCount}}

MY

diff --git a/src/frontend/src/pages/MyRoomPage/index.tsx b/src/frontend/src/pages/MyRoomPage/index.tsx index 33f58ebd..c492071d 100644 --- a/src/frontend/src/pages/MyRoomPage/index.tsx +++ b/src/frontend/src/pages/MyRoomPage/index.tsx @@ -11,12 +11,13 @@ import { AlertDescription } from '@/components/common/AlertDescription'; export const MyRoomPage = () => { const { data } = useMyRooms(); const { user } = useUserStore(); - const { myRooms, setMyRooms, clearMyRooms } = useMyRoomsStore(); + const { myRooms, setMyRooms, clearMyRooms, resetNewChatCount } = useMyRoomsStore(); const showSkeleton = useDelayedLoading(data); useEffect(() => { if (data) { setMyRooms(data); + resetNewChatCount(); } else { clearMyRooms(); } diff --git a/src/frontend/src/ui/Common.css.ts b/src/frontend/src/ui/Common.css.ts index 0a5609e5..01ee081a 100644 --- a/src/frontend/src/ui/Common.css.ts +++ b/src/frontend/src/ui/Common.css.ts @@ -111,3 +111,19 @@ export const SkeletonBase = styled.div` export const Divider = styled.div` height: 1rem; `; + +export const NotificationCount = styled.div` + position: absolute; + top: 2px; + right: 2px; + width: 18px; + height: 18px; + border-radius: 50%; + background-color: var(--palette-status-negative); + color: var(--palette-static-white); + font-size: 0.75rem; + font-weight: 600; + display: flex; + justify-content: center; + align-items: center; +`; From 8cc8ad2aead70e8b37d51c885f205be85e02d74e Mon Sep 17 00:00:00 2001 From: 42inshin Date: Wed, 26 Feb 2025 14:25:54 +0900 Subject: [PATCH 06/13] =?UTF-8?q?[FE]=20FIX:=20=EB=A3=B8=20=ED=8E=98?= =?UTF-8?q?=EC=9D=B4=EC=A7=80=20=EB=A0=8C=EB=8D=94=EB=A7=81=20=EC=B5=9C?= =?UTF-8?q?=EC=A0=81=ED=99=94=EB=A5=BC=20=EC=9C=84=ED=95=9C=20=EC=88=98?= =?UTF-8?q?=EC=A0=95=20#248?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/frontend/src/components/RoomDetail/index.tsx | 2 +- src/frontend/src/pages/RoomPage/index.tsx | 9 +++++++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/frontend/src/components/RoomDetail/index.tsx b/src/frontend/src/components/RoomDetail/index.tsx index 6cd2e2ea..58063d5f 100644 --- a/src/frontend/src/components/RoomDetail/index.tsx +++ b/src/frontend/src/components/RoomDetail/index.tsx @@ -16,7 +16,7 @@ import { useCurrentRoomStore } from '@/stores/useCurrentRoomStore'; import DefaultProfile from '@/assets/img/DefaultProfile.svg'; export const RoomDetail = () => { - const { currentRoom } = useCurrentRoomStore(); + const currentRoom = useCurrentRoomStore(state => state.currentRoom); const roomInfo = currentRoom?.roomDetails.roomInfo[0]; const handleDescription = () => { diff --git a/src/frontend/src/pages/RoomPage/index.tsx b/src/frontend/src/pages/RoomPage/index.tsx index c61d9a92..89b6fc7a 100644 --- a/src/frontend/src/pages/RoomPage/index.tsx +++ b/src/frontend/src/pages/RoomPage/index.tsx @@ -11,6 +11,8 @@ import { useCurrentRoom } from '@/hooks/queries/useCurrentRoom'; import { useVideoStore } from '@/stores/useVideoStore'; import { getVideoQueueFromPlaylist } from '@/utils/playlistUtils'; import { useWebSocketStore } from '@/stores/useWebSocketStore'; +import { useMyRoomsStore } from '@/stores/useMyRoomsStore'; + export const RoomPage = () => { const [searchParams] = useSearchParams(); const roomCode = searchParams.get('code'); @@ -18,7 +20,7 @@ export const RoomPage = () => { console.log('RoomPage:', room); const { setVideoQueue } = useVideoStore(); const { subscribeRoomPlaylistUpdate } = useWebSocketStore(); - const { roomId } = useCurrentRoomStore(); + const roomId = useCurrentRoomStore(state => state.roomId); useEffect(() => { if (room) { @@ -35,8 +37,11 @@ export const RoomPage = () => { } return () => { useCurrentRoomStore.getState().clearCurrentRoom(); + if (roomId) { + useMyRoomsStore.getState().subscribeRoom(roomId); + } }; - }, [room]); + }, []); // YouTube API를 이용하여 영상 정보(제목 & 유튜버) 가져오기 const fetchVideoDetails = async (videoIds: string[]) => { From b190a70001a3a8b205ae550048985461cd78c6d2 Mon Sep 17 00:00:00 2001 From: 42inshin Date: Wed, 26 Feb 2025 14:27:52 +0900 Subject: [PATCH 07/13] =?UTF-8?q?[FE]=20FEAT:=20Sentry=20host=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/frontend/src/sentry.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/frontend/src/sentry.ts b/src/frontend/src/sentry.ts index 4c882924..90ad960d 100644 --- a/src/frontend/src/sentry.ts +++ b/src/frontend/src/sentry.ts @@ -28,7 +28,11 @@ Sentry.init({ // Set `tracePropagationTargets` to control for which URLs trace propagation should be enabled // tracePropagationTargets: [/^\//, /^https:\/\/yourserver\.io\/api/], - tracePropagationTargets: ['localhost'], + tracePropagationTargets: [ + 'localhost', + /^http:\/\/kicktube\.site/, + /^http:\/\/13\.231\.39\.189:8000\/api/, + ], // Capture Replay for 100% of all sessions, // plus for 100% of sessions with an error From 2c4337e36a1f8ec11f3f0a377852ed12801c38f4 Mon Sep 17 00:00:00 2001 From: 42inshin Date: Wed, 26 Feb 2025 14:32:10 +0900 Subject: [PATCH 08/13] =?UTF-8?q?[FE]=20FIX:=20store=20=EC=83=81=ED=83=9C?= =?UTF-8?q?=20=EB=B0=9B=EB=8A=94=20=ED=98=95=EC=8B=9D=20=EB=B3=80=EA=B2=BD?= =?UTF-8?q?=20#248?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/frontend/src/App.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/frontend/src/App.tsx b/src/frontend/src/App.tsx index 648ef893..fb57883a 100644 --- a/src/frontend/src/App.tsx +++ b/src/frontend/src/App.tsx @@ -17,7 +17,7 @@ import { queryClient } from '@/lib/react-query'; import { useUserStore } from './stores/useUserStore'; const ProtectedRoute = ({ children }: { children: JSX.Element }) => { - const { user } = useUserStore(); + const user = useUserStore(state => state.user); if (!user) { return ; From 4e61cfe1eca76add4d33faee75a1a5d9831749b8 Mon Sep 17 00:00:00 2001 From: 42inshin Date: Wed, 26 Feb 2025 14:32:46 +0900 Subject: [PATCH 09/13] =?UTF-8?q?[FE]=20FEAT:=20=EB=B0=A9=20=EC=B4=88?= =?UTF-8?q?=EB=8C=80=20api=20=EC=B6=94=EA=B0=80=20#248?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/api/endpoints/room/room.api.ts | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/src/frontend/src/api/endpoints/room/room.api.ts b/src/frontend/src/api/endpoints/room/room.api.ts index 408fc6e9..136d8e5e 100644 --- a/src/frontend/src/api/endpoints/room/room.api.ts +++ b/src/frontend/src/api/endpoints/room/room.api.ts @@ -158,6 +158,7 @@ export const roomApi = { } }, + // 엘라스틱서치 검색 searchFromElastic: async (keyword: string) => { try { const { data } = await instance.get(`/search`, { params: { keyword } }); @@ -167,4 +168,36 @@ export const roomApi = { throw error; } }, + + // 방 초대 수락 + acceptInvitation: async (roomId: number, me: number, senderId: number, roomCode: string) => { + try { + const { data } = await instance.post(`/rooms/invitations/accept`, { + senderId, + receiverId: me, + roomId, + roomCode, + }); + return data; + } catch (error) { + logAxiosError(error, ErrorType.ROOM, '방 초대 수락 실패'); + throw error; + } + }, + + // 방 초대 거절 + rejectInvitation: async (roomId: number, me: number, senderId: number, roomCode: string) => { + try { + const { data } = await instance.post(`/rooms/invitations/reject`, { + senderId, + receiverId: me, + roomId, + roomCode, + }); + return data; + } catch (error) { + logAxiosError(error, ErrorType.ROOM, '방 초대 거절 실패'); + throw error; + } + }, }; From 5ce478c369289071f34a4f2c9effb0d33b7e9dac Mon Sep 17 00:00:00 2001 From: 42inshin Date: Wed, 26 Feb 2025 14:33:17 +0900 Subject: [PATCH 10/13] =?UTF-8?q?[FE]=20FEAT:=20ios=20=EB=A9=94=EC=8B=9C?= =?UTF-8?q?=EC=A7=80=20=ED=95=B8=EB=93=A4=EB=A7=81=20#248?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/components/Modal/RegisterSuccessModal/index.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/frontend/src/components/Modal/RegisterSuccessModal/index.tsx b/src/frontend/src/components/Modal/RegisterSuccessModal/index.tsx index 953c69de..a269a3ab 100644 --- a/src/frontend/src/components/Modal/RegisterSuccessModal/index.tsx +++ b/src/frontend/src/components/Modal/RegisterSuccessModal/index.tsx @@ -12,8 +12,8 @@ export const RegisterSuccessModal = ({ onCancel }: IRegisterSuccessModal) => { const navigate = useNavigate(); const handleConfirm = () => { - if (window.webkit?.messageHandlers?.closeModal) { - window.webkit.messageHandlers.closeModal.postMessage('LoginSuccess'); + if (window.webkit?.messageHandlers?.messageHandler) { + window.webkit.messageHandlers.messageHandler.postMessage('LoginSuccess'); } navigate('/login'); onCancel(); From 036b18b9093a6dd85c7088ba66fa67cf788fd220 Mon Sep 17 00:00:00 2001 From: 42inshin Date: Wed, 26 Feb 2025 14:35:44 +0900 Subject: [PATCH 11/13] =?UTF-8?q?[FE]=20FEAT:=20stomp=20=EA=B5=AC=EB=8F=85?= =?UTF-8?q?=20=ED=95=B4=EC=A7=80=20=EA=B8=B0=EB=8A=A5=20=EC=B6=94=EA=B0=80?= =?UTF-8?q?=20#248?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/frontend/src/stores/useWebSocketStore.ts | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/frontend/src/stores/useWebSocketStore.ts b/src/frontend/src/stores/useWebSocketStore.ts index fce3dd29..9b624ef6 100644 --- a/src/frontend/src/stores/useWebSocketStore.ts +++ b/src/frontend/src/stores/useWebSocketStore.ts @@ -43,6 +43,7 @@ interface WebSocketStore { playlist: { order: number; url: string; title: string; youtuber: string }[]; }) => void, ) => void; + unsubscribe: (destination: string) => void; unsubscribeAll: () => void; pubTopic: (destination: string, message: string) => void; } @@ -202,6 +203,15 @@ export const useWebSocketStore = create((set, get) => ({ get().subTopic(destination, callback); }, + unsubscribe: (destination: string) => { + const { client } = get(); + if (!client) return; + + const subscription = get().subscriptions.get(destination); + subscription?.unsubscribe(); + get().subscriptions.delete(destination); + }, + // 구독 해제 unsubscribeAll: () => { get().subscriptions.forEach(sub => sub.unsubscribe()); From c3c12c1b59a0407fc2f726140ab1905e0ea9b3ab Mon Sep 17 00:00:00 2001 From: 42inshin Date: Wed, 26 Feb 2025 15:18:24 +0900 Subject: [PATCH 12/13] =?UTF-8?q?[FE]=20BUG:=20=EC=83=88=EB=A1=9C=EA=B3=A0?= =?UTF-8?q?=EC=B9=A8=20=EC=8B=9C=20newMessageCount=20=EC=A6=9D=EA=B0=80?= =?UTF-8?q?=ED=95=98=EB=8A=94=20=EB=B2=84=EA=B7=B8=20#253?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/frontend/src/components/Sidebar/Chating/index.tsx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/frontend/src/components/Sidebar/Chating/index.tsx b/src/frontend/src/components/Sidebar/Chating/index.tsx index 5a00ea1c..502619ed 100644 --- a/src/frontend/src/components/Sidebar/Chating/index.tsx +++ b/src/frontend/src/components/Sidebar/Chating/index.tsx @@ -26,6 +26,7 @@ export const Chat = () => { if (isInitialLoad) { chatContainerRef.current.scrollTop = chatContainerRef.current.scrollHeight; + setnewMessageCount(0); setIsInitialLoad(false); } }, [messages, isInitialLoad]); @@ -58,6 +59,7 @@ export const Chat = () => { top: chatContainerRef.current.scrollHeight, behavior: 'smooth', }); + setnewMessageCount(0); }; // 메시지 추가 From d2dc796539945ea97ae0c75a540c0101b8d2be37 Mon Sep 17 00:00:00 2001 From: 42inshin Date: Wed, 26 Feb 2025 15:25:41 +0900 Subject: [PATCH 13/13] =?UTF-8?q?[FE]=20BUG:=20useEffect=20=EB=94=94?= =?UTF-8?q?=ED=8E=9C=EB=8D=98=EC=8B=9C=20=EC=B6=94=EA=B0=80=20#253?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/frontend/src/pages/RoomPage/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/frontend/src/pages/RoomPage/index.tsx b/src/frontend/src/pages/RoomPage/index.tsx index 89b6fc7a..a56d73f4 100644 --- a/src/frontend/src/pages/RoomPage/index.tsx +++ b/src/frontend/src/pages/RoomPage/index.tsx @@ -41,7 +41,7 @@ export const RoomPage = () => { useMyRoomsStore.getState().subscribeRoom(roomId); } }; - }, []); + }, [room]); // YouTube API를 이용하여 영상 정보(제목 & 유튜버) 가져오기 const fetchVideoDetails = async (videoIds: string[]) => {