From 25f64a0de3c2e1779430dc31b1fffa266d3642cc Mon Sep 17 00:00:00 2001 From: munee <121735319+alaneelee@users.noreply.github.com> Date: Wed, 27 Dec 2023 01:56:38 +0900 Subject: [PATCH 1/7] =?UTF-8?q?=EC=A4=91=EB=B3=B5=EC=9C=BC=EB=A1=9C=20?= =?UTF-8?q?=EA=B5=AC=EB=8F=85=EB=90=98=EB=8A=94=20=EB=AC=B8=EC=A0=9C=3F=20?= =?UTF-8?q?=EB=B0=9C=EC=83=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/Chat.js | 79 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) create mode 100644 src/components/Chat.js diff --git a/src/components/Chat.js b/src/components/Chat.js new file mode 100644 index 0000000..0ec540f --- /dev/null +++ b/src/components/Chat.js @@ -0,0 +1,79 @@ +import React, { useEffect, useState } from 'react'; + +const ChatComponent = () => { + const [messages, setMessages] = useState([]); + const [inputMessage, setInputMessage] = useState(''); + const [socket, setSocket] = useState(null); + + useEffect(() => { + const roomId = 'abcde'; + const newSocket = new WebSocket(`ws://localhost:8082/chat/${roomId}`); + setSocket(newSocket); + + newSocket.onopen = () => { + console.log('웹소켓 연결됨'); + }; + + newSocket.onmessage = (event) => { + console.log(event.data); + const receiveData = event.data.split(':'); + const from = receiveData[0]; + const message = receiveData.slice(1).join(':').trim(); + setMessages((prevMessages) => [...prevMessages, { from, message }]); + }; + + newSocket.onclose = () => { + console.log('웹소켓 연결 종료'); + // 연결 종료 시 재연결 시도 + setTimeout(() => { + const reconnectSocket = new WebSocket(`ws://localhost:8082/chat/${roomId}`); + reconnectSocket.onopen = () => { + console.log('웹소켓 재연결됨'); + setSocket(reconnectSocket); + }; + + reconnectSocket.onmessage = (event) => { + console.log(event.data); + const receiveData = event.data.split(':'); + const from = receiveData[0]; + const message = receiveData.slice(1).join(':').trim(); + setMessages((prevMessages) => [...prevMessages, { from, message }]); + }; + }, 6000); // 6초 후 재연결 시도 + }; + + return () => { + newSocket.close(); + }; + }, []); + + const sendMessage = () => { + if (inputMessage.trim() === '') return; + + socket.send(inputMessage); + setInputMessage(''); + }; + + return ( +
+
+ {messages.map((message, index) => ( +
+ {message.from}: + {message.message} +
+ ))} +
+
+ setInputMessage(e.target.value)} + /> + +
+
+ ); +}; + +export default ChatComponent; \ No newline at end of file From ca646126fc3513577d101a18bf8bfee69ff04186 Mon Sep 17 00:00:00 2001 From: BYEONGRYEOL Date: Wed, 27 Dec 2023 20:31:12 +0900 Subject: [PATCH 2/7] =?UTF-8?q?=EC=B1=84=ED=8C=85=EC=84=9C=EB=B2=84?= =?UTF-8?q?=EC=9A=A9=20=ED=86=A0=ED=81=B0=20=EB=B0=9C=EA=B8=89=20=ED=85=8C?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=EC=A4=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/Chat.js | 55 +++++++++++++++++-------- src/components/header.js | 36 ++++++++-------- src/modal/LoginModal.js | 54 ++++++++++++------------ src/modal/SignupModal.js | 84 +++++++++++++++++++------------------- src/pages/ChannelDetail.js | 30 ++++++++------ src/pages/Home.js | 12 +++--- src/sbltest/Channel.js | 10 ++--- 7 files changed, 152 insertions(+), 129 deletions(-) diff --git a/src/components/Chat.js b/src/components/Chat.js index 0ec540f..82fdfc0 100644 --- a/src/components/Chat.js +++ b/src/components/Chat.js @@ -1,42 +1,61 @@ -import React, { useEffect, useState } from 'react'; +import React, { useEffect, useState } from "react"; +import axios from "axios"; -const ChatComponent = () => { +const ChatComponent = (chatToken, chattingRoomId) => { const [messages, setMessages] = useState([]); - const [inputMessage, setInputMessage] = useState(''); + const [inputMessage, setInputMessage] = useState(""); const [socket, setSocket] = useState(null); + const tokenString = chatToken.chatToken; + const chattingRoomIdString = chattingRoomId.chattingRoomId; + const accessToken = localStorage.getItem("accessToken"); + useEffect(() => { - const roomId = 'abcde'; - const newSocket = new WebSocket(`ws://localhost:8082/chat/${roomId}`); + const newSocket = new WebSocket( + `ws://localhost:8082/chat/${chattingRoomIdString}/${tokenString}` + ); setSocket(newSocket); newSocket.onopen = () => { - console.log('웹소켓 연결됨'); + console.log("웹소켓 연결됨"); }; newSocket.onmessage = (event) => { console.log(event.data); - const receiveData = event.data.split(':'); + const receiveData = event.data.split(":"); const from = receiveData[0]; - const message = receiveData.slice(1).join(':').trim(); + const message = receiveData.slice(1).join(":").trim(); setMessages((prevMessages) => [...prevMessages, { from, message }]); }; newSocket.onclose = () => { - console.log('웹소켓 연결 종료'); + console.log("웹소켓 연결 종료"); // 연결 종료 시 재연결 시도 - setTimeout(() => { - const reconnectSocket = new WebSocket(`ws://localhost:8082/chat/${roomId}`); + setTimeout(async () => { + const response = await axios.post( + "http://localhost:8081/api/auth/chat", + { + headers: { + Authorization: accessToken, + }, + } + ); + + // 응답에서 토큰 추출 + const tokenString = response.data.chatToken; + const reconnectSocket = new WebSocket( + `ws://localhost:8082/chat/${chattingRoomIdString}/${tokenString}` + ); reconnectSocket.onopen = () => { - console.log('웹소켓 재연결됨'); + console.log("웹소켓 재연결됨"); setSocket(reconnectSocket); }; reconnectSocket.onmessage = (event) => { console.log(event.data); - const receiveData = event.data.split(':'); + const receiveData = event.data.split(":"); const from = receiveData[0]; - const message = receiveData.slice(1).join(':').trim(); + const message = receiveData.slice(1).join(":").trim(); setMessages((prevMessages) => [...prevMessages, { from, message }]); }; }, 6000); // 6초 후 재연결 시도 @@ -48,10 +67,10 @@ const ChatComponent = () => { }, []); const sendMessage = () => { - if (inputMessage.trim() === '') return; + if (inputMessage.trim() === "") return; socket.send(inputMessage); - setInputMessage(''); + setInputMessage(""); }; return ( @@ -66,7 +85,7 @@ const ChatComponent = () => {
setInputMessage(e.target.value)} /> @@ -76,4 +95,4 @@ const ChatComponent = () => { ); }; -export default ChatComponent; \ No newline at end of file +export default ChatComponent; diff --git a/src/components/header.js b/src/components/header.js index 55df0e2..166d261 100644 --- a/src/components/header.js +++ b/src/components/header.js @@ -1,9 +1,9 @@ -import React, { useState } from 'react'; -import styled from 'styled-components'; -import { Link } from 'react-router-dom'; -import { ReactComponent as LemonSVG } from '../images/lemon.svg'; -import SignupModal from '../modal/SignupModal'; -import LoginModal from '../modal/LoginModal'; +import React, { useState } from "react"; +import styled from "styled-components"; +import { Link } from "react-router-dom"; +import { ReactComponent as LemonSVG } from "../images/lemon.svg"; +import SignupModal from "../modal/SignupModal"; +import LoginModal from "../modal/LoginModal"; const HeaderContainer = styled.header` display: flex; @@ -50,7 +50,7 @@ const UserOptions = styled.div` text-decoration: none; color: #555; padding-right: 25px; - font-family: 'Reenie Beanie', cursive; + font-family: "Reenie Beanie", cursive; } a:hover { @@ -65,13 +65,13 @@ const HeaderText = styled.span` text-decoration: none; color: #555; padding-right: 25px; - font-family: 'Reenie Beanie', cursive; + font-family: "Reenie Beanie", cursive; `; const Header = () => { const [isSignupModalOpen, setIsSignupModalOpen] = useState(false); const [isLoginModalOpen, setIsLoginModalOpen] = useState(false); - const accessToken = localStorage.getItem('accessToken'); + const accessToken = localStorage.getItem("accessToken"); const openSignupModal = () => { setIsSignupModalOpen(true); @@ -91,30 +91,30 @@ const Header = () => { const handleLogout = async () => { try { - const response = await fetch('https://api.lemonair.me:8081/api/logout', { - method: 'POST', + const response = await fetch("http://localhost:8081/api/logout", { + method: "POST", headers: { Authorization: accessToken, }, }); if (response.ok) { - localStorage.removeItem('accessToken'); - localStorage.removeItem('refreshToken'); - alert('로그아웃 되었습니다.'); + localStorage.removeItem("accessToken"); + localStorage.removeItem("refreshToken"); + alert("로그아웃 되었습니다."); window.location.reload(); } else { - console.log('로그아웃에 실패하였습니다.'); + console.log("로그아웃에 실패하였습니다."); } } catch (error) { - console.error('로그아웃 중 오류 발생:', error); + console.error("로그아웃 중 오류 발생:", error); } }; return ( - - 로고 + + 로고 diff --git a/src/modal/LoginModal.js b/src/modal/LoginModal.js index e300560..ad7b572 100644 --- a/src/modal/LoginModal.js +++ b/src/modal/LoginModal.js @@ -1,6 +1,6 @@ -import React, { useState } from 'react'; -import styled from 'styled-components'; -import useInput from '../hooks/useInput'; +import React, { useState } from "react"; +import styled from "styled-components"; +import useInput from "../hooks/useInput"; const ModalBackground = styled.div` position: fixed; @@ -34,7 +34,7 @@ const Title = styled.h2` font-size: 2rem; color: #555; margin-bottom: 15px; - font-family: 'Reenie Beanie', cursive; + font-family: "Reenie Beanie", cursive; `; const InputField = styled.input` @@ -46,7 +46,7 @@ const InputField = styled.input` font-size: 13px; padding-left: 1.2%; line-height: 16px; - font-family: 'Roboto', sans-serif; + font-family: "Roboto", sans-serif; margin-bottom: 1vh; `; @@ -62,7 +62,7 @@ const SubmitButton = styled.button` color: #4c3c00; margin: 0 auto; margin-top: 6%; - font-family: 'Gamja Flower', sans-serif; + font-family: "Gamja Flower", sans-serif; &:hover { background-color: #ffea00; @@ -77,13 +77,13 @@ const Label = styled.label` color: #333; text-align: left; padding-left: 15%; - font-family: 'Gamja Flower', sans-serif; + font-family: "Gamja Flower", sans-serif; `; const LoginModal = ({ closeModal }) => { - const [loginId, onChangeLoginId] = useInput(''); - const [password, onChangePassword] = useInput(''); - const [error, setError] = useState(''); + const [loginId, onChangeLoginId] = useInput(""); + const [password, onChangePassword] = useInput(""); + const [error, setError] = useState(""); const handleOutsideClick = (e) => { if (e.target === e.currentTarget) { @@ -100,24 +100,24 @@ const LoginModal = ({ closeModal }) => { }; try { - const response = await fetch('https://api.lemonair.me:8081/api/login', { - method: 'POST', + const response = await fetch("http://localhost:8081/api/login", { + method: "POST", headers: { - 'Content-Type': 'application/json', + "Content-Type": "application/json", }, body: JSON.stringify(loginData), }); if (response.ok) { const data = await response.json(); - localStorage.setItem('accessToken', data.accessToken); - localStorage.setItem('refreshToken', data.refreshToken); + localStorage.setItem("accessToken", data.accessToken); + localStorage.setItem("refreshToken", data.refreshToken); closeModal(); } else { - setError('아이디 또는 비밀번호가 올바르지 않습니다.'); + setError("아이디 또는 비밀번호가 올바르지 않습니다."); } } catch (error) { - setError('오류가 발생했습니다.'); + setError("오류가 발생했습니다."); } }; return ( @@ -125,24 +125,24 @@ const LoginModal = ({ closeModal }) => { Login
- + - + - {error &&

{error}

} - 로그인 + {error &&

{error}

} + 로그인
diff --git a/src/modal/SignupModal.js b/src/modal/SignupModal.js index cc62318..ecb84cc 100644 --- a/src/modal/SignupModal.js +++ b/src/modal/SignupModal.js @@ -1,6 +1,6 @@ -import React, { useState } from 'react'; -import styled from 'styled-components'; -import useInput from '../hooks/useInput'; +import React, { useState } from "react"; +import styled from "styled-components"; +import useInput from "../hooks/useInput"; const ModalBackground = styled.div` position: fixed; @@ -33,7 +33,7 @@ const Title = styled.h2` font-size: 2rem; color: #555; margin-bottom: 15px; - font-family: 'Reenie Beanie', cursive; + font-family: "Reenie Beanie", cursive; `; const InputField = styled.input` @@ -45,7 +45,7 @@ const InputField = styled.input` font-size: 13px; padding-left: 1.2%; line-height: 16px; - font-family: 'Roboto', sans-serif; + font-family: "Roboto", sans-serif; `; const SubmitButton = styled.button` @@ -59,7 +59,7 @@ const SubmitButton = styled.button` background-color: #f8de7e; color: #4c3c00; margin: 0 auto; - font-family: 'Gamja Flower', sans-serif; + font-family: "Gamja Flower", sans-serif; &:hover { background-color: #ffea00; @@ -74,16 +74,16 @@ const Label = styled.label` color: #333; text-align: left; padding-left: 15%; - font-family: 'Gamja Flower', sans-serif; + font-family: "Gamja Flower", sans-serif; `; const SignupModal = ({ closeModal }) => { - const [loginId, onChangeLoginId] = useInput(''); - const [email, onChangeEmail] = useInput(''); - const [password, onChangePassword] = useInput(''); - const [password2, onChangePassword2] = useInput(''); - const [nickname, onChangeNickname] = useInput(''); - const [error, setError] = useState(''); + const [loginId, onChangeLoginId] = useInput(""); + const [email, onChangeEmail] = useInput(""); + const [password, onChangePassword] = useInput(""); + const [password2, onChangePassword2] = useInput(""); + const [nickname, onChangeNickname] = useInput(""); + const [error, setError] = useState(""); const handleOutsideClick = (e) => { if (e.target === e.currentTarget) { @@ -95,12 +95,12 @@ const SignupModal = ({ closeModal }) => { e.preventDefault(); if (!loginId || !email || !password || !password2 || !nickname) { - setError('모든 필드를 입력해주세요.'); + setError("모든 필드를 입력해주세요."); return; } if (password !== password2) { - setError('비밀번호가 일치하지 않습니다.'); + setError("비밀번호가 일치하지 않습니다."); return; } @@ -113,10 +113,10 @@ const SignupModal = ({ closeModal }) => { }; try { - const response = await fetch('https://api.lemonair.me:8081/api/signup', { - method: 'POST', + const response = await fetch("http://localhost:8081/api/signup", { + method: "POST", headers: { - 'Content-Type': 'application/json', + "Content-Type": "application/json", }, body: JSON.stringify(signupData), }); @@ -130,11 +130,11 @@ stream key : ${data.streamKey}` ); closeModal(); } else { - setError('회원가입에 실패했습니다.'); + setError("회원가입에 실패했습니다."); // 서버 에러 정의되면 서버에러로 바꿔야 함 } } catch (error) { - setError('오류가 발생했습니다.'); + setError("오류가 발생했습니다."); // 서버 에러 정의되면 서버에러로 바꿔야 함 } }; @@ -144,48 +144,48 @@ stream key : ${data.streamKey}` Signup
- + - + - + - + - + - {error &&

{error}

} - 가입하기 + {error &&

{error}

} + 가입하기
diff --git a/src/pages/ChannelDetail.js b/src/pages/ChannelDetail.js index 73ee7e5..4621262 100644 --- a/src/pages/ChannelDetail.js +++ b/src/pages/ChannelDetail.js @@ -1,8 +1,9 @@ -import React, { useEffect, useState } from 'react'; -import { useParams } from 'react-router-dom'; -import Header from '../components/header'; -import VideoPlayer from '../components/ReactPlayer'; -import styled from 'styled-components'; +import React, { useEffect, useState } from "react"; +import { useParams } from "react-router-dom"; +import Header from "../components/header"; +import VideoPlayer from "../components/ReactPlayer"; +import styled from "styled-components"; +import Chat from "../components/Chat"; const StreamingContainer = styled.div` width: 100%; @@ -19,7 +20,7 @@ const StreamingTitle = styled.p` margin-top: 15px; margin-left: 15px; font-size: 1.5rem; - font-family: 'Gamja Flower', sans-serif; + font-family: "Gamja Flower", sans-serif; `; const ChatWrapper = styled.div` @@ -35,17 +36,17 @@ const ChannelDetail = () => { const fetchData = async () => { try { const response = await fetch( - `https://api.lemonair.me:8081/api/channels/${id}` + `http://localhost:8081/api/channels/${id}` ); if (!response.ok) { - throw new Error('Network response was not ok.'); + throw new Error("Network response was not ok."); } const data = await response.json(); setChannelData(data); - console.log('title:', data.title); - console.log('url:', data.hlsUrl); + console.log("title:", data.title); + console.log("url:", data.hlsUrl); } catch (error) { - console.error('데이터를 불러오는 중 오류가 발생했습니다:', error); + console.error("데이터를 불러오는 중 오류가 발생했습니다:", error); } }; @@ -57,7 +58,12 @@ const ChannelDetail = () => { {channelData ? : null} - {channelData ? 채팅 공간입니다. : null} + {channelData ? ( + + ) : null} {channelData ? ( diff --git a/src/pages/Home.js b/src/pages/Home.js index 88f51dd..e6ccf37 100644 --- a/src/pages/Home.js +++ b/src/pages/Home.js @@ -1,7 +1,7 @@ -import React, { useEffect, useState } from 'react'; -import Header from '../components/header'; -import styled from 'styled-components'; -import CardExample from '../components/Card'; +import React, { useEffect, useState } from "react"; +import Header from "../components/header"; +import styled from "styled-components"; +import CardExample from "../components/Card"; const ArticleContainer = styled.div` height: 20vh; @@ -13,14 +13,14 @@ const Home = () => { const [data, setData] = useState([]); useEffect(() => { - fetch('https://api.lemonair.me:8081/api/channels') + fetch("http://localhost:8081/api/channels") .then((response) => response.json()) .then((data) => { setData(data); console.log(data); }) .catch((error) => { - console.error('Error fetching data:', error); + console.error("Error fetching data:", error); }); }, []); diff --git a/src/sbltest/Channel.js b/src/sbltest/Channel.js index 895e1a4..a930c09 100644 --- a/src/sbltest/Channel.js +++ b/src/sbltest/Channel.js @@ -1,5 +1,5 @@ -import React, { useEffect, useState } from 'react'; -import axios from 'axios'; +import React, { useEffect, useState } from "react"; +import axios from "axios"; const ChannelInfo = () => { const [channelData, setChannelData] = useState([]); @@ -7,12 +7,10 @@ const ChannelInfo = () => { useEffect(() => { const fetchData = async () => { try { - const response = await axios.get( - 'https://api.lemonair.me:8081/api/channels' - ); + const response = await axios.get("http://localhost:8081/api/channels"); setChannelData(response.data); } catch (error) { - console.error('Error fetching data:', error); + console.error("Error fetching data:", error); } }; From cbd9b25f0e98ad5824f39513496a2473fc0ef77f Mon Sep 17 00:00:00 2001 From: BYEONGRYEOL Date: Thu, 28 Dec 2023 00:20:09 +0900 Subject: [PATCH 3/7] =?UTF-8?q?FE=20=EC=86=8C=EC=BC=93=20=EC=97=B0?= =?UTF-8?q?=EA=B2=B0=20=ED=95=B4=EC=A0=9C=20=EB=AC=B8=EC=A0=9C=20=ED=95=B4?= =?UTF-8?q?=EA=B2=B0=EC=A4=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/Chat.js | 79 +++++++++++++++++++------------------- src/pages/ChannelDetail.js | 1 + 2 files changed, 40 insertions(+), 40 deletions(-) diff --git a/src/components/Chat.js b/src/components/Chat.js index 82fdfc0..0a79309 100644 --- a/src/components/Chat.js +++ b/src/components/Chat.js @@ -1,21 +1,21 @@ import React, { useEffect, useState } from "react"; -import axios from "axios"; +import { useRef } from "react"; -const ChatComponent = (chatToken, chattingRoomId) => { +const ChatComponent = ({ chatToken, chattingRoomId }) => { const [messages, setMessages] = useState([]); const [inputMessage, setInputMessage] = useState(""); const [socket, setSocket] = useState(null); - - const tokenString = chatToken.chatToken; - const chattingRoomIdString = chattingRoomId.chattingRoomId; - const accessToken = localStorage.getItem("accessToken"); + const tokenString = chatToken; useEffect(() => { + console.log("chatToken", chatToken); + console.log("chattingRommId", chattingRoomId); + const chattingRoomIdString = chattingRoomId; + const accessToken = localStorage.getItem("accessToken"); const newSocket = new WebSocket( `ws://localhost:8082/chat/${chattingRoomIdString}/${tokenString}` ); setSocket(newSocket); - newSocket.onopen = () => { console.log("웹소켓 연결됨"); }; @@ -28,42 +28,41 @@ const ChatComponent = (chatToken, chattingRoomId) => { setMessages((prevMessages) => [...prevMessages, { from, message }]); }; - newSocket.onclose = () => { - console.log("웹소켓 연결 종료"); - // 연결 종료 시 재연결 시도 - setTimeout(async () => { - const response = await axios.post( - "http://localhost:8081/api/auth/chat", - { - headers: { - Authorization: accessToken, - }, - } - ); + // newSocket.onclose = () => { + // console.log("웹소켓 연결 종료"); + // // 연결 종료 시 재연결 시도 + // setTimeout(async () => { + // console.log("accessToken", accessToken); + // const response = await fetch("http://localhost:8081/api/auth/chat", { + // method: "POST", + // headers: { + // Authorization: accessToken, + // }, + // }); - // 응답에서 토큰 추출 - const tokenString = response.data.chatToken; - const reconnectSocket = new WebSocket( - `ws://localhost:8082/chat/${chattingRoomIdString}/${tokenString}` - ); - reconnectSocket.onopen = () => { - console.log("웹소켓 재연결됨"); - setSocket(reconnectSocket); - }; + // // 응답에서 토큰 추출 + // const tokenString = response.data.chatToken; + // const reconnectSocket = new WebSocket( + // `ws://localhost:8082/chat/${chattingRoomIdString}/${tokenString}` + // ); + // reconnectSocket.onopen = () => { + // console.log("웹소켓 재연결됨"); + // setSocket(reconnectSocket); + // }; - reconnectSocket.onmessage = (event) => { - console.log(event.data); - const receiveData = event.data.split(":"); - const from = receiveData[0]; - const message = receiveData.slice(1).join(":").trim(); - setMessages((prevMessages) => [...prevMessages, { from, message }]); - }; - }, 6000); // 6초 후 재연결 시도 - }; + // reconnectSocket.onmessage = (event) => { + // console.log(event.data); + // const receiveData = event.data.split(":"); + // const from = receiveData[0]; + // const message = receiveData.slice(1).join(":").trim(); + // setMessages((prevMessages) => [...prevMessages, { from, message }]); + // }; + // }, 6000); // 6초 후 재연결 시도 + // }; - return () => { - newSocket.close(); - }; + // return () => { + // newSocket.close(); + // }; }, []); const sendMessage = () => { diff --git a/src/pages/ChannelDetail.js b/src/pages/ChannelDetail.js index 4621262..3c1896f 100644 --- a/src/pages/ChannelDetail.js +++ b/src/pages/ChannelDetail.js @@ -45,6 +45,7 @@ const ChannelDetail = () => { setChannelData(data); console.log("title:", data.title); console.log("url:", data.hlsUrl); + console.log("roomid:", data.chattingRoomId); } catch (error) { console.error("데이터를 불러오는 중 오류가 발생했습니다:", error); } From 109d96a0f4b1e976ec7aa85d6d6460264fd89437 Mon Sep 17 00:00:00 2001 From: BYEONGRYEOL Date: Thu, 28 Dec 2023 11:23:49 +0900 Subject: [PATCH 4/7] =?UTF-8?q?=EC=86=8C=EC=BC=93=20=EC=97=B0=EA=B2=B0=20?= =?UTF-8?q?=EB=B2=84=EA=B7=B8=20=EC=88=98=EC=A0=95=EC=A4=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/Chat.js | 70 ++++++++++++++++++++++------------------- src/components/Slide.js | 25 +++++++-------- 2 files changed, 49 insertions(+), 46 deletions(-) diff --git a/src/components/Chat.js b/src/components/Chat.js index 0a79309..4c7be11 100644 --- a/src/components/Chat.js +++ b/src/components/Chat.js @@ -8,10 +8,16 @@ const ChatComponent = ({ chatToken, chattingRoomId }) => { const tokenString = chatToken; useEffect(() => { + // window.addEventListener("beforeunload", () => { + // socket.close(); + // }); console.log("chatToken", chatToken); console.log("chattingRommId", chattingRoomId); const chattingRoomIdString = chattingRoomId; const accessToken = localStorage.getItem("accessToken"); + console.log( + `ws://localhost:8082/chat/${chattingRoomIdString}/${tokenString}` + ); const newSocket = new WebSocket( `ws://localhost:8082/chat/${chattingRoomIdString}/${tokenString}` ); @@ -28,41 +34,41 @@ const ChatComponent = ({ chatToken, chattingRoomId }) => { setMessages((prevMessages) => [...prevMessages, { from, message }]); }; - // newSocket.onclose = () => { - // console.log("웹소켓 연결 종료"); - // // 연결 종료 시 재연결 시도 - // setTimeout(async () => { - // console.log("accessToken", accessToken); - // const response = await fetch("http://localhost:8081/api/auth/chat", { - // method: "POST", - // headers: { - // Authorization: accessToken, - // }, - // }); + newSocket.onclose = () => { + console.log("웹소켓 연결 종료"); + // 연결 종료 시 재연결 시도 + setTimeout(async () => { + console.log("accessToken", accessToken); + const response = await fetch("http://localhost:8081/api/auth/chat", { + method: "POST", + headers: { + Authorization: accessToken, + }, + }); - // // 응답에서 토큰 추출 - // const tokenString = response.data.chatToken; - // const reconnectSocket = new WebSocket( - // `ws://localhost:8082/chat/${chattingRoomIdString}/${tokenString}` - // ); - // reconnectSocket.onopen = () => { - // console.log("웹소켓 재연결됨"); - // setSocket(reconnectSocket); - // }; + // 응답에서 토큰 추출 + const tokenString = response.data.chatToken; + const reconnectSocket = new WebSocket( + `ws://localhost:8082/chat/${chattingRoomIdString}/${tokenString}` + ); + reconnectSocket.onopen = () => { + console.log("웹소켓 재연결됨"); + setSocket(reconnectSocket); + }; - // reconnectSocket.onmessage = (event) => { - // console.log(event.data); - // const receiveData = event.data.split(":"); - // const from = receiveData[0]; - // const message = receiveData.slice(1).join(":").trim(); - // setMessages((prevMessages) => [...prevMessages, { from, message }]); - // }; - // }, 6000); // 6초 후 재연결 시도 - // }; + reconnectSocket.onmessage = (event) => { + console.log(event.data); + const receiveData = event.data.split(":"); + const from = receiveData[0]; + const message = receiveData.slice(1).join(":").trim(); + setMessages((prevMessages) => [...prevMessages, { from, message }]); + }; + }, 6000); // 6초 후 재연결 시도 + }; - // return () => { - // newSocket.close(); - // }; + return () => { + newSocket.close(); + }; }, []); const sendMessage = () => { diff --git a/src/components/Slide.js b/src/components/Slide.js index 3fa263e..f5ad011 100644 --- a/src/components/Slide.js +++ b/src/components/Slide.js @@ -1,36 +1,33 @@ -import React from 'react'; -import { Link } from 'react-router-dom'; -import './Slide.css'; +import React from "react"; +import { Link } from "react-router-dom"; +import "./Slide.css"; export const Slide = React.memo(function (StackedCarouselSlideProps) { const { data, dataIndex, isCenterSlide, swipeTo, slideIndex } = StackedCarouselSlideProps; - const coverImage = data[dataIndex].thumbnailUrl; const text = data[dataIndex].title; const channelId = data[dataIndex].channelId; - - console.log(coverImage); return ( -
+
-
+
{ if (!isCenterSlide) swipeTo(slideIndex); }} />
-
-
+
+
j

{text}

From 64d15112c98932e75d687e486f0094541870949d Mon Sep 17 00:00:00 2001 From: munee <121735319+alaneelee@users.noreply.github.com> Date: Thu, 28 Dec 2023 13:54:31 +0900 Subject: [PATCH 5/7] chat UI --- src/components/Chat.js | 134 +++++++++++++++++++++++++++---------- src/pages/ChannelDetail.js | 36 +++++----- 2 files changed, 119 insertions(+), 51 deletions(-) diff --git a/src/components/Chat.js b/src/components/Chat.js index 4c7be11..e935e72 100644 --- a/src/components/Chat.js +++ b/src/components/Chat.js @@ -1,46 +1,103 @@ -import React, { useEffect, useState } from "react"; -import { useRef } from "react"; +import React, { useEffect, useState, useRef } from 'react'; +import styled from 'styled-components'; + +const ChatContainer = styled.div` + border: 1px solid #ccc; + width: 99.7%; + height: 100%; + margin: 0 auto; + display: flex; + flex-direction: column; +`; + +const MessageContainer = styled.div` + margin-bottom: 10px; +`; + +const MessageBox = styled.div` + overflow-y: auto; +`; + +const Sender = styled.span` + color: #c0c0c0; + font-size: 1rem; + padding-left: 5px; + font-family: 'Gamja Flower', sans-serif; +`; + +const SpanText = styled.span` + font-size: 1.1rem; + color: #666; + font-family: 'Gamja Flower', sans-serif; +`; + +const InputContainer = styled.div` + margin-top: auto; + border-top: 1px solid #333333; + height: 8vh; + display: flex; + align-items: center; + justify-content: center; +`; + +const TextInput = styled.input` + border-radius: 10px; + width: 70%; + height: 10%; + padding: 10px; + margin-right: 5px; +`; + +const SendButton = styled.button` + font-family: 'Gamja Flower', sans-serif; + border-radius: 10px; + width: 20%; + height: 50%; + padding: 5px 10px; + background-color: #f8de7e; + color: #666; + border: none; + cursor: pointer; +`; const ChatComponent = ({ chatToken, chattingRoomId }) => { const [messages, setMessages] = useState([]); - const [inputMessage, setInputMessage] = useState(""); + const [inputMessage, setInputMessage] = useState(''); const [socket, setSocket] = useState(null); const tokenString = chatToken; + const messagesEndRef = useRef(null); useEffect(() => { // window.addEventListener("beforeunload", () => { // socket.close(); // }); - console.log("chatToken", chatToken); - console.log("chattingRommId", chattingRoomId); + const chattingRoomIdString = chattingRoomId; - const accessToken = localStorage.getItem("accessToken"); - console.log( - `ws://localhost:8082/chat/${chattingRoomIdString}/${tokenString}` - ); + const accessToken = localStorage.getItem('accessToken'); + const newSocket = new WebSocket( `ws://localhost:8082/chat/${chattingRoomIdString}/${tokenString}` ); setSocket(newSocket); newSocket.onopen = () => { - console.log("웹소켓 연결됨"); + console.log('웹소켓 연결됨'); }; newSocket.onmessage = (event) => { console.log(event.data); - const receiveData = event.data.split(":"); + const receiveData = event.data.split(':'); const from = receiveData[0]; - const message = receiveData.slice(1).join(":").trim(); + const message = receiveData.slice(1).join(':').trim(); setMessages((prevMessages) => [...prevMessages, { from, message }]); }; newSocket.onclose = () => { - console.log("웹소켓 연결 종료"); + console.log('웹소켓 연결 종료'); // 연결 종료 시 재연결 시도 setTimeout(async () => { - console.log("accessToken", accessToken); - const response = await fetch("http://localhost:8081/api/auth/chat", { - method: "POST", + console.log('accessToken', accessToken); + const response = await fetch('http://localhost:8081/api/auth/chat', { + method: 'POST', headers: { Authorization: accessToken, }, @@ -52,15 +109,15 @@ const ChatComponent = ({ chatToken, chattingRoomId }) => { `ws://localhost:8082/chat/${chattingRoomIdString}/${tokenString}` ); reconnectSocket.onopen = () => { - console.log("웹소켓 재연결됨"); + console.log('웹소켓 재연결됨'); setSocket(reconnectSocket); }; reconnectSocket.onmessage = (event) => { console.log(event.data); - const receiveData = event.data.split(":"); + const receiveData = event.data.split(':'); const from = receiveData[0]; - const message = receiveData.slice(1).join(":").trim(); + const message = receiveData.slice(1).join(':').trim(); setMessages((prevMessages) => [...prevMessages, { from, message }]); }; }, 6000); // 6초 후 재연결 시도 @@ -72,31 +129,40 @@ const ChatComponent = ({ chatToken, chattingRoomId }) => { }, []); const sendMessage = () => { - if (inputMessage.trim() === "") return; + if (inputMessage.trim() === '') return; socket.send(inputMessage); - setInputMessage(""); + setInputMessage(''); + }; + + const handleKeyDown = (event) => { + if (event.key === 'Enter') { + event.preventDefault(); + sendMessage(); + } }; return ( -
-
+ + {messages.map((message, index) => ( -
- {message.from}: - {message.message} -
+ + {message.from}: + {message.message} + ))} -
-
- + + + setInputMessage(e.target.value)} + onKeyDown={handleKeyDown} /> - -
-
+ 전송 + + ); }; diff --git a/src/pages/ChannelDetail.js b/src/pages/ChannelDetail.js index 3c1896f..f209c20 100644 --- a/src/pages/ChannelDetail.js +++ b/src/pages/ChannelDetail.js @@ -1,9 +1,9 @@ -import React, { useEffect, useState } from "react"; -import { useParams } from "react-router-dom"; -import Header from "../components/header"; -import VideoPlayer from "../components/ReactPlayer"; -import styled from "styled-components"; -import Chat from "../components/Chat"; +import React, { useEffect, useState } from 'react'; +import { useParams } from 'react-router-dom'; +import Header from '../components/header'; +import VideoPlayer from '../components/ReactPlayer'; +import styled from 'styled-components'; +import Chat from '../components/Chat'; const StreamingContainer = styled.div` width: 100%; @@ -20,12 +20,12 @@ const StreamingTitle = styled.p` margin-top: 15px; margin-left: 15px; font-size: 1.5rem; - font-family: "Gamja Flower", sans-serif; + font-family: 'Gamja Flower', sans-serif; `; const ChatWrapper = styled.div` width: 32%; - background-color: forestgreen; + background-color: #fff; `; const ChannelDetail = () => { @@ -39,15 +39,15 @@ const ChannelDetail = () => { `http://localhost:8081/api/channels/${id}` ); if (!response.ok) { - throw new Error("Network response was not ok."); + throw new Error('Network response was not ok.'); } const data = await response.json(); setChannelData(data); - console.log("title:", data.title); - console.log("url:", data.hlsUrl); - console.log("roomid:", data.chattingRoomId); + console.log('title:', data.title); + console.log('url:', data.hlsUrl); + console.log('roomid:', data.chattingRoomId); } catch (error) { - console.error("데이터를 불러오는 중 오류가 발생했습니다:", error); + console.error('데이터를 불러오는 중 오류가 발생했습니다:', error); } }; @@ -60,10 +60,12 @@ const ChannelDetail = () => { {channelData ? : null} {channelData ? ( - + + + ) : null} From ed6816a6249ef5b42a49ed5c8846f6b8327f81c0 Mon Sep 17 00:00:00 2001 From: munee <121735319+alaneelee@users.noreply.github.com> Date: Thu, 28 Dec 2023 14:13:16 +0900 Subject: [PATCH 6/7] =?UTF-8?q?chat=20scroll=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/Chat.js | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/components/Chat.js b/src/components/Chat.js index e935e72..85bbadc 100644 --- a/src/components/Chat.js +++ b/src/components/Chat.js @@ -15,7 +15,8 @@ const MessageContainer = styled.div` `; const MessageBox = styled.div` - overflow-y: auto; + height: 72vh; + overflow-y: scroll; `; const Sender = styled.span` @@ -120,7 +121,7 @@ const ChatComponent = ({ chatToken, chattingRoomId }) => { const message = receiveData.slice(1).join(':').trim(); setMessages((prevMessages) => [...prevMessages, { from, message }]); }; - }, 6000); // 6초 후 재연결 시도 + }, 3000); // 3초 후 재연결 시도 }; return () => { @@ -128,6 +129,12 @@ const ChatComponent = ({ chatToken, chattingRoomId }) => { }; }, []); + const scrollToBottom = () => { + messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' }); + }; + + useEffect(scrollToBottom, [messages]); + const sendMessage = () => { if (inputMessage.trim() === '') return; From 1a5eafecdbac0041bace3c63435c40ec74a18d81 Mon Sep 17 00:00:00 2001 From: BYEONGRYEOL Date: Thu, 28 Dec 2023 15:56:40 +0900 Subject: [PATCH 7/7] =?UTF-8?q?chat=20token=EC=9D=84=20=EB=A8=BC=EC=A0=80?= =?UTF-8?q?=20=EC=9A=94=EC=B2=AD=ED=95=9C=20=ED=9B=84=20chat=20=EC=84=9C?= =?UTF-8?q?=EB=B2=84=EC=97=90=20websocket=20=EC=97=B0=EA=B2=B0=20=EC=9A=94?= =?UTF-8?q?=EC=B2=AD=20=ED=95=98=EB=8F=84=EB=A1=9D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/Chat.js | 159 ++++++++++++++++++++++--------------- src/pages/ChannelDetail.js | 29 +++---- 2 files changed, 107 insertions(+), 81 deletions(-) diff --git a/src/components/Chat.js b/src/components/Chat.js index 85bbadc..bd6da16 100644 --- a/src/components/Chat.js +++ b/src/components/Chat.js @@ -1,5 +1,5 @@ -import React, { useEffect, useState, useRef } from 'react'; -import styled from 'styled-components'; +import React, { useEffect, useState, useRef } from "react"; +import styled from "styled-components"; const ChatContainer = styled.div` border: 1px solid #ccc; @@ -23,13 +23,13 @@ const Sender = styled.span` color: #c0c0c0; font-size: 1rem; padding-left: 5px; - font-family: 'Gamja Flower', sans-serif; + font-family: "Gamja Flower", sans-serif; `; const SpanText = styled.span` font-size: 1.1rem; color: #666; - font-family: 'Gamja Flower', sans-serif; + font-family: "Gamja Flower", sans-serif; `; const InputContainer = styled.div` @@ -50,7 +50,7 @@ const TextInput = styled.input` `; const SendButton = styled.button` - font-family: 'Gamja Flower', sans-serif; + font-family: "Gamja Flower", sans-serif; border-radius: 10px; width: 20%; height: 50%; @@ -61,89 +61,118 @@ const SendButton = styled.button` cursor: pointer; `; -const ChatComponent = ({ chatToken, chattingRoomId }) => { +const ChatComponent = ({ chattingRoomId }) => { const [messages, setMessages] = useState([]); - const [inputMessage, setInputMessage] = useState(''); + const [inputMessage, setInputMessage] = useState(""); const [socket, setSocket] = useState(null); - const tokenString = chatToken; const messagesEndRef = useRef(null); + const chattingRoomIdString = chattingRoomId; + const accessToken = localStorage.getItem("accessToken"); + const fetchToken = async () => { + try { + console.log(accessToken); + const response = await fetch("http://localhost:8081/api/auth/chat", { + method: "POST", + headers: { + Authorization: accessToken, + }, + }); + if (!response.ok) { + throw new Error("Network response was not ok."); + } + const data = await response.json(); + console.log("서버에서 받은 chatTokenResponseDto : ", data); + return data.chatToken; + } catch (error) { + console.error("데이터를 불러오는 중 오류가 발생했습니다:", error); + } + }; + useEffect(() => { // window.addEventListener("beforeunload", () => { // socket.close(); // }); - const chattingRoomIdString = chattingRoomId; - const accessToken = localStorage.getItem('accessToken'); - - const newSocket = new WebSocket( - `ws://localhost:8082/chat/${chattingRoomIdString}/${tokenString}` - ); - setSocket(newSocket); - newSocket.onopen = () => { - console.log('웹소켓 연결됨'); + // chatting 토큰을 먼저 요청하고 나서 webSocket 연결하기 위한 로직 + const connectWebSocketAsync = async () => { + let chatToken = ""; + console.log("accessToken is null ? :", accessToken === null); + if (accessToken) { + chatToken = await fetchToken(); + } else { + chatToken = "notlogin"; // 로그인하지 않은 사용자의 경우 토큰 정보를 notlogin으로 요청한다. + } + const newSocket = new WebSocket( + `ws://localhost:8082/chat/${chattingRoomIdString}/${chatToken}` + ); + setSocket(newSocket); + newSocket.onopen = () => { + console.log("웹소켓 연결됨"); + }; + + newSocket.onmessage = (event) => { + console.log(event.data); + const receiveData = event.data.split(":"); + const from = receiveData[0]; + const message = receiveData.slice(1).join(":").trim(); + setMessages((prevMessages) => [...prevMessages, { from, message }]); + }; + + newSocket.onclose = () => { + console.log("웹소켓 연결 종료"); + // 연결 종료 시 재연결 시도 + setTimeout(async () => { + console.log("accessToken", accessToken); + const response = await fetch("http://localhost:8081/api/auth/chat", { + method: "POST", + headers: { + Authorization: accessToken, + }, + }); + + // 응답에서 토큰 추출 + const tokenString = response.data.chatToken; + const reconnectSocket = new WebSocket( + `ws://localhost:8082/chat/${chattingRoomIdString}/${tokenString}` + ); + reconnectSocket.onopen = () => { + console.log("웹소켓 재연결됨"); + setSocket(reconnectSocket); + }; + + reconnectSocket.onmessage = (event) => { + console.log(event.data); + const receiveData = event.data.split(":"); + const from = receiveData[0]; + const message = receiveData.slice(1).join(":").trim(); + setMessages((prevMessages) => [...prevMessages, { from, message }]); + }; + }, 3000); // 3초 후 재연결 시도 + }; + return () => { + newSocket.close(); + }; }; - newSocket.onmessage = (event) => { - console.log(event.data); - const receiveData = event.data.split(':'); - const from = receiveData[0]; - const message = receiveData.slice(1).join(':').trim(); - setMessages((prevMessages) => [...prevMessages, { from, message }]); - }; - - newSocket.onclose = () => { - console.log('웹소켓 연결 종료'); - // 연결 종료 시 재연결 시도 - setTimeout(async () => { - console.log('accessToken', accessToken); - const response = await fetch('http://localhost:8081/api/auth/chat', { - method: 'POST', - headers: { - Authorization: accessToken, - }, - }); - - // 응답에서 토큰 추출 - const tokenString = response.data.chatToken; - const reconnectSocket = new WebSocket( - `ws://localhost:8082/chat/${chattingRoomIdString}/${tokenString}` - ); - reconnectSocket.onopen = () => { - console.log('웹소켓 재연결됨'); - setSocket(reconnectSocket); - }; - - reconnectSocket.onmessage = (event) => { - console.log(event.data); - const receiveData = event.data.split(':'); - const from = receiveData[0]; - const message = receiveData.slice(1).join(':').trim(); - setMessages((prevMessages) => [...prevMessages, { from, message }]); - }; - }, 3000); // 3초 후 재연결 시도 - }; - - return () => { - newSocket.close(); - }; + connectWebSocketAsync(); }, []); const scrollToBottom = () => { - messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' }); + messagesEndRef.current?.scrollIntoView({ behavior: "smooth" }); }; useEffect(scrollToBottom, [messages]); const sendMessage = () => { - if (inputMessage.trim() === '') return; + if (inputMessage.trim() === "") return; socket.send(inputMessage); - setInputMessage(''); + setInputMessage(""); }; const handleKeyDown = (event) => { - if (event.key === 'Enter') { + if (event.key === "Enter") { event.preventDefault(); sendMessage(); } @@ -162,7 +191,7 @@ const ChatComponent = ({ chatToken, chattingRoomId }) => { setInputMessage(e.target.value)} onKeyDown={handleKeyDown} diff --git a/src/pages/ChannelDetail.js b/src/pages/ChannelDetail.js index f209c20..91faf4d 100644 --- a/src/pages/ChannelDetail.js +++ b/src/pages/ChannelDetail.js @@ -1,9 +1,9 @@ -import React, { useEffect, useState } from 'react'; -import { useParams } from 'react-router-dom'; -import Header from '../components/header'; -import VideoPlayer from '../components/ReactPlayer'; -import styled from 'styled-components'; -import Chat from '../components/Chat'; +import React, { useEffect, useState } from "react"; +import { useParams } from "react-router-dom"; +import Header from "../components/header"; +import VideoPlayer from "../components/ReactPlayer"; +import styled from "styled-components"; +import Chat from "../components/Chat"; const StreamingContainer = styled.div` width: 100%; @@ -20,7 +20,7 @@ const StreamingTitle = styled.p` margin-top: 15px; margin-left: 15px; font-size: 1.5rem; - font-family: 'Gamja Flower', sans-serif; + font-family: "Gamja Flower", sans-serif; `; const ChatWrapper = styled.div` @@ -39,15 +39,15 @@ const ChannelDetail = () => { `http://localhost:8081/api/channels/${id}` ); if (!response.ok) { - throw new Error('Network response was not ok.'); + throw new Error("Network response was not ok."); } const data = await response.json(); setChannelData(data); - console.log('title:', data.title); - console.log('url:', data.hlsUrl); - console.log('roomid:', data.chattingRoomId); + console.log("title:", data.title); + console.log("url:", data.hlsUrl); + console.log("roomid:", data.chattingRoomId); } catch (error) { - console.error('데이터를 불러오는 중 오류가 발생했습니다:', error); + console.error("데이터를 불러오는 중 오류가 발생했습니다:", error); } }; @@ -61,10 +61,7 @@ const ChannelDetail = () => { {channelData ? : null} {channelData ? ( - + ) : null}