diff --git a/client/src/api/user/index.ts b/client/src/api/user/index.ts index 89d79822..60025c98 100644 --- a/client/src/api/user/index.ts +++ b/client/src/api/user/index.ts @@ -123,7 +123,14 @@ type TChangeProfileImage = { ok: boolean, newProfileUrl: string } export const changeProfileImage = async (userDocumentId: string, formData: FormData) => { try { - const response = await fetch(`${process.env.REACT_APP_API_URL}/api/user/profile-image`, postCredentialsOption(formData)); + const response = await fetch( + `${process.env.REACT_APP_API_URL}/api/user/profile-image`, + { + method: 'post', + credentials: 'include', + body: formData, + }, + ); if (!response.ok) throw new Error(`HTTP Error! status: ${response.status}`); diff --git a/client/src/assets/styles/global-styles.ts b/client/src/assets/styles/global-styles.ts index 8bebc138..c2eff74f 100644 --- a/client/src/assets/styles/global-styles.ts +++ b/client/src/assets/styles/global-styles.ts @@ -11,6 +11,7 @@ const GlobalStyle = createGlobalStyle` font-weight: normal; font-style: normal; src: url(${Bangers}); + font-display: swap; } @font-face { @@ -18,6 +19,7 @@ const GlobalStyle = createGlobalStyle` font-weight: normal; font-style: normal; src: url(${Nunito}); + font-display: swap; } html, body { diff --git a/client/src/assets/styles/select.tsx b/client/src/assets/styles/select.tsx index bab7bb9c..c0f05253 100644 --- a/client/src/assets/styles/select.tsx +++ b/client/src/assets/styles/select.tsx @@ -40,7 +40,6 @@ export const SelectInputBar = styled.input` border: none; font-size: 18px; - font-family: 'Nunito'; &:focus { outline: none; diff --git a/client/src/components/chat/detail-view/footer/index.tsx b/client/src/components/chat/detail-view/footer/index.tsx index 9018b649..5bf04e04 100644 --- a/client/src/components/chat/detail-view/footer/index.tsx +++ b/client/src/components/chat/detail-view/footer/index.tsx @@ -1,14 +1,32 @@ import { useRef } from 'react'; import { FiSend } from 'react-icons/fi'; import { useRecoilValue } from 'recoil'; +import { Socket } from 'socket.io-client'; import userType from '@atoms/user'; +import chatSocketMessage from '@constants/socket-message/chat'; import { makeDateToHourMinute } from '@utils/index'; import { ChatRoomFooterStyle, MsgInput, SendBtnDiv } from './style'; +interface IChattingLog { + key: string, + message: string, + profileUrl: string, + userName: string, + userDocumentId: string, + date: string, +} + +interface IChatFooterProps { + addChattingLog: (arg: IChattingLog) => void, + chatDocumentId: string, + chatSocket: Socket, + participants: Array, +} + export default function ChatRoomFooter({ addChattingLog, chatDocumentId, chatSocket, participants, -}: any) { +}: IChatFooterProps) { const messageInputRef = useRef(null); const user = useRecoilValue(userType); @@ -20,7 +38,7 @@ export default function ChatRoomFooter({ if (message.trim() === '') return; - chatSocket?.emit('chat:sendMsg', { + chatSocket?.emit(chatSocketMessage.sendMsg, { userDocumentId: user.userDocumentId, userName: user.userName, profileUrl: user.profileUrl, @@ -29,10 +47,15 @@ export default function ChatRoomFooter({ chatDocumentId, key: `${nowDate.getTime()}_${user.userDocumentId}`, }); - chatSocket?.emit('chat:alertMsg', { participants, chatDocumentId }); - chatSocket?.emit('chat:updateCount', participants, chatDocumentId); + chatSocket?.emit(chatSocketMessage.alertMsg, { participants, chatDocumentId }); + chatSocket?.emit(chatSocketMessage.updateCount, participants, chatDocumentId); addChattingLog({ - userDocumentId: user.userDocumentId, userName: user.userName, profileUrl: user.profileUrl, message, date: makeDateToHourMinute(new Date()), + key: `${nowDate.getTime()}_${user.userDocumentId}`, + userDocumentId: user.userDocumentId, + userName: user.userName, + profileUrl: user.profileUrl, + message, + date: makeDateToHourMinute(nowDate), }); }; diff --git a/client/src/components/chat/detail-view/header/index.tsx b/client/src/components/chat/detail-view/header/index.tsx index 79a6f5e6..cd3b9d4d 100644 --- a/client/src/components/chat/detail-view/header/index.tsx +++ b/client/src/components/chat/detail-view/header/index.tsx @@ -7,8 +7,18 @@ import { BackBtn, ParticipantsDiv, ParticipantsProfileDiv, ParticipantsProfile, ParticipantsName, } from './style'; -export default React.memo(({ participantsInfo }: any) => { - const userNames = participantsInfo.map((user:any) => user.userName).join(', '); +interface IParticipantInfo { + profileUrl: string, + userDocumentId: string, + userName: string, +} + +interface IHeaderProps { + participantsInfo: Array +} + +export default React.memo(({ participantsInfo }: IHeaderProps) => { + const userNames = participantsInfo.map((user: IParticipantInfo) => user.userName).join(', '); return ( @@ -19,7 +29,7 @@ export default React.memo(({ participantsInfo }: any) => { - {participantsInfo.map((user: any) => ())} + {participantsInfo.map((user: IParticipantInfo) => ())} {userNames} diff --git a/client/src/components/chat/detail-view/index.tsx b/client/src/components/chat/detail-view/index.tsx index aac7d263..731d68af 100644 --- a/client/src/components/chat/detail-view/index.tsx +++ b/client/src/components/chat/detail-view/index.tsx @@ -26,12 +26,13 @@ import { type urlParams = { chatDocumentId: string }; interface IChattingLog { + key: string, message: string, profileUrl: string, userName: string, userDocumentId: string, date: string, - linkTo: string, + linkTo?: string, } function ChatRoomDetailView() { @@ -49,7 +50,7 @@ function ChatRoomDetailView() { let previousY = 0; let previousRatio = 0; - const addChattingLog = (chatLog: any) => { + const addChattingLog = (chatLog: IChattingLog) => { dispatch({ type: 'ADD_CHATTING_LOG', payload: { chatLog } }); chattingLogDiv.current!.scrollTop = chattingLogDiv.current!.scrollHeight - chattingLogDiv.current!.clientHeight; }; @@ -70,7 +71,7 @@ function ChatRoomDetailView() { }); }; - const moveToLink = (linkTo: string) => { + const moveToLink = (linkTo: string | undefined) => { if (!linkTo) return; setRoomView('inRoomView'); setRoomDocumentId(linkTo); @@ -83,7 +84,14 @@ function ChatRoomDetailView() { getChattingLog(chatDocumentId, chatState.chattingLog.length) .then((res: any) => { setNowFetching(false); - dispatch({ type: 'UPDATE', payload: { responseChattingLog: res.chattingLog, participantsInfo: location.state.participantsInfo, user } }); + dispatch({ + type: 'UPDATE', + payload: { + responseChattingLog: res.chattingLog, + participantsInfo: location.state.participantsInfo, + user, + }, + }); }); } }, [nowFetching]); @@ -101,7 +109,7 @@ function ChatRoomDetailView() { useEffect(() => { if (!chatSocket) return; chatSocket.emit(chatSocketMessage.roomJoin, chatDocumentId); - chatSocket.on(chatSocketMessage.sendMsg, (payload: any) => { + chatSocket.on(chatSocketMessage.sendMsg, (payload: IChattingLog) => { dispatch({ type: 'ADD_CHATTING_LOG', payload: { chatLog: payload } }); }); return () => { @@ -130,9 +138,9 @@ function ChatRoomDetailView() { {chatState.chattingLog.map(({ - message, profileUrl, userName, userDocumentId, date, linkTo, - } : IChattingLog, index: number) => ( - + message, profileUrl, userName, userDocumentId, date, linkTo, key, + } : IChattingLog) => ( + moveToLink(linkTo)}> {userDocumentId === user.userDocumentId @@ -151,7 +159,7 @@ function ChatRoomDetailView() { addChattingLog={addChattingLog} chatDocumentId={chatDocumentId} chatSocket={chatSocket} - participants={location.state.participantsInfo.map((participant: any) => participant.userDocumentId)} + participants={location.state.participantsInfo.map((participant: IChattingLog) => participant.userDocumentId)} /> ); diff --git a/client/src/components/chat/detail-view/reducer.ts b/client/src/components/chat/detail-view/reducer.ts index a3a4ef92..1a73c11e 100644 --- a/client/src/components/chat/detail-view/reducer.ts +++ b/client/src/components/chat/detail-view/reducer.ts @@ -5,6 +5,13 @@ import { deepCopy, makeDateToHourMinute } from '@utils/index'; +interface IChatBasicInfo { + date: string, + userDocumentId: string, + message: string, + linkTo?: string, +} + export const initialState = { chattingLog: [], }; @@ -24,7 +31,7 @@ export function chatReducer(state: any, action: any): any { case 'UPDATE': { const { responseChattingLog, user, participantsInfo } = payload; - const newChattingLog = responseChattingLog.map((chat: any) => { + const newChattingLog = responseChattingLog.map((chat: IChatBasicInfo) => { if (chat.userDocumentId === user.userDocumentId) { return ({ key: `${new Date(chat.date).getTime()}_${chat.userDocumentId}`, @@ -37,7 +44,7 @@ export function chatReducer(state: any, action: any): any { }); } - const userData = participantsInfo.filter((userInfo: any) => userInfo.userDocumentId === chat.userDocumentId); + const userData = participantsInfo.filter((userInfo: IChatBasicInfo) => userInfo.userDocumentId === chat.userDocumentId); return ({ key: `${new Date(chat.date).getTime()}_${chat.userDocumentId}`, message: chat.message, diff --git a/client/src/components/chat/main-view/index.tsx b/client/src/components/chat/main-view/index.tsx index 08f70b7e..22f1b289 100644 --- a/client/src/components/chat/main-view/index.tsx +++ b/client/src/components/chat/main-view/index.tsx @@ -7,6 +7,7 @@ import unReadMsgCountState from '@atoms/not-read-msg'; import ChatRoomListHeader from '@src/components/chat/main-view/header'; import ChatUserCard from '@src/components/chat/main-view/chat-card'; import { ChatRoomsLayout } from '@components/chat/style'; +import chatSocketMessage from '@constants/socket-message/chat'; import LoadingSpinner from '@styles/loading-spinner'; import { getChatRooms } from '@api/chat'; import { makeDateToHourMinute, makeDateToMonthDate } from '@utils/index'; @@ -77,11 +78,11 @@ function ChatRoomsViews() { useEffect(() => { if (!socket) return; - socket.on('chat:alertMsg', setNewRooms); - socket.on('chat:makeChat', newChatRooms); + socket.on(chatSocketMessage.alertMsg, setNewRooms); + socket.on(chatSocketMessage.makeChat, newChatRooms); return () => { - socket.off('chat:alertMsg'); - socket.off('chat:makeChat'); + socket.off(chatSocketMessage.alertMsg); + socket.off(chatSocketMessage.makeChat); }; }, [socket]); diff --git a/client/src/components/common/default-header/index.tsx b/client/src/components/common/default-header/index.tsx index 7103dac8..6e0eca4b 100644 --- a/client/src/components/common/default-header/index.tsx +++ b/client/src/components/common/default-header/index.tsx @@ -92,16 +92,16 @@ function DefaultHeader() { - + {leftSideIcons.map(makeIconToLink)} - + {unReadMsgCount > 0 ? {unReadMsgCount > 99 ? '99+' : unReadMsgCount} : ''} {rightSideIcons.map(makeIconToLink)} - + {isActivityChecked ? : ''} diff --git a/client/src/components/common/menu-modal/index.tsx b/client/src/components/common/menu-modal/index.tsx index 3a97a8ec..fd2d1f70 100644 --- a/client/src/components/common/menu-modal/index.tsx +++ b/client/src/components/common/menu-modal/index.tsx @@ -30,26 +30,26 @@ function SliderMenu({ isActivityChecked, unReadMsgCount }: any) { setIsOpenRoom(false); }; - const makeLinkListToStyledLink = (list: ILinkList) => { - if (list.key === 'chat-rooms') { + const makeLinkListToStyledLink = (listItem: ILinkList) => { + if (listItem.key === 'chat-rooms') { return ( - - {list.text} + + {listItem.text} {unReadMsgCount > 0 ? {unReadMsgCount > 99 ? '99+' : unReadMsgCount} : ''} ); } - if (list.key === 'activity') { + if (listItem.key === 'activity') { return ( - - {list.text} + + {listItem.text} {isActivityChecked ? : ''} ); } return ( - - {list.text} + + {listItem.text} ); }; @@ -67,7 +67,7 @@ function SliderMenu({ isActivityChecked, unReadMsgCount }: any) { setIsOpenMenu(!isOpenMenu)} /> - + diff --git a/client/src/components/common/toast/style.ts b/client/src/components/common/toast/style.ts index 9c380359..4b4a0a6d 100644 --- a/client/src/components/common/toast/style.ts +++ b/client/src/components/common/toast/style.ts @@ -24,6 +24,11 @@ export const Notification = styled.div` height: 50px; width: 365px; + + @media (max-width: 768px){ + width: 250px; + } + color: #fff; padding: 20px 15px 10px 10px; diff --git a/client/src/components/event/register-modal/index.tsx b/client/src/components/event/register-modal/index.tsx index aaeddbbc..ceeca983 100644 --- a/client/src/components/event/register-modal/index.tsx +++ b/client/src/components/event/register-modal/index.tsx @@ -6,6 +6,7 @@ import toastListSelector from '@selectors/toast-list'; import { BackgroundWrapper } from '@styles/modal'; import postEvent from '@api/event'; import { nowCountState, nowFetchingState, nowItemsListState } from '@src/recoil/atoms/main-section-scroll'; +import toastMessage from '@constants/toast-message'; import EventSelectUserDropdown from './select-uesr-dropdown'; import { CustomEventRegisterModal, ModalHeader, CustomEventForm, CustomFormBox, @@ -51,11 +52,7 @@ function EventRegisterModal() { }; await postEvent(eventInfo); - setToastList({ - type: 'success', - title: '등록 성공', - description: `${inputTitleRef.current?.value} 이벤트가 등록되었습니다!`, - }); + setToastList(toastMessage.addEventSuccess(`${inputTitleRef.current?.value} 이벤트가 등록되었습니다!`)); changeModalState(); resetNowItemsList(); diff --git a/client/src/components/event/register-modal/style.ts b/client/src/components/event/register-modal/style.ts index 31d96571..ecb444b2 100644 --- a/client/src/components/event/register-modal/style.ts +++ b/client/src/components/event/register-modal/style.ts @@ -100,7 +100,6 @@ export const SelectUserComponent = styled.div` background-color: #F1F0E4; border-radius: 30px; - font-family: 'Nunito'; color: #819C88; cursor: default; diff --git a/client/src/components/invite/index.tsx b/client/src/components/invite/index.tsx index 877886c7..e07d5d6a 100644 --- a/client/src/components/invite/index.tsx +++ b/client/src/components/invite/index.tsx @@ -7,6 +7,7 @@ import { useSetRecoilState } from 'recoil'; import toastListSelector from '@selectors/toast-list'; import { CustomInputBox, CustomInputBar } from '@styles/custom-inputbar'; import DefaultButton from '@common/default-button'; +import toastMessage from '@constants/toast-message'; import LoadingSpinner from '@styles/loading-spinner'; import { testEmailValidation } from '@utils/index'; import { InviteBody, InviteInputLayout, InputTitle } from './style'; @@ -36,19 +37,11 @@ function InviteView({ history }: RouteComponentProps) { }).then((res) => res.json()) as { isUnique: boolean }; if (isUnique) { setLoading(false); - setToastList({ - type: 'success', - title: '전송 완료', - description: '초대장이 발송되었습니다', - }); + setToastList(toastMessage.inviteSuccess()); history.push('/'); } else { setLoading(false); - setToastList({ - type: 'warning', - title: '초대장 에러', - description: '이미 존재하는 이메일입니다', - }); + setToastList(toastMessage.inviteWarning('exist')); } }; @@ -59,11 +52,7 @@ function InviteView({ history }: RouteComponentProps) { setLoading(true); fetchPostInviteMail(inputEmailValue); } else { - setToastList({ - type: 'warning', - title: '초대장 에러', - description: '올바른 형식의 이메일을 입력해주세요', - }); + setToastList(toastMessage.inviteWarning('validation')); } }; diff --git a/client/src/components/main/left-sidebar/active-following-card/style.ts b/client/src/components/main/left-sidebar/active-following-card/style.ts index 8efee807..abfbfa82 100644 --- a/client/src/components/main/left-sidebar/active-following-card/style.ts +++ b/client/src/components/main/left-sidebar/active-following-card/style.ts @@ -40,7 +40,6 @@ export const DescriptionLayout = styled.div` display: flex; flex-direction : column; justify-content: center; - font-family: 'Nunito'; `; export const UserName = styled.div` diff --git a/client/src/components/main/left-sidebar/index.tsx b/client/src/components/main/left-sidebar/index.tsx index 6a376429..97829fe9 100644 --- a/client/src/components/main/left-sidebar/index.tsx +++ b/client/src/components/main/left-sidebar/index.tsx @@ -5,7 +5,7 @@ import { useRecoilValue, useSetRecoilState } from 'recoil'; import followingListState from '@atoms/following-list'; import userState from '@atoms/user'; -import { IToast } from '@atoms/toast-list'; +import toastMessage from '@constants/toast-message'; import userSocketMessage from '@constants/socket-message/user'; import toastListSelector from '@selectors/toast-list'; import useUserSocket from '@utils/user-socket'; @@ -57,12 +57,7 @@ function LeftSideBar() { }); userSocket.on(userSocketMessage.hands, (handsData: { from: Partial, to: string }) => { if (handsData.to === user.userDocumentId) { - const newToast: IToast = { - type: 'info', - title: '반가운 인사', - description: `${handsData.from.userName}님이 손을 흔들었습니다!`, - }; - setToastList(newToast); + setToastList(toastMessage.handsInfo(handsData.from.userName as string)); } }); }, [user]); diff --git a/client/src/components/main/style.ts b/client/src/components/main/style.ts index 6fcc6902..30c286ac 100644 --- a/client/src/components/main/style.ts +++ b/client/src/components/main/style.ts @@ -40,7 +40,7 @@ export const MainSectionLayout = styled.div` } @media (max-width: 768px){ - height: calc(100%-100px); + height: calc(100% - 100px); } @media (min-width: 1025px) { diff --git a/client/src/components/profile/modal/change-profile-image/index.tsx b/client/src/components/profile/modal/change-profile-image/index.tsx index 2cb0732d..310d1dcd 100644 --- a/client/src/components/profile/modal/change-profile-image/index.tsx +++ b/client/src/components/profile/modal/change-profile-image/index.tsx @@ -9,6 +9,7 @@ import { ModalBox, BackgroundWrapper } from '@styles/modal'; import userState from '@atoms/user'; import DefaultButton from '@common/default-button'; import userSocketMessage from '@constants/socket-message/user'; +import toastMessage from '@constants/toast-message'; import { changeProfileImage } from '@api/user'; import useUserSocket from '@utils/user-socket'; import { @@ -24,6 +25,11 @@ function ShareModal() { const [potentialProfileImage, setPotentialProfileImage] = useState(null); const followingList = useRecoilValue(followingListState); + const checkFileSize = (image: File) => { + if (image.size > 2097152) return false; + return true; + }; + const inputOnChange = (e : any) => { if (e.target.files[0]) { const imageFile = e.target.files[0]; @@ -35,19 +41,23 @@ function ShareModal() { const changeImageHandler = async () => { if (potentialProfileImage) { + if (!checkFileSize(potentialProfileImage)) { + setToastList({ + type: 'warning', + title: '프로필 사진 이미지 제한', + description: '프로필 사진의 크기는 2MB 이하입니다.', + }); + + return; + } const formData = new FormData(); formData.append('profileImage', potentialProfileImage); formData.append('userDocumentId', user.userDocumentId); - // eslint-disable-next-line max-len const response = await changeProfileImage(user.userDocumentId, formData) as any; const { newProfileUrl } = response; setUser((oldUser) => ({ ...oldUser, profileUrl: newProfileUrl })); setIsOpenChangeProfileImageModalState(!isOpenChangeProfileImageModal); - setToastList({ - type: 'success', - title: '프로필 설정', - description: '지정한 이미지로 변경이 완료됐습니다', - }); + setToastList(toastMessage.profileChangeSuccess()); const userSocket = useUserSocket(); if (userSocket) { userSocket.emit(userSocketMessage.join, { diff --git a/client/src/components/room/in-view/index.tsx b/client/src/components/room/in-view/index.tsx index 98e64657..e31bed64 100644 --- a/client/src/components/room/in-view/index.tsx +++ b/client/src/components/room/in-view/index.tsx @@ -12,6 +12,7 @@ import { IParticipant, InRoomUserBox, InRoomOtherUserBox } from '@components/roo import roomSocketMessage from '@constants/socket-message/room'; import { getRoomInfo } from '@api/room'; import { useRtc, IRTC } from '@hooks/useRtc'; +import toastMessage from '@constants/toast-message'; import { InRoomHeader, TitleDiv, InRoomFooter, InRoomUserList, FooterBtnDiv, } from './style'; @@ -42,11 +43,7 @@ function InRoomModal() { if (!res) setRoomView('notFoundRoomView'); else if (res.participants.length > 5) { setRoomView('createRoomView'); - setToastList({ - type: 'danger', - title: '방 접속 실패', - description: '입장 가능 인원수가 초과되어 입장이 불가능 합니다', - }); + setToastList(toastMessage.roomLimitOverDanger()); } else setRoomInfo(res); }); diff --git a/client/src/components/room/in-view/style.ts b/client/src/components/room/in-view/style.ts index fe3d2230..011d6903 100644 --- a/client/src/components/room/in-view/style.ts +++ b/client/src/components/room/in-view/style.ts @@ -15,7 +15,6 @@ export const InRoomHeader = styled.div` `; export const TitleDiv = styled.div` - font-family: "Nunito"; font-style: normal; font-size: 20px; diff --git a/client/src/components/room/modal/follower-select-header.tsx b/client/src/components/room/modal/follower-select-header.tsx index 7a43dfab..7dd0e7f8 100644 --- a/client/src/components/room/modal/follower-select-header.tsx +++ b/client/src/components/room/modal/follower-select-header.tsx @@ -7,6 +7,7 @@ import userState from '@atoms/user'; import roomViewState from '@atoms/room-view-type'; import { isOpenRoomModalState } from '@atoms/is-open-modal'; import roomDoucumentIdState from '@atoms/room-document-id'; +import toastMessage from '@constants/toast-message'; import chatSocketMessage from '@constants/socket-message/chat'; import { makeDateToHourMinute } from '@utils/index'; import useChatSocket from '@utils/chat-socket'; @@ -43,11 +44,7 @@ export default function FollowerSelectRoomHeader({ onClick, selectedUsers }: any key: `${nowDate.getTime()}_${user.userDocumentId}`, }; chatSocket.emit(chatSocketMessage.inviteRoom, inviteInfo); - setToastList({ - type: 'success', - title: '방 초대', - description: '초대 메세지를 보냈습니다!', - }); + setToastList(toastMessage.roomInviteSuccess); setRoomView('inRoomView'); setIsOpenRoomModal(false); }; diff --git a/client/src/components/room/new-view/index.tsx b/client/src/components/room/new-view/index.tsx index a4cbfc83..33df8afc 100644 --- a/client/src/components/room/new-view/index.tsx +++ b/client/src/components/room/new-view/index.tsx @@ -11,6 +11,7 @@ import DefaultButton from '@common/default-button'; import RoomTypeCheckBox from '@components/room/common/room-type-check-box'; import AnonymousCheckBox from '@components/room/new-view/anonymous-checkbox'; import { ButtonLayout } from '@components/room/common/style'; +import toastMessage from '@constants/toast-message'; import toastListSelector from '@selectors/toast-list'; import { CustomTitleForm, TitleInputbar, CheckboxLayout, TitleInputbarLabel, @@ -46,11 +47,7 @@ function RoomModal() { } }) .catch((err) => { - setToastList({ - type: 'danger', - title: '방 생성', - description: '방 생성을 실패했습니다', - }); + setToastList(toastMessage.roomCreateDanger()); console.error(err); }); }; @@ -70,11 +67,7 @@ function RoomModal() { const randomlyAssignedHandler = async () => { const roomDocumentId = await getRandomRoomDocumentId(); if (roomDocumentId === 'NO_ROOM') { - setToastList({ - type: 'danger', - title: '방 매칭 실패', - description: '현재 접속 가능한 익명 허용 방이 없습니다', - }); + setToastList(toastMessage.roomMatchingDanger()); } else { setRoomDocumentId(roomDocumentId); setRoomView('selectModeView'); diff --git a/client/src/components/sign/signin-view/index.tsx b/client/src/components/sign/signin-view/index.tsx index 96bbcb9f..5ed27f93 100644 --- a/client/src/components/sign/signin-view/index.tsx +++ b/client/src/components/sign/signin-view/index.tsx @@ -2,14 +2,15 @@ import React, { useEffect, useRef, useState } from 'react'; import { useSetRecoilState } from 'recoil'; import { useHistory } from 'react-router-dom'; -import toastListSelector from '@selectors/toast-list'; +import { postSignIn } from '@api/user'; import SignHeader from '@components/sign/common/sign-header'; import SignTitle from '@components/sign/common/sign-title'; import { SignBody } from '@components/sign/common/style'; import DefaultButton from '@common/default-button'; +import toastMessage from '@constants/toast-message'; +import toastListSelector from '@selectors/toast-list'; import { CustomInputBox, CustomInputBar } from '@styles/custom-inputbar'; import { setAccessToken } from '@utils/index'; -import { postSignIn } from '@api/user'; function SignInView() { const inputEmailRef = useRef(null); @@ -36,11 +37,7 @@ function SignInView() { setAccessToken(json.accessToken as string); history.go(0); } else { - setToastList({ - type: 'warning', - title: '로그인 에러', - description: '로그인 정보를 확인하세요', - }); + setToastList(toastMessage.signInWarning()); } }; diff --git a/client/src/components/sign/signup-info-view/index.tsx b/client/src/components/sign/signup-info-view/index.tsx index 0f4908ca..cce3324b 100644 --- a/client/src/components/sign/signup-info-view/index.tsx +++ b/client/src/components/sign/signup-info-view/index.tsx @@ -12,6 +12,7 @@ import { CustomInputBox, CustomInputBar, InputLayout, CustomInputBoxLayout, } from '@styles/custom-inputbar'; import { postSignUpUserInfo, getUserExistenceByUserId } from '@api/user'; +import toastMessage from '@src/constants/toast-message'; const CustomInfoInputBar = styled(CustomInputBar)` font-size: min(5vw, 30px); @@ -40,44 +41,63 @@ function SignupInfoView() { const checkPasswordValidity = () => inputPasswordRef.current?.value.length as number >= 6 && inputPasswordRef.current?.value.length as number <= 16; const checkPassword = () => inputPasswordRef.current?.value === inputPasswordCheckRef.current?.value; - const checkUserId = async () => { + const checkUserIdLength = () => inputIdRef.current?.value.length as number >= 2 + && inputIdRef.current?.value.length as number <= 12; + const checkUserIdIsExisted = async () => { const result = await getUserExistenceByUserId(inputIdRef.current?.value as string); return result; }; + const checkUserName = () => inputFullNameRef.current?.value.length as number >= 2 + && inputFullNameRef.current?.value.length as number <= 12; - const onClickNextButton = async () => { + const checkValidation = async () => { if (!checkPasswordValidity()) { + setToastList(toastMessage.signupInfoWarning('passLength')); + + return false; + } + + if (!checkPassword()) { + setToastList(toastMessage.signupInfoWarning('passMatching')); + + return false; + } + + if (!checkUserName()) { setToastList({ type: 'warning', - title: '비밀번호 에러', - description: '비밀번호는 6자 이상 16자 이하입니다.', + title: '이름 길이 제한', + description: '이름은 2자 이상 12자 이하입니다.', }); - return; + return false; } - if (!checkPassword()) { + if (!checkUserIdLength()) { setToastList({ type: 'warning', - title: '비밀번호 일치 에러', - description: '비밀번호가 일치하지 않습니다.', + title: '아이디 길이 제한', + description: '아이디는 2자 이상 12자 이하입니다.', }); - return; + return false; } - const isExistedId = await checkUserId(); + const isExistedId = await checkUserIdIsExisted(); if (isExistedId) { - setToastList({ - type: 'warning', - title: '아이디 중복 에러', - description: '이미 존재하는 아이디입니다.', - }); + setToastList(toastMessage.signupInfoWarning('idExist')); - return; + return false; } + return true; + }; + + const onClickNextButton = async () => { + const isValidated = await checkValidation(); + if (!isValidated) return; + const userInfo = { loginType: 'normal', userId: inputIdRef.current?.value as string, diff --git a/client/src/components/sign/signup-view/index.tsx b/client/src/components/sign/signup-view/index.tsx index 4ef29e92..17d2b7be 100644 --- a/client/src/components/sign/signup-view/index.tsx +++ b/client/src/components/sign/signup-view/index.tsx @@ -11,6 +11,7 @@ import { SignBody } from '@components/sign/common/style'; import { CustomInputBox, CustomInputBar, CustomInputBoxLayout } from '@styles/custom-inputbar'; import { testEmailValidation } from '@utils/index'; import { postCheckMail } from '@api/user'; +import toastMessage from '@src/constants/toast-message'; import CustomBackgroundWrapper from './style'; function SignUpView() { @@ -47,11 +48,7 @@ function SignUpView() { setIsEmailInputView(false); } else { setLoading(false); - setToastList({ - type: 'warning', - title: '로그인 에러', - description: '이미 존재하는 이메일입니다', - }); + setToastList(toastMessage.signupWarning('emailExist')); } }; @@ -62,11 +59,7 @@ function SignUpView() { setLoading(true); fetchPostMail(inputEmailValue); } else { - setToastList({ - type: 'warning', - title: '로그인 에러', - description: '올바른 이메일을 입력해주세요', - }); + setToastList(toastMessage.signupWarning('emailValidation')); } }; @@ -76,11 +69,7 @@ function SignUpView() { if (inputVerificationValue === (verificationNumberRef.current?.toString())) { history.replace('/signup/info', { email: emailState.current }); } else { - setToastList({ - type: 'warning', - title: '로그인 에러', - description: '인증번호를 확인하세요.', - }); + setToastList(toastMessage.signupWarning('verification')); } }; diff --git a/client/src/constants/socket-message/chat.ts b/client/src/constants/socket-message/chat.ts index 99d3dac7..d059083b 100644 --- a/client/src/constants/socket-message/chat.ts +++ b/client/src/constants/socket-message/chat.ts @@ -5,6 +5,7 @@ type TChatSocketMessage = { inviteRoom: string, leave: string, sendMsg: string, + alertMsg: string, updateCount: string, } @@ -15,5 +16,6 @@ export default { inviteRoom: 'chat:inviteRoom', leave: 'chat:leave', sendMsg: 'chat:sendMsg', + alertMsg: 'chat:alertMsg', updateCount: 'chat:updateCount', } as TChatSocketMessage; diff --git a/client/src/constants/toast-message.ts b/client/src/constants/toast-message.ts new file mode 100644 index 00000000..0f6c88aa --- /dev/null +++ b/client/src/constants/toast-message.ts @@ -0,0 +1,107 @@ +import { IToast } from '@atoms/toast-list'; + +const inviteWarningType = { + exist: '이미 존재하는 이메일입니다', + validation: '올바른 형식의 이메일을 입력해주세요', +}; + +const signupWaringType = { + emailExist: { + title: '로그인 에러', + description: '이미 존재하는 이메일입니다', + }, + emailValidation: { + title: '로그인 에러', + description: '올바른 이메일을 입력해주세요', + }, + verification: { + title: '로그인 에러', + description: '인증번호를 확인하세요.', + }, +}; +const signupInfoWaringType = { + passLength: { + title: '비밀번호 에러', + description: '비밀번호는 6자 이상 16자 이하입니다.', + }, + passMatching: { + title: '비밀번호 일치 에러', + description: '비밀번호가 일치하지 않습니다.', + }, + idExist: { + title: '아이디 중복 에러', + description: '이미 존재하는 아이디입니다.', + }, +}; + +export default { + addEventSuccess: (description: string): IToast => ({ + type: 'success', + title: '등록 성공', + description, + }), + inviteSuccess: (): IToast => ({ + type: 'success', + title: '전송 완료', + description: '초대장이 발송되었습니다', + }), + inviteWarning: (type: 'exist' | 'validation'): IToast => ({ + type: 'warning', + title: '초대장 에러', + description: inviteWarningType[type], + }), + handsInfo: (userName: string): IToast => ({ + type: 'info', + title: '반가운 인사', + description: `${userName}님이 손을 흔들었습니다!`, + }), + profileChangeSuccess: (): IToast => ({ + type: 'success', + title: '프로필 설정', + description: '지정한 이미지로 변경이 완료됐습니다', + }), + roomInviteSuccess: (): IToast => ({ + type: 'success', + title: '방 초대', + description: '초대 메세지를 보냈습니다!', + }), + roomLimitOverDanger: (): IToast => ({ + type: 'danger', + title: '방 접속 실패', + description: '입장 가능 인원수가 초과되어 입장이 불가능 합니다', + }), + roomCreateSuccess: (): IToast => ({ + type: 'success', + title: '방 생성', + description: '성공적으로 방이 생성됐습니다!', + }), + roomCreateDanger: (): IToast => ({ + type: 'danger', + title: '방 생성', + description: '방 생성을 실패했습니다', + }), + roomAllowMicDanger: (): IToast => ({ + type: 'danger', + title: '장치 허용', + description: '마이크를 허용하지 않을 경우 방에 참가할 수 없습니다.', + }), + roomMatchingDanger: (): IToast => ({ + type: 'danger', + title: '방 매칭 실패', + description: '현재 접속 가능한 익명 허용 방이 없습니다', + }), + signInWarning: (): IToast => ({ + type: 'warning', + title: '로그인 에러', + description: '로그인 정보를 확인하세요', + }), + signupInfoWarning: (type: 'passLength' | 'passMatching' | 'idExist'): IToast => ({ + type: 'warning', + ...signupInfoWaringType[type], + }), + signupWarning: (type: 'emailExist' | 'emailValidation' | 'verification'): IToast => ({ + type: 'warning', + ...signupWaringType[type], + }), +}; +// import toastMessage from '@constants/toast-message'; diff --git a/client/src/constants/toast-mssage.ts b/client/src/constants/toast-mssage.ts deleted file mode 100644 index ff8b4c56..00000000 --- a/client/src/constants/toast-mssage.ts +++ /dev/null @@ -1 +0,0 @@ -export default {}; diff --git a/client/src/hooks/useIsFollowingRef.tsx b/client/src/hooks/useIsFollowingRef.tsx index 9babedec..dbe30b68 100644 --- a/client/src/hooks/useIsFollowingRef.tsx +++ b/client/src/hooks/useIsFollowingRef.tsx @@ -1,13 +1,13 @@ /* eslint-disable no-unused-expressions */ import react, { useCallback, useRef } from 'react'; -import { useRecoilState } from 'recoil'; +import { useSetRecoilState } from 'recoil'; import followingListState from '@src/recoil/atoms/following-list'; const useIsFollowingRef = (setLoading: React.Dispatch>, isFollowDafult?: boolean) : [react.MutableRefObject, (isFollow: boolean, targetUserDocumentId: string) => void] => { const isFollowingRef = useRef(isFollowDafult as boolean); - const [followingList, setFollowingList] = useRecoilState(followingListState); + const setFollowingList = useSetRecoilState(followingListState); const fetchFollow = useCallback((isFollow: boolean, targetUserDocumentId: string) => { setLoading(true); @@ -27,7 +27,6 @@ const useIsFollowingRef = (setLoading: React.Dispatch [...followList, targetUserDocumentId]); isFollowingRef.current = !isFollowingRef.current; } - console.log(followingList); setLoading(false); }); }, [isFollowingRef.current]); diff --git a/client/src/hooks/useRtc.tsx b/client/src/hooks/useRtc.tsx index 11f193f3..c5222634 100644 --- a/client/src/hooks/useRtc.tsx +++ b/client/src/hooks/useRtc.tsx @@ -12,6 +12,7 @@ import anonymousState from '@atoms/anonymous'; import roomViewState from '@atoms/room-view-type'; import roomSocketMessage from '@constants/socket-message/room'; import toastListSelector from '@selectors/toast-list'; +import toastMessage from '@src/constants/toast-message'; export interface IRTC { socketId?: string, @@ -128,18 +129,10 @@ export const useRtc = (): [ socket.emit(roomSocketMessage.join, { roomDocumentId, userDocumentId: user.userDocumentId, socketId: socket!.id, isAnonymous, }); - setToastList({ - type: 'success', - title: '방 생성', - description: '성공적으로 방이 생성됐습니다!', - }); + setToastList(toastMessage.roomCreateSuccess()); } catch (error) { console.error(error); - setToastList({ - type: 'danger', - title: '장치 허용', - description: '마이크를 허용하지 않을 경우 방에 참가할 수 없습니다.', - }); + setToastList(toastMessage.roomAllowMicDanger()); setRoomView('createRoomView'); } }; diff --git a/client/src/utils/index.tsx b/client/src/utils/index.tsx index 79b06278..44fa314d 100644 --- a/client/src/utils/index.tsx +++ b/client/src/utils/index.tsx @@ -10,7 +10,7 @@ interface Params { export const makeIconToLink = ({ Component, link, key, size = 48, color = 'black', }: IconAndLink) => ( - + ); diff --git a/server/package.json b/server/package.json index c44655de..e310712f 100644 --- a/server/package.json +++ b/server/package.json @@ -69,6 +69,7 @@ "@services/*": "src/services/*", "@subscribers/*": "src/subscribers/*", "@types/*": "src/types/*", - "@utils/*": "src/utils/*" + "@utils/*": "src/utils/*", + "@constants/*": "src/constants/*" } } diff --git a/server/src/api/middlewares/image-upload.ts b/server/src/api/middlewares/image-upload.ts index 7a813164..c51fc1ee 100644 --- a/server/src/api/middlewares/image-upload.ts +++ b/server/src/api/middlewares/image-upload.ts @@ -18,10 +18,10 @@ const storage = multerS3({ acl: 'public-read', key(req:Request, file, cb) { - const originFilename = file.originalname; - const extension = originFilename.substring(originFilename.lastIndexOf('.')); + const originFileName = file.originalname; + const extension = originFileName.substring(originFileName.lastIndexOf('.')); cb(null, `uploads/profile-images/${new Date().getTime()}-${v4()}${extension}`); }, }); -export default multer({ storage }); +export default multer({ storage, limits: { fileSize: 2 * 1024 * 1024 } }); diff --git a/server/src/constants/socket-message/chat.ts b/server/src/constants/socket-message/chat.ts new file mode 100644 index 00000000..d059083b --- /dev/null +++ b/server/src/constants/socket-message/chat.ts @@ -0,0 +1,21 @@ +type TChatSocketMessage = { + viewJoin: string, + roomJoin: string, + makeChat: string, + inviteRoom: string, + leave: string, + sendMsg: string, + alertMsg: string, + updateCount: string, +} + +export default { + viewJoin: 'chat:viewJoin', + roomJoin: 'chat:roomJoin', + makeChat: 'chat:makeChat', + inviteRoom: 'chat:inviteRoom', + leave: 'chat:leave', + sendMsg: 'chat:sendMsg', + alertMsg: 'chat:alertMsg', + updateCount: 'chat:updateCount', +} as TChatSocketMessage; diff --git a/server/src/constants/socket-message/room.ts b/server/src/constants/socket-message/room.ts new file mode 100644 index 00000000..5b5b45be --- /dev/null +++ b/server/src/constants/socket-message/room.ts @@ -0,0 +1,17 @@ +type TRoomSocketMessage = { + join: string, + offer: string, + answer: string, + ice: string, + mic: string, + leave: string +} + +export default { + join: 'room:join', + offer: 'room:offer', + answer: 'room:answer', + ice: 'room:ice', + mic: 'room:mic', + leave: 'room:leave', +} as TRoomSocketMessage; diff --git a/server/src/constants/socket-message/user.ts b/server/src/constants/socket-message/user.ts new file mode 100644 index 00000000..1b4c2614 --- /dev/null +++ b/server/src/constants/socket-message/user.ts @@ -0,0 +1,17 @@ +type TUserSocketMessage = { + join: string, + getActivity: string, + firstFollowingList: string, + newActiveUser: string, + newLeaveUser: string, + hands: string, +} + +export default { + join: 'user:join', + getActivity: 'user:getActivity', + firstFollowingList: 'user:firstFollowingList', + newActiveUser: 'user:newActiveUser', + newLeaveUser: 'user:newLeaveUser', + hands: 'user:hands', +} as TUserSocketMessage; diff --git a/server/src/models/chats.ts b/server/src/models/chats.ts index 99e9d2de..67fb19eb 100644 --- a/server/src/models/chats.ts +++ b/server/src/models/chats.ts @@ -1,10 +1,10 @@ import { Schema, Document, model } from 'mongoose'; -interface IChattingLog { +export interface IChattingLog { userDocumentId: string, message: string, date: Date, - linkTo: string, + linkTo?: string, } export interface IUnReadMsg { diff --git a/server/src/services/chat-service.ts b/server/src/services/chat-service.ts index a644aef7..74d15102 100644 --- a/server/src/services/chat-service.ts +++ b/server/src/services/chat-service.ts @@ -1,8 +1,23 @@ +/* eslint-disable no-throw-literal */ /* eslint-disable prefer-destructuring */ /* eslint-disable no-return-await */ /* eslint-disable no-return-assign */ import Users from '@models/users'; -import Chats, { IUnReadMsg } from '@models/chats'; +import Chats, { IUnReadMsg, IChattingLog } from '@models/chats'; + +interface IUserInfo { + userDocumentId: string, + userName: string, + profileUrl: string, +} + +interface IChatInfo { + chatDocumentId: string, + participants: Array, + lastMsg: string | undefined, + recentActive: Date | undefined, + unCheckedMsg: number, +} let instance: any = null; @@ -15,9 +30,9 @@ class ChatService { async getChatRooms(userDocumentId : string) { const chatRoomList = await Users.findOne({ _id: userDocumentId }, ['chatRooms']); - const chatRoomInfoArray = await Promise.all((chatRoomList!.chatRooms).map(async (chatDocumentId: string) => { + const chatRoomInfoArray : Array = await Promise.all((chatRoomList!.chatRooms).map(async (chatDocumentId: string) => { const chatRoomInfo = await Chats.findOne({ _id: chatDocumentId }, ['participants', 'lastMsg', 'recentActive', 'unReadMsg']); - const UserInfo : any = []; + const UserInfo : Array = []; await Promise.all((chatRoomInfo)!.participants.map(async (_id) => { if (_id === userDocumentId) return; const info = await Users.findOne({ _id }, ['userName', 'profileUrl']); @@ -34,11 +49,17 @@ class ChatService { }); })); - return chatRoomInfoArray.sort((a: any, b: any) => { - if (a.recentActive < b.recentActive) return 1; - if (a.recentActive > b.recentActive) return -1; - return 0; - }); + try { + return chatRoomInfoArray.sort((a, b) => { + if (!a.recentActive || !b.recentActive) throw 'undefined exception'; + if (a.recentActive < b.recentActive) return 1; + if (a.recentActive > b.recentActive) return -1; + return 0; + }); + } catch (e) { + console.log(e); + return []; + } } async makeChatRoom(participants: Array) { @@ -62,7 +83,7 @@ class ChatService { return { chattingLog: chattingLog!.chattingLog.slice(size - count - 10, size - count).reverse() }; } - async addChattingLog(chattingLog: any, chatDocumentId: string, userDocumentId: string) { + async addChattingLog(chattingLog: IChattingLog, chatDocumentId: string, userDocumentId: string) { const chat = await Chats.findOneAndUpdate({ _id: chatDocumentId }, { $push: { chattingLog }, $set: { recentActive: chattingLog.date, lastMsg: chattingLog.message }, @@ -79,7 +100,7 @@ class ChatService { } async getUnReadMsgCount(userDocumentId: string) { - const { chatRooms } :any = await Users.findOne({ _id: userDocumentId }, ['chatRooms']); + const { chatRooms } : any = await Users.findOne({ _id: userDocumentId }, ['chatRooms']); let unReadMsgCount = 0; await Promise.all(chatRooms.map(async (chatDocumentId: string) => { diff --git a/server/src/sockets/chat.ts b/server/src/sockets/chat.ts index 294084c4..ac1ec69f 100644 --- a/server/src/sockets/chat.ts +++ b/server/src/sockets/chat.ts @@ -2,21 +2,52 @@ /* eslint-disable array-callback-return */ /* eslint-disable prefer-destructuring */ import { Socket, Namespace } from 'socket.io'; -import Chats from '@models/chats'; + +import Chats, { IUnReadMsg } from '@models/chats'; +import chatSocketMessage from '@constants/socket-message/chat'; import chatService from '@services/chat-service'; +interface IAlertMsgHandlerProps { + participants: Array, + chatDocumentId: string, +} + +interface IsendMsgHandler { + userDocumentId: string, + userName: string, + profileUrl: string, + message: string, + chatDocumentId: string, + date: string, + key: string, +} + +interface IUserInfo { + userDocumentId: string, + userName: string, + profileUrl: string, +} + +interface IinviteHandlerProps { + participants: Array, + message: string, + userInfo: IUserInfo, + roomDocumentId: string, + date: string, + key: string, +} + export default function chatEventHandler(socket : Socket, namespace: Namespace) { const chatRoomJoinHandler = (chatDocumentId: string) => socket.join(chatDocumentId); const chatViewJoinHandler = (userDocumentId: string) => socket.join(userDocumentId); - const sendMsgHandler = async (payload: any) => { - const { - userDocumentId, userName, profileUrl, message, chatDocumentId, date, key, - } = payload; + const sendMsgHandler = async ({ + userDocumentId, userName, profileUrl, message, chatDocumentId, date, key, + }: IsendMsgHandler) => { const chattingLog = { date: new Date(), userDocumentId, message }; await chatService.addChattingLog(chattingLog, chatDocumentId, userDocumentId); - socket.to(chatDocumentId).emit('chat:sendMsg', { + socket.to(chatDocumentId).emit(chatSocketMessage.sendMsg, { userDocumentId, userName, profileUrl, message, date, key, }); }; @@ -25,34 +56,31 @@ export default function chatEventHandler(socket : Socket, namespace: Namespace) socket.leave(chatDocumentId); }; - const alertMsgHandler = (payload: any) => { - const { participants, chatDocumentId } = payload; + const alertMsgHandler = ({ participants, chatDocumentId }: IAlertMsgHandlerProps) => { participants.forEach(async (userDocumentId: string) => { - const chatInfo : any = await Chats.findOne({ _id: chatDocumentId }, ['lastMsg', 'unReadMsg', 'recentActive']); - const count = chatInfo.unReadMsg[chatInfo.unReadMsg.findIndex((user: any) => user.userDocumentId === userDocumentId)].count; - socket.to(userDocumentId).emit('chat:alertMsg', { - chatDocumentId, lastMsg: chatInfo.lastMsg, recentActive: chatInfo.recentActive, unCheckedMsg: count + 1, + const chatInfo = await Chats.findOne({ _id: chatDocumentId }, ['lastMsg', 'unReadMsg', 'recentActive']); + const count = chatInfo!.unReadMsg[chatInfo!.unReadMsg.findIndex((user: IUnReadMsg) => user.userDocumentId === userDocumentId)].count; + socket.to(userDocumentId).emit(chatSocketMessage.alertMsg, { + chatDocumentId, lastMsg: chatInfo!.lastMsg, recentActive: chatInfo!.recentActive, unCheckedMsg: count + 1, }); }); }; - const makeChatHandler = ({ participantsInfo, chatDocumentId }: any) => { - participantsInfo.map((user: any) => { - const newParticipants = participantsInfo.filter((participant: any) => participant.userDocumentId !== user.userDocumentId); - socket.to(user.userDocumentId).emit('chat:makeChat', { chatDocumentId, participantsInfo: newParticipants }); + const makeChatHandler = ({ participantsInfo, chatDocumentId }: { participantsInfo: Array, chatDocumentId: string }) => { + participantsInfo.map((user: IUserInfo) => { + const newParticipants = participantsInfo.filter((participant: IUserInfo) => participant.userDocumentId !== user.userDocumentId); + socket.to(user.userDocumentId).emit(chatSocketMessage.makeChat, { chatDocumentId, participantsInfo: newParticipants }); }); }; const updateCountHandler = (participants: Array, chatDocumentId: string) => { - participants.forEach((userDocumentId: string) => socket.to(userDocumentId).emit('chat:updateCount', chatDocumentId)); + participants.forEach((userDocumentId: string) => socket.to(userDocumentId).emit(chatSocketMessage.updateCount, chatDocumentId)); }; - const inviteRoomHandler = (payload: any) => { - const { - // eslint-disable-next-line no-unused-vars - participants, message, roomDocumentId, userInfo, date, key, - } = payload; - participants.forEach(async (participant: any) => { + const inviteRoomHandler = ({ + participants, message, roomDocumentId, userInfo, date, key, + }: IinviteHandlerProps) => { + participants.forEach(async (participant: IUserInfo) => { const { chatRoom, chatDocumentId, isNew } = await chatService.makeChatRoom([participant.userDocumentId, userInfo.userDocumentId].sort()); await chatService.addChattingLog({ message, @@ -61,39 +89,39 @@ export default function chatEventHandler(socket : Socket, namespace: Namespace) linkTo: roomDocumentId, }, chatDocumentId, userInfo.userDocumentId); - namespace.to(chatDocumentId.toString()).emit('chat:sendMsg', { + namespace.to(chatDocumentId.toString()).emit(chatSocketMessage.sendMsg, { userDocumentId: userInfo.userDocumentId, userName: userInfo.userName, profileUrl: userInfo.profileUrl, message, date, linkTo: roomDocumentId, key, }); if (isNew) { - socket.to(participant.userDocumentId).emit('chat:makeChat', { chatDocumentId, participantsInfo: [userInfo] }); - namespace.to(userInfo.userDocumentId).emit('chat:makeChat', { chatDocumentId, participantsInfo: [participant] }); + socket.to(participant.userDocumentId).emit(chatSocketMessage.makeChat, { chatDocumentId, participantsInfo: [userInfo] }); + namespace.to(userInfo.userDocumentId).emit(chatSocketMessage.makeChat, { chatDocumentId, participantsInfo: [participant] }); } - socket.to(participant.userDocumentId).emit('chat:alertMsg', { + socket.to(participant.userDocumentId).emit(chatSocketMessage.alertMsg, { chatDocumentId, lastMsg: message, recentActive: new Date(), - unCheckedMsg: chatRoom!.unReadMsg[chatRoom!.unReadMsg.findIndex((user: any) => user.userDocumentId === participant.userDocumentId)].count + 1, + unCheckedMsg: chatRoom!.unReadMsg[chatRoom!.unReadMsg.findIndex((user: IUnReadMsg) => user.userDocumentId === participant.userDocumentId)].count + 1, }); - namespace.to(userInfo.userDocumentId).emit('chat:alertMsg', { + namespace.to(userInfo.userDocumentId).emit(chatSocketMessage.alertMsg, { chatDocumentId, lastMsg: message, recentActive: new Date(), unCheckedMsg: 0, }); await chatService.setUnCheckedMsg(chatDocumentId, userInfo.userDocumentId); - socket.to(participant.userDocumentId).emit('chat:updateCount', chatDocumentId); + socket.to(participant.userDocumentId).emit(chatSocketMessage.updateCount, chatDocumentId); }); }; - socket.on('chat:roomJoin', chatRoomJoinHandler); - socket.on('chat:viewJoin', chatViewJoinHandler); - socket.on('chat:sendMsg', sendMsgHandler); - socket.on('chat:leave', chatLeaveHandler); - socket.on('chat:alertMsg', alertMsgHandler); - socket.on('chat:makeChat', makeChatHandler); - socket.on('chat:inviteRoom', inviteRoomHandler); - socket.on('chat:updateCount', updateCountHandler); + socket.on(chatSocketMessage.roomJoin, chatRoomJoinHandler); + socket.on(chatSocketMessage.viewJoin, chatViewJoinHandler); + socket.on(chatSocketMessage.sendMsg, sendMsgHandler); + socket.on(chatSocketMessage.leave, chatLeaveHandler); + socket.on(chatSocketMessage.alertMsg, alertMsgHandler); + socket.on(chatSocketMessage.makeChat, makeChatHandler); + socket.on(chatSocketMessage.inviteRoom, inviteRoomHandler); + socket.on(chatSocketMessage.updateCount, updateCountHandler); } diff --git a/server/src/sockets/room.ts b/server/src/sockets/room.ts index 38818fca..d337cee4 100644 --- a/server/src/sockets/room.ts +++ b/server/src/sockets/room.ts @@ -1,11 +1,18 @@ import { Namespace, Socket } from 'socket.io'; +import roomSocketMessage from '@constants/socket-message/room'; import RoomService from '@services/rooms-service'; interface IUsers { [id: string]: any, } +interface IHandleMic { + roomDocumentId: string, + userDocumentId: string, + isMicOn: boolean, +} + const users: IUsers = {}; export default function RoomHandler(socket : Socket, namespace : Namespace) { @@ -22,7 +29,7 @@ export default function RoomHandler(socket : Socket, namespace : Namespace) { const participantsInfo = room?.participants .filter((participant) => participant.userDocumentId !== userDocumentId); - namespace.to(socket.id).emit('room:join', participantsInfo); + namespace.to(socket.id).emit(roomSocketMessage.join, participantsInfo); }; const handleRoomLeave = async () => { @@ -31,37 +38,37 @@ export default function RoomHandler(socket : Socket, namespace : Namespace) { delete users[socket.id]; await RoomService.deleteParticipant(roomDocumentId, userDocumentId); - socket.to(roomDocumentId).emit('room:leave', socket.id); + socket.to(roomDocumentId).emit(roomSocketMessage.leave, socket.id); }; // eslint-disable-next-line no-undef const handleRoomOffer = (offer: RTCSessionDescriptionInit, receiveId: string) => { const { userDocumentId, isAnonymous } = users[socket.id]; - socket.to(receiveId).emit('room:offer', offer, userDocumentId, socket.id, isAnonymous); + socket.to(receiveId).emit(roomSocketMessage.offer, offer, userDocumentId, socket.id, isAnonymous); }; // eslint-disable-next-line no-undef const handleRoomAnswer = (answer: RTCSessionDescriptionInit, receiveId: string) => { - socket.to(receiveId).emit('room:answer', answer, socket.id); + socket.to(receiveId).emit(roomSocketMessage.answer, answer, socket.id); }; // eslint-disable-next-line no-undef const handleRoomIce = (candidate: RTCIceCandidateInit, receiveId: string) => { - socket.to(receiveId).emit('room:ice', { candidate, candidateSendId: socket.id }); + socket.to(receiveId).emit(roomSocketMessage.ice, { candidate, candidateSendId: socket.id }); }; - const handleMic = async (payload: any) => { + const handleMic = async (payload: IHandleMic) => { const { roomDocumentId, userDocumentId, isMicOn } = payload; await RoomService.setMic(roomDocumentId, userDocumentId, isMicOn); const userData = { userDocumentId, isMicOn, socketId: socket.id }; - socket.to(roomDocumentId).emit('room:mic', { userData }); + socket.to(roomDocumentId).emit(roomSocketMessage.mic, { userData }); }; - socket.on('room:join', handleRoomJoin); - socket.on('room:offer', handleRoomOffer); - socket.on('room:answer', handleRoomAnswer); - socket.on('room:ice', handleRoomIce); + socket.on(roomSocketMessage.join, handleRoomJoin); + socket.on(roomSocketMessage.offer, handleRoomOffer); + socket.on(roomSocketMessage.answer, handleRoomAnswer); + socket.on(roomSocketMessage.ice, handleRoomIce); socket.on('disconnect', handleRoomLeave); - socket.on('room:mic', handleMic); + socket.on(roomSocketMessage.mic, handleMic); } diff --git a/server/src/sockets/user.ts b/server/src/sockets/user.ts index 02e7ff0c..f8e434be 100644 --- a/server/src/sockets/user.ts +++ b/server/src/sockets/user.ts @@ -1,5 +1,7 @@ import { Namespace, Socket } from 'socket.io'; +import userSocketMessage from '@constants/socket-message/user'; + interface IJoinPayload { userDocumentId: string, userName: string, @@ -32,12 +34,12 @@ export default function userHandler(socket : Socket, namespace : Namespace) { return acc; }, []); - namespace.emit('user:newActiveUser', { + namespace.emit(userSocketMessage.newActiveUser, { userDocumentId, userName, userId, profileUrl, isActive: true, }); // 기존 접속자들에게 새로운 유저 데이터 보내주기 - namespace.to(socket.id).emit('user:firstFollowingList', activeFollowingList); + namespace.to(socket.id).emit(userSocketMessage.firstFollowingList, activeFollowingList); // 신규 접속자에게 현재 접속중인 팔로우 리스트 전달 }; @@ -46,7 +48,7 @@ export default function userHandler(socket : Socket, namespace : Namespace) { socketUser.delete(socket.id); activeUser.delete(userDocumentId); - namespace.emit('user:newLeaveUser', userDocumentId); + namespace.emit(userSocketMessage.newLeaveUser, userDocumentId); }; const handleUserHands = (targetDocumentId: string) => { @@ -54,13 +56,13 @@ export default function userHandler(socket : Socket, namespace : Namespace) { const userDocumentId = socketUser.get(socket.id); const userInfo = (activeUser.get(userDocumentId)).info; const targetSocketId = (activeUser.get(targetDocumentId)).socketId; - namespace.to(targetSocketId).emit('user:hands', { from: { ...userInfo }, to: targetDocumentId }); + namespace.to(targetSocketId).emit(userSocketMessage.hands, { from: { ...userInfo }, to: targetDocumentId }); } catch (e) { console.error(e); } }; - socket.on('user:join', handleUserJoin); - socket.on('user:hands', handleUserHands); + socket.on(userSocketMessage.join, handleUserJoin); + socket.on(userSocketMessage.hands, handleUserHands); socket.on('disconnect', handleUserLeave); } diff --git a/server/tsconfig.json b/server/tsconfig.json index b7305a14..f1c22e1a 100644 --- a/server/tsconfig.json +++ b/server/tsconfig.json @@ -15,7 +15,8 @@ "@subscribers/*": [ "src/subscribers/*" ], "@types/*": [ "src/types/*" ], "@utils/*": [ "src/utils/*" ], - "@sockets/*": [ "src/sockets/*" ] + "@sockets/*": [ "src/sockets/*" ], + "@constants/*": [ "src/constants/*" ], }, "target": "es6", // "allowJs": true,