Commit 3b2c3948 authored by seoyeon's avatar seoyeon
Browse files

Merge remote-tracking branch 'origin/master' into seoyeon2

parents 042b0a4e 2eab9ded
// express 설정 파일 // express 설정 파일
import express from "express"; import express from "express";
import fs from "fs"; import cors from "cors";
import socketio from "socket.io";
import http from "http";
import wrtc from "wrtc";
import cookieParser from "cookie-parser"; import cookieParser from "cookie-parser";
import mainRouter from "./routes/index.js"; import mainRouter from "./routes/index.js";
// fs.readdir('uploads', (error) => {
// if (error) {
// fs.mkdirSync('uploads');
// }
// })
const app = express(); const app = express();
app.use(cors());
const server = http.createServer(app);
app.use(express.json()); app.use(express.json());
// app.use('/uploads', express.static('uploads'))
app.use(express.urlencoded({ extended: true })); app.use(express.urlencoded({ extended: true }));
app.use(cookieParser()); app.use(cookieParser());
app.use("/api", mainRouter); app.use("/api", mainRouter);
export default app; let receiverPCs = {};
let senderPCs = {};
let users = {};
let socketToRoom = {};
const pc_config = {
iceServers: [
// {
// urls: 'stun:[STUN_IP]:[PORT]',
// 'credentials': '[YOR CREDENTIALS]',
// 'username': '[USERNAME]'
// },
{
urls: "stun:stun.l.google.com:19302",
},
],
};
const isIncluded = (array, id) => {
let len = array.length;
for (let i = 0; i < len; i++) {
if (array[i].id === id) return true;
}
return false;
};
const createReceiverPeerConnection = (socketID, socket, roomID) => {
let pc = new wrtc.RTCPeerConnection(pc_config);
if (receiverPCs[socketID]) receiverPCs[socketID] = pc;
else receiverPCs = { ...receiverPCs, [socketID]: pc };
pc.onicecandidate = (e) => {
//console.log(`socketID: ${socketID}'s receiverPeerConnection icecandidate`);
socket.to(socketID).emit("getSenderCandidate", {
candidate: e.candidate,
});
};
pc.oniceconnectionstatechange = (e) => {
//console.log(e);
};
pc.ontrack = (e) => {
if (users[roomID]) {
if (!isIncluded(users[roomID], socketID)) {
users[roomID].push({
id: socketID,
stream: e.streams[0],
});
} else return;
} else {
users[roomID] = [
{
id: socketID,
stream: e.streams[0],
},
];
}
socket.broadcast.to(roomID).emit("userEnter", { id: socketID });
};
return pc;
};
const createSenderPeerConnection = (
receiverSocketID,
senderSocketID,
socket,
roomID
) => {
let pc = new wrtc.RTCPeerConnection(pc_config);
if (senderPCs[senderSocketID]) {
senderPCs[senderSocketID].filter((user) => user.id !== receiverSocketID);
senderPCs[senderSocketID].push({ id: receiverSocketID, pc: pc });
} else
senderPCs = {
...senderPCs,
[senderSocketID]: [{ id: receiverSocketID, pc: pc }],
};
pc.onicecandidate = (e) => {
//console.log(`socketID: ${receiverSocketID}'s senderPeerConnection icecandidate`);
socket.to(receiverSocketID).emit("getReceiverCandidate", {
id: senderSocketID,
candidate: e.candidate,
});
};
pc.oniceconnectionstatechange = (e) => {
//console.log(e);
};
const sendUser = users[roomID].filter((user) => user.id === senderSocketID);
sendUser[0].stream.getTracks().forEach((track) => {
pc.addTrack(track, sendUser[0].stream);
});
return pc;
};
const getOtherUsersInRoom = (socketID, roomID) => {
let allUsers = [];
if (!users[roomID]) return allUsers;
let len = users[roomID].length;
for (let i = 0; i < len; i++) {
if (users[roomID][i].id === socketID) continue;
allUsers.push({ id: users[roomID][i].id });
}
return allUsers;
};
const deleteUser = (socketID, roomID) => {
let roomUsers = users[roomID];
if (!roomUsers) return;
roomUsers = roomUsers.filter((user) => user.id !== socketID);
users[roomID] = roomUsers;
if (roomUsers.length === 0) {
delete users[roomID];
}
delete socketToRoom[socketID];
};
const closeRecevierPC = (socketID) => {
if (!receiverPCs[socketID]) return;
receiverPCs[socketID].close();
delete receiverPCs[socketID];
};
const closeSenderPCs = (socketID) => {
if (!senderPCs[socketID]) return;
let len = senderPCs[socketID].length;
for (let i = 0; i < len; i++) {
senderPCs[socketID][i].pc.close();
let _senderPCs = senderPCs[senderPCs[socketID][i].id];
let senderPC = _senderPCs.filter((sPC) => sPC.id === socketID);
if (senderPC[0]) {
senderPC[0].pc.close();
senderPCs[senderPCs[socketID][i].id] = _senderPCs.filter(
(sPC) => sPC.id !== socketID
);
}
}
delete senderPCs[socketID];
};
const io = socketio.listen(server);
io.sockets.on("connection", (socket) => {
console.log("socket connection complete")
socket.on("joinRoom", (data) => {
try {
let allUsers = getOtherUsersInRoom(data.id, data.roomID);
io.to(data.id).emit("allUsers", { users: allUsers });
} catch (error) {
console.log(error);
}
});
socket.on("senderOffer", async (data) => {
try {
socketToRoom[data.senderSocketID] = data.roomID;
let pc = createReceiverPeerConnection(
data.senderSocketID,
socket,
data.roomID
);
await pc.setRemoteDescription(data.sdp);
let sdp = await pc.createAnswer({
offerToReceiveAudio: true,
offerToReceiveVideo: true,
});
await pc.setLocalDescription(sdp);
socket.join(data.roomID);
io.to(data.senderSocketID).emit("getSenderAnswer", { sdp });
} catch (error) {
console.log(error);
}
});
socket.on("senderCandidate", async (data) => {
try {
let pc = receiverPCs[data.senderSocketID];
await pc.addIceCandidate(new wrtc.RTCIceCandidate(data.candidate));
} catch (error) {
console.log(error);
}
});
socket.on("receiverOffer", async (data) => {
try {
let pc = createSenderPeerConnection(
data.receiverSocketID,
data.senderSocketID,
socket,
data.roomID
);
await pc.setRemoteDescription(data.sdp);
let sdp = await pc.createAnswer({
offerToReceiveAudio: false,
offerToReceiveVideo: false,
});
await pc.setLocalDescription(sdp);
io.to(data.receiverSocketID).emit("getReceiverAnswer", {
id: data.senderSocketID,
sdp,
});
} catch (error) {
console.log(error);
}
});
socket.on("receiverCandidate", async (data) => {
try {
const senderPC = senderPCs[data.senderSocketID].filter(
(sPC) => sPC.id === data.receiverSocketID
);
await senderPC[0].pc.addIceCandidate(
new wrtc.RTCIceCandidate(data.candidate)
);
} catch (error) {
console.log(error);
}
});
socket.on("disconnect", () => {
try {
let roomID = socketToRoom[socket.id];
deleteUser(socket.id, roomID);
closeRecevierPC(socket.id);
closeSenderPCs(socket.id);
socket.broadcast.to(roomID).emit("userExit", { id: socket.id });
} catch (error) {
console.log(error);
}
});
});
export default server;
import axios from "axios"; import axios from "axios";
const login = async (payload) => { const create = async (payload) => {
const { data } = await axios.post("/api/login", payload); const { data } = await axios.post("/api/room/create", payload);
return data; return data;
}; };
const signup = async (payload) => { const join = async (payload) => {
const { data } = await axios.post("/api/signup", payload); const { data } = await axios.put("/api/room/join", payload);
return data; return data;
}; };
const roomApi = { login, signup }; const roomApi = { create, join };
export default roomApi; export default roomApi;
import CreateRoom from "./CreateRoom";
import JoinRoom from "./JoinRoom";
const AddRoom = () => { const AddRoom = () => {
return ( return (
<div> <div>
...@@ -50,11 +53,19 @@ const AddRoom = () => { ...@@ -50,11 +53,19 @@ const AddRoom = () => {
backgroundColor: "#E0CEE8", backgroundColor: "#E0CEE8",
borderColor: "#E0CEE8", borderColor: "#E0CEE8",
}} }}
>방참여하기
</button>
<div
className="modal fade"
id="joinModal"
tabIndex="-1"
aria-labelledby="joinModalLabel"
aria-hidden="true"
> >
<div style={{ width: "6rem" }} > <div className="modal-dialog">
방참여하기 <JoinRoom />
</div>
</div> </div>
</button>
</div> </div>
<div className="col-6 d-flex justify-content-center"> <div className="col-6 d-flex justify-content-center">
<button <button
...@@ -70,83 +81,20 @@ const AddRoom = () => { ...@@ -70,83 +81,20 @@ const AddRoom = () => {
backgroundColor: "#f5cfe3", backgroundColor: "#f5cfe3",
borderColor: "#f5cfe3", borderColor: "#f5cfe3",
}} }}
> >방생성하기
<div style={{ width: "6rem" }} >
방생성하기
</div>
</button>
</div>
</div>
</div>
</div>
</div>
</div>
{/* 방참여하기 모달 */}
<div className="modal" id="joinModal" tabIndex="-1" aria-hidden="true">
<div className="modal-dialog">
<div className="modal-content">
<div className="modal-header">
<div>방참여하기</div>
<button
type="button"
className="btn-close"
data-bs-dismiss="modal"
aria-label="Close"
></button>
</div>
<div className="modal-body">
<div className="input-group mb-3">
<input
type="text"
className="form-control"
placeholder="참여코드를 입력하세요"
aria-label="참여코드를 입력하세요"
aria-describedby="basic-addon1"
/>
</div>
<div className="modal-footer">
<button type="submit" className="btn btn-primary">
확인
</button> </button>
</div> <div
</div> className="modal fade"
</div> id="makeModal"
</div> tabIndex="-1"
</div> aria-labelledby="makeModalLabel"
aria-hidden="true"
{/* 방생성하기 모달 */} >
<div className="modal" id="makeModal" tabIndex="-1" aria-hidden="true">
<div className="modal-dialog"> <div className="modal-dialog">
<div className="modal-content"> <CreateRoom />
<div className="modal-header">
<div>방생성하기</div>
<button
type="button"
className="btn-close"
data-bs-dismiss="modal"
aria-label="Close"
></button>
</div> </div>
<div className="modal-body">
<h6>방프로필사진</h6>
<div className="mb-4">
<input type="file" className="upload-hidden" />
</div> </div>
<h6>방이름</h6>
<div className="input-group">
<input
type="text"
className="form-control"
placeholder="방이름을 입력해주세요"
aria-label="방이름 입력해주세요"
aria-describedby="basic-addon1"
/>
</div> </div>
<div className="modal-footer">
<button type="submit" className="btn btn-primary">
생성
</button>
</div> </div>
</div> </div>
</div> </div>
......
import { useEffect, useState } from "react";
import roomApi from "../../apis/room.api";
const userId = localStorage.getItem('user');
console.log(userId)
const INIT_ROOM = {
name: '',
profileimg: '',
channel: ['회의'],
}
const CreateRoom = () => {
const [room, setRoom] = useState(INIT_ROOM)
const [error, setError] = useState("");
const [success, setSuccess] = useState(false)
const [disabled, setDisabled] = useState(true)
useEffect(() => {
const isRoom = Object.values(roomApi).every((el) => Boolean(el));
isRoom ? setDisabled(false) : setDisabled(true);
}, [room]);
// const userId = localStorage.getItem('user');
// setRoom({...room, owner: userId})
// setRoom({...room, member: userId})
function handleChange(event) {
console.log(room)
const { name, value } = event.target
setRoom({ ...room, [name]: value })
}
console.log(room)
async function handleSubmit(e) {
e.preventDefault()
console.log('룸룸', room)
try {
const res = await roomApi.create(room)
// console.log(res)
const Id = res.id
// console.log(Id)
//alert(`방참여코드는 ${Id}입니다`)
//setSuccess(true)
} catch (error) {
// catchErrors(error, setError);
} finally {
// setLoading(false);
}
}
if (success) {
console.log('success', success)
alert('룸생성이 완료되었습니다!')
//return <Redirect to='/' />
}
const { name, owner, member, profileimg } = room;
return (
<div className="modal-content" >
<form onSubmit={handleSubmit}>
<div className="modal-header">
<div className="modal-title" id="makeModal">방생성하기</div>
<button
type="button"
className="btn-close"
data-bs-dismiss="modal"
aria-label="Close"
></button>
</div>
<div className="modal-body">
<h6>방프로필사진</h6>
<div className="mb-4">
<input
type="file"
className="upload-hidden"
onChange={handleChange}
accept="image/*"
name="profileimg"
value={room.profileimg} />
</div>
<h6>방이름</h6>
<div className="input-group">
<input
type="text"
className="form-control"
placeholder="방이름을 입력해주세요"
aria-label="방이름 입력해주세요"
aria-describedby="basic-addon1"
onChange={handleChange}
name="name"
value={room.name}
/>
</div>
<div className="modal-footer">
<button type="submit" className="btn btn-primary">
생성
</button>
</div>
</div>
</form>
</div >
);
};
export default CreateRoom;
\ No newline at end of file
import { useEffect, useState } from "react";
import { Redirect } from "react-router-dom";
import roomApi from "../../apis/room.api";
const userId = localStorage.getItem('user');
const JoinRoom = () => {
const [roomId, setRoomId] = useState('');
const [disabled, setDisabled] = useState(true);
const [error, setError] = useState("");
const [success, setSuccess] = useState(false);
useEffect(() => {
const isRoom = Object.values(roomApi).every((el) => Boolean(el));
isRoom ? setDisabled(false) : setDisabled(true);
}, [roomId]);
function handleChange(event) {
const { value } = event.target;
setRoomId(value);
console.log(roomId);
}
async function handleSubmit(e) {
e.preventDefault();
try {
// setLoading(true);
// setError("");
console.log('userId:',userId)
console.log('roomId:',roomId)
const data = await roomApi.join({userId: userId, roomId: roomId});
console.log(data);
setSuccess(true);
} catch (error) {
// catchErrors(error, setError);
} finally {
// setLoading(false);
}
}
if (success) {
}
return (
<div className="modal-content">
<form onSubmit={handleSubmit}>
<div className="modal-header">
<div className="modal-title" id="joinModal">방참여하기</div>
<button
type="button"
className="btn-close"
data-bs-dismiss="modal"
aria-label="Close"
></button>
</div>
<div className="modal-body">
<div className="input-group mb-3">
<input
type="text"
className="form-control"
placeholder="참여코드를 입력하세요"
aria-label="참여코드를 입력하세요"
aria-describedby="basic-addon1"
name="roomId"
value={roomId}
onChange={handleChange}
/>
</div>
<div className="modal-footer">
<button type="submit" className="btn btn-primary">
확인
</button>
</div>
</div>
</form>
</div>
);
};
export default JoinRoom;
\ No newline at end of file
...@@ -87,7 +87,7 @@ const Login = () => { ...@@ -87,7 +87,7 @@ const Login = () => {
</div> </div>
</div> </div>
<div className="modal-footer"> <div className="modal-footer">
<button type="submit" className="btn btn-primary" disabled={disabled}> <button type="submit" className="btn btn-primary" disabled={disabled} data-bs-dismiss="modal">
로그인 로그인
</button> </button>
</div> </div>
......
...@@ -120,7 +120,7 @@ const InfoUpdate = () => { ...@@ -120,7 +120,7 @@ const InfoUpdate = () => {
현재 비밀번호 현재 비밀번호
</label> </label>
<input <input
type="text" type="password"
class="form-control" class="form-control"
style={{ height: "38px", width: "200px" }} style={{ height: "38px", width: "200px" }}
/> />
......
import backward from "../../backward.png";
import ChannelSingle from "./ChannelSingle";
const LeftHamberger = () => {
function roomIdCopy() {
const t = document.querySelector("#roomId").innerText;
console.log(t);
navigator.clipboard.writeText(t);
//document.execCommand("copy");
}
return (
<div>
<div>
<button
className="navbar-toggler"
type="button"
data-bs-toggle="offcanvas"
data-bs-target="#left-hamburger"
aria-controls="left-hamburger"
aria-expanded="false"
aria-label="Toggle navigation"
style={{ border: "#f4c1f2" }}
>
<span className="navbar-toggler-icon"></span>
</button>
</div>
<div
className="offcanvas offcanvas-start"
style={{ width: "330px" }}
tabIndex="-1"
id="left-hamburger"
aria-labelledby="hamburgerLabel"
>
<div className="offcanvas-header">
<p
className="col-6 offcanvas-title"
id="offcanvasExampleLabel"
style={{
fontWeight: "bold",
fontSize: "15px",
width: "150px",
color: "#000000",
}}
>
/오프라인 사용자
</p>
<h6 className="mt-2" id="roomId">
{" "}
#ASV2AE985{" "}
</h6>
<button
type="button"
className="btn-close text-reset"
data-bs-dismiss="offcanvas"
aria-label="Close"
></button>
</div>
<div className="overflow-auto" style={{ height: "610px" }}>
<div className="mb-3">
<div className="m-3 p-1 row" style={{ backgroundColor: "#E0CEE8" }}>
<h5 className="col mt-2">온라인 사용자</h5>
</div>
<ul className="mx-5" style={{ color: "#76D079" }}>
<li>
<p style={{ color: "black" }}>CHERRY</p>
</li>
<li>
<p style={{ color: "black" }}>JAEYEON</p>
</li>
<li>
<p style={{ color: "black" }}>SEOYEON</p>
</li>
<li>
<p style={{ color: "black" }}>JIWEON</p>
</li>
<li>
<p style={{ color: "black" }}>BYOUNGYUN</p>
</li>
</ul>
</div>
<div className="mb-3">
<div className="m-3 p-1 row" style={{ backgroundColor: "#E0CEE8" }}>
<h5 className="col mt-2">오프라인 사용자</h5>
</div>
<ul className="mx-5">
<li>CHERRY</li>
<li>JAEYEON</li>
<li>SEOYEON</li>
<li>JIWEON</li>
<li>BYOUNGYUN</li>
</ul>
</div>
</div>
<div>
<div className="d-flex flex-row-reverse">
<button
type="button"
className="m-3 rounded"
data-bs-toggle="modal"
data-bs-target="#exitRoom"
style={{
height: "30px",
fontWeight: "bold",
backgroundColor: "#E0CEE8",
color: "black",
border: "1px #D64D61",
}}
>
초대
</button>
<div
className="modal fade"
id="exitRoom"
tabIndex="-1"
aria-labelledby="exitRoomLabel"
aria-hidden="true"
>
<div className="modal-dialog">
<div className="modal-content">
<div className="modal-header">
<button
type="button"
className="btn-close"
data-bs-dismiss="modal"
aria-label="Close"
></button>
</div>
<div className="modal-body d-flex justify-content-center">
어떤 방식으로 초대하시겠습니까?
</div>
<div className="row mb-3">
<div className="d-flex justify-content-evenly">
<button
type="submit"
className="col-2 p-1 btn btn-primary"
style={{ width: "120px" }}
>
카카오로 초대
</button>
<button
type="submit"
className="col-2 p-1 btn btn-primary"
data-bs-dismiss="modal"
style={{ width: "120px" }}
onClick={roomIdCopy}
>
Id 복사
</button>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
);
};
export default LeftHamberger;
import React, { useState } from "react";
import io from "socket.io-client";
import { useRef } from "react";
import { useEffect } from "react";
import Video from "./Video";
import { useParams } from "react-router-dom";
const Screen = () => { const Screen = () => {
const user = '00' const [socket, setSocket] = useState(null);
const [users, setUsers] = useState([]);
const { roomId, channelId } = useParams();
const user = "00";
let localVideoRef = useRef(null);
let sendPC;
let receivePCs;
// 방화벽 등의 보호장치를 거쳐 ip로 연결하기 위한 설정
const pc_config = {
iceServers: [
// {
// urls: 'stun:[STUN_IP]:[PORT]',
// 'credentials': '[YOR CREDENTIALS]',
// 'username': '[USERNAME]'
// },
{
urls: "stun:stun.l.google.com:19302",
},
],
};
useEffect(() => {
let newSocket = io.connect("http://localhost:8080");
let localStream;
// console.log("newSocket", newSocket.id);
//
newSocket.on("userEnter", (data) => {
console.log(data);
createReceivePC(data.id, newSocket);
});
newSocket.on("allUsers", (data) => {
let len = data.users.length;
for (let i = 0; i < len; i++) {
createReceivePC(data.users[i].id, newSocket);
}
});
newSocket.on("userExit", (data) => {
receivePCs[data.id].close();
delete receivePCs[data.id];
setUsers((users) => users.filter((user) => user.id !== data.id));
});
newSocket.on("getSenderAnswer", async (data) => {
try {
console.log("get sender answer");
console.log(data.sdp);
await sendPC.setRemoteDescription(new RTCSessionDescription(data.sdp));
} catch (error) {
console.log(error);
}
});
newSocket.on("getSenderCandidate", async (data) => {
try {
console.log("get sender candidate");
if (!data.candidate) return;
sendPC.addIceCandidate(new RTCIceCandidate(data.candidate));
console.log("candidate add success");
} catch (error) {
console.log(error);
}
});
newSocket.on("getReceiverAnswer", async (data) => {
try {
console.log(`get socketID(${data.id})'s answer`);
let pc = receivePCs[data.id];
await pc.setRemoteDescription(data.sdp);
console.log(`socketID(${data.id})'s set remote sdp success`);
} catch (error) {
console.log(error);
}
});
newSocket.on("getReceiverCandidate", async (data) => {
try {
console.log(data);
console.log(`get socketID(${data.id})'s candidate`);
let pc = receivePCs[data.id];
if (!data.candidate) return;
pc.addIceCandidate(new RTCIceCandidate(data.candidate));
console.log(`socketID(${data.id})'s candidate add success`);
} catch (error) {
console.log(error);
}
});
setSocket(newSocket);
navigator.mediaDevices
.getUserMedia({
audio: true,
video: {
width: 375,
height: 260,
},
})
.then((stream) => {
if (localVideoRef.current) localVideoRef.current.srcObject = stream;
localStream = stream;
sendPC = createSenderPeerConnection(newSocket, localStream);
createSenderOffer(newSocket);
newSocket.emit("joinRoom", {
id: newSocket.id,
roomID: roomId,
});
})
.catch((error) => {
console.log(`getUserMedia error: ${error}`);
});
}, []);
const createReceivePC = (id, newSocket) => {
try {
console.log(`socketID(${id}) user entered`);
let pc = createReceiverPeerConnection(id, newSocket);
createReceiverOffer(pc, newSocket, id);
} catch (error) {
console.log(error);
}
};
const createSenderOffer = async (newSocket) => {
try {
let sdp = await sendPC.createOffer({
offerToReceiveAudio: false,
offerToReceiveVideo: false,
});
console.log("create sender offer success");
await sendPC.setLocalDescription(new RTCSessionDescription(sdp));
console.log(sdp, "", newSocket.id, "", roomId);
newSocket.emit("senderOffer", {
sdp,
senderSocketID: newSocket.id,
roomID: roomId,
});
} catch (error) {
console.log(error);
}
};
const createReceiverOffer = async (pc, newSocket, senderSocketID) => {
try {
let sdp = await pc.createOffer({
offerToReceiveAudio: true,
offerToReceiveVideo: true,
});
console.log("create receiver offer success");
await pc.setLocalDescription(new RTCSessionDescription(sdp));
console.log(sdp, newSocket.id, senderSocketID, roomId);
newSocket.emit("receiverOffer", {
sdp,
receiverSocketID: newSocket.id,
senderSocketID,
roomID: roomId,
});
} catch (error) {
console.log(error);
}
};
const createSenderPeerConnection = (newSocket, localStream) => {
let pc = new RTCPeerConnection(pc_config);
pc.onicecandidate = (e) => {
if (e.candidate) {
console.log("sender PC onicecandidate");
newSocket.emit("senderCandidate", {
candidate: e.candidate,
senderSocketID: newSocket.id,
});
}
};
pc.oniceconnectionstatechange = (e) => {
console.log(e);
};
if (localStream) {
console.log("localstream add");
localStream.getTracks().forEach((track) => {
pc.addTrack(track, localStream);
});
} else {
console.log("no local stream");
}
// return pc
return pc;
};
const createReceiverPeerConnection = (socketID, newSocket) => {
let pc = new RTCPeerConnection(pc_config);
// add pc to peerConnections object
receivePCs = { ...receivePCs, [socketID]: pc };
pc.onicecandidate = (e) => {
if (e.candidate) {
console.log("receiver PC onicecandidate");
newSocket.emit("receiverCandidate", {
candidate: e.candidate,
receiverSocketID: newSocket.id,
senderSocketID: socketID,
});
}
};
pc.oniceconnectionstatechange = (e) => {
console.log(e);
};
pc.ontrack = (e) => {
console.log("ontrack success");
setUsers((oldUsers) => oldUsers.filter((user) => user.id !== socketID));
setUsers((oldUsers) => [
...oldUsers,
{
id: socketID,
stream: e.streams[0],
},
]);
};
// return pc
return pc;
};
return ( return (
<div className="container"> <div className="container">
<div className="row"> {/* {console.log(users)} */}
<div className="col mt-3 d-flex justify-content-space-between" style={{ backgroundColor: '#FCF4FF' }}> <div className="mt-3" style={{ backgroundColor: "#FCF4FF" }}>
<div
className="m-2 d-flex fw-bold text-center"
style={{ color: "#4A4251", fontSize: "20px" }}
>
<img <img
className="rounded-circle" className="rounded-circle me-2"
src="/cherry.jpg" src="/cherry.jpg"
width="40px" width="40px"
height="40px" height="40px"
/> />
<p
className="m-2"
style={{ fontWeight: 'bold', color: '#4A4251', fontSize: '20px' }}
>
{user}님이 화면공유중... {user}님이 화면공유중...
<br />
</p>
<div className="col m-5"></div>
</div> </div>
<video
style={{
display: "flex",
justifyContent: "center",
width: 375,
height: 260,
backgroundColor: "black",
}}
muted
ref={localVideoRef}
autoPlay
/>
{/* {users.map((user, index) => {
return <Video key={index} stream={user.stream} />;
})} */}
</div> </div>
</div> </div>
) );
} };
export default Screen export default Screen;
...@@ -42,11 +42,18 @@ const Signup = () => { ...@@ -42,11 +42,18 @@ const Signup = () => {
async function handleSubmit() { async function handleSubmit() {
try { try {
<<<<<<< HEAD
const data = await userApi.signup(user) const data = await userApi.signup(user)
// const data = await axios.post("https://localhost:8080/api/room/1/1",user) // const data = await axios.post("https://localhost:8080/api/room/1/1",user)
setLoading(true); setLoading(true);
setError(""); setError("");
// const success = await login(user.email, user.password); // const success = await login(user.email, user.password);
=======
const data = await axios.post("/api/room/1/1",user)
// setLoading(true);
// setError("");
// const success = await login(user.email, user.password);
>>>>>>> origin/master
console.log(data); console.log(data);
// sestSuccess(success); // sestSuccess(success);
} catch (error) { } catch (error) {
......
import { Room } from "../models/index.js"; import { Room, User } from "../models/index.js";
import { customAlphabet } from 'nanoid'
import config from "../config/app.config.js";
import isLength from 'validator/lib/isLength.js'
const nanoid = customAlphabet('1234567890abcdef', 10)
const joinRoom = async (req, res) => {
console.log('req.body.value:', req.body)
const { userId, roomId } = req.body
console.log('userId:', userId)
console.log('roomId:', roomId)
const room_Id = await Room.findOne({ where: { id: roomId } });
console.log('room_Id:', room_Id)
if (room_Id) {
//roomId에 일치하는 방의 member정보에 userId 저장하기
console.log('room_Id.member1:', room_Id.member)
room_Id.member.push(userId)
console.log('room_Id.member2:', room_Id.member)
await Room.update({ 'member': room_Id.member }, { where: { id: roomId } })
const roomID = await Room.findOne({ where: { id: roomId } });
console.log('room_Id2:', roomID.member)
//userId에 일치하는 사용자의 roomNumber에 roomId저장하기
// const user_Id = await User.findOne({ where: { id: userId } });
// console.log('user_Id:', user_Id)
// console.log('user_Id.roomNumber1:', user_Id.roomNumber)
// user_Id.roomNumber.push(roomId)
// console.log('user_Id.roomNumber2:', user_Id.roomNumber)
// await User.update({ 'roomNumber': roomId }, { where: { id: userId } })
// const userID = await User.findOne({ where: { id: userId } });
// console.log('user_Id2:', userID.roomNumber)
} else {
return res.status(422).send('참여코드와 일치하는 방이 존재하지 않습니다.')
}
};
// const changemember = async (req, res) => {
// const { userId, roomId } = req.body
// // console.log(roomId)
// let room = await Room.findOne({ roomId: roomId }).select('member')
// const isPresent = room.member.indexOf(userId)
// indexOf : userId가 몇번째 인덱스인지 찾기
// try {
// if (isPresent < 0) {
// const memberId = room.member.push(userId)
// await Room.updateOne({ 'roomId': roomId }, { 'member': room.member })
// // console.log('room.member 업데이트 완료')
// return res.json(true)
// }
// else {
// return res.json(false)
// }
// } catch (error) {
// res.status(500).send('멤버 업데이트 실패')
// }
// }
const createRoom = async (req, res) => {
console.log('룸정보', req.body)
const { name, owner, member, profileimg, channel } = req.body;
console.log('owner:', owner)
const id = nanoid()
console.log('id:', id)
const Id = await Room.findOne({ where: { id: id } });
console.log("Id중복확인:", Id)
while (Id) {
const id = nanoid()
const Id = await Room.findOne({ where: { id: id } });
}
const test = async (req, res) => {
try { try {
console.log("room= ", req.body); if (!isLength(name, { min: 3, max: 20 })) {
res.json("안녕"); console.log('방이름은 3-20자여야 합니다.')
return res.status(422).send('방이름은 3-20자여야 합니다.')
}
const newRoom = await Room.create({
id: id,
name: name,
owner: owner,
member: member,
profileimg: profileimg,
channel: channel,
}).then(_ => console.log('room정보:', id, name, owner, member, profileimg, channel))
console.log('newRoom:', newRoom)
res.json(newRoom)
} catch (error) { } catch (error) {
console.log(error); console.log(error)
return res.status(500).send("안녕 중 에러"); res.status(500).send('방생성 에러')
} }
}; }
export default { export default {
test, joinRoom, createRoom
}; };
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
import dotenv from "dotenv"; import dotenv from "dotenv";
import app from "./app.js"; import app from "./app.js";
import appConfig from "./config/app.config.js"; import appConfig from "./config/app.config.js";
import { sequelize, User } from "./models/index.js"; import { Room, sequelize, User } from "./models/index.js";
dotenv.config({ dotenv.config({
path: `${ path: `${
...@@ -15,13 +15,22 @@ sequelize ...@@ -15,13 +15,22 @@ sequelize
.then(async () => { .then(async () => {
console.log(" DB 연결 성공"); console.log(" DB 연결 성공");
await User.create({ await User.create({
id: 9999, id: "9999",
name: "admin", name: "admin",
email: "admin", email: "admin",
password: "admin!", password: "admin!",
gender: 0, gender: 0,
}); });
await Room.create({
id: "1234567890",
name: "room",
owner: [ '600112d16d09ac6b7892d900' ],
member: [ '600112d16d09ac6b7892d900' ],
profileimg: "C:\fakepath\스크린샷(1).png",
channel: [ '회의' ],
});
app.listen(appConfig.port, () => { app.listen(appConfig.port, () => {
console.log(`Server is running on port ${appConfig.port}`); console.log(`Server is running on port ${appConfig.port}`);
}); });
...@@ -30,39 +39,3 @@ sequelize ...@@ -30,39 +39,3 @@ sequelize
console.log("연결 실패"); console.log("연결 실패");
console.log(err); console.log(err);
}); });
\ No newline at end of file
// production
// sequelize.sync().then(() => {
// app.listen(appConfig.port, () => {
// console.log(`Server is running on port ${appConfig.port}`)
// })
// })
// development
// 주의!!!: {force: true}는 서버가 다시 시작되면 기존 디비 모두 삭제되고 새로운 디비 생성
// sequelize
// .sync({ force: true })
// .then(async () => {
// // await Promise.all(
// // Object.keys(ROLE_NAME).map((name) => {
// // return Role.create({ name });
// // })
// // );
// // const adminRole = await Role.findOne({ where: { name: "admin" } });
// await User.create({
// id: "0000",
// name: "admin",
// email: "admin",
// password: "admin!",
// gender: 0,
// });
// app.listen(appConfig.port, () => {
// console.log(`Server is running on port ${appConfig.port}`);
// });
// })
// .catch((err) => {
// console.log(err);
// });
...@@ -5,17 +5,20 @@ const RoomModel = (sequelize) => { ...@@ -5,17 +5,20 @@ const RoomModel = (sequelize) => {
"room", "room",
{ {
id: { id: {
type: DataTypes.INTEGER, type: DataTypes.STRING,
primaryKey: true, primaryKey: true,
}, },
name: { name: {
type: DataTypes.STRING, type: DataTypes.STRING,
}, },
owner: { owner: {
type: DataTypes.STRING, type: DataTypes.ARRAY(DataTypes.STRING),
}, },
member: { member: {
type: DataTypes.ARRAY(DataTypes.INTEGER), type: DataTypes.ARRAY(DataTypes.STRING),
},
profileimg: {
type: DataTypes.STRING,
}, },
channel: { channel: {
type: DataTypes.ARRAY(DataTypes.JSON), type: DataTypes.ARRAY(DataTypes.JSON),
...@@ -23,8 +26,8 @@ const RoomModel = (sequelize) => { ...@@ -23,8 +26,8 @@ const RoomModel = (sequelize) => {
}, },
{ timestamps: true } { timestamps: true }
); );
return Room; return Room;
}; };
export default RoomModel; export default RoomModel;
...@@ -22,11 +22,10 @@ const UserModel = (sequelize) => { ...@@ -22,11 +22,10 @@ const UserModel = (sequelize) => {
type: DataTypes.INTEGER, type: DataTypes.INTEGER,
}, },
phone: { phone: {
type: DataTypes.STRING, type: DataTypes.INTEGER,
}, },
img: { img: {
type: DataTypes.ARRAY(DataTypes.INTEGER), type: DataTypes.STRING,
default:'/user.png'
}, },
roomNumber: { roomNumber: {
type: DataTypes.ARRAY(DataTypes.STRING), type: DataTypes.ARRAY(DataTypes.STRING),
......
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
"express": "4.17.1", "express": "4.17.1",
"http": "0.0.1-security", "http": "0.0.1-security",
"jsonwebtoken": "^8.5.1", "jsonwebtoken": "^8.5.1",
"nanoid": "^3.1.20",
"nodemon": "^2.0.7", "nodemon": "^2.0.7",
"pg": "^8.6.0", "pg": "^8.6.0",
"pg-hstore": "^2.3.4", "pg-hstore": "^2.3.4",
......
...@@ -5,6 +5,6 @@ import roomRouter from "./room.route.js"; ...@@ -5,6 +5,6 @@ import roomRouter from "./room.route.js";
const router = express.Router(); const router = express.Router();
router.use("/", userRouter); router.use("/", userRouter);
router.use("/room/:userId/:channelId", roomRouter); router.use("/room", roomRouter);
export default router; export default router;
...@@ -3,6 +3,8 @@ import roomCrtl from "../controllers/room.controller.js"; ...@@ -3,6 +3,8 @@ import roomCrtl from "../controllers/room.controller.js";
const router = express.Router(); const router = express.Router();
router.route("/").post(roomCrtl.test); router.route("/create").post(roomCrtl.createRoom);
router.route("/join").put(roomCrtl.joinRoom);
export default router; export default router;
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment