From 2517ebc368c94263d640afdb8d32d87ed8c857bc Mon Sep 17 00:00:00 2001 From: hollag Date: Thu, 14 Nov 2024 00:35:05 +0800 Subject: [PATCH 1/3] fix: video call stuff --- .../Communication/Video/VideoChatWidget.tsx | 47 +++++++++++++++---- .../components/TestCases/TestCasesWrapper.tsx | 3 -- .../pages/Session/SessionPage/SessionPage.tsx | 5 +- 3 files changed, 40 insertions(+), 15 deletions(-) diff --git a/peer-prep/src/components/Communication/Video/VideoChatWidget.tsx b/peer-prep/src/components/Communication/Video/VideoChatWidget.tsx index 1ea414d5e7..c941cf5a2b 100644 --- a/peer-prep/src/components/Communication/Video/VideoChatWidget.tsx +++ b/peer-prep/src/components/Communication/Video/VideoChatWidget.tsx @@ -45,7 +45,7 @@ type Offer = RTCSessionDescriptionInit; enum CALL_STATUS { IDLE, - CALLING, + CALLING, // ready to call CONNECTED, INCOMING, } @@ -68,6 +68,9 @@ export default function VideoChatWidget({ roomId: string; }) { const auth = useAuth(); + const [remotePeerIdFromCall, setRemotePeerIdFromCall] = useState< + string | null + >(null); const [callStatus, setCallStatus] = useState(CALL_STATUS.IDLE); const callStatusRef = useRef(CALL_STATUS.IDLE); @@ -80,7 +83,6 @@ export default function VideoChatWidget({ const remoteVideoRef = useRef(null); // only when this is populated are we ready to make a call (connection wise) - const [peerId, setPeerId] = useState(null); const [remotePeerIdValue, setRemotePeerIdValue] = useState(""); const peerInstance = useRef(null); const mediaConnection = useRef(null); @@ -97,11 +99,18 @@ export default function VideoChatWidget({ peer.on("open", (id) => { console.log("DEBUG: peer open id set to", id); - setPeerId(id); }); peer.on("call", async (call) => { console.log("DEBUG: call received", call); + setRemotePeerIdFromCall(call.peer); + + // setup a listener for when the call ends + const conn = peer.connect(call.peer); + console.log("DEBUG: conn", conn); + conn.on("data", (data) => { + console.log(`DEBUG: data received FROM PEERJS: `, data); + }); // dont answer if not ready to call if (callStatusRef.current !== CALL_STATUS.CALLING) { @@ -113,10 +122,14 @@ export default function VideoChatWidget({ } is calling you! Go to the chat room to answer the call.`, title: "Incoming call", color: "cyan", - autoClose: 10000, + autoClose: 5000, }); setCallStatusWrapper(CALL_STATUS.INCOMING); + + // set otherUser to the user who is calling + // user id is the peer id + return; } @@ -142,6 +155,7 @@ export default function VideoChatWidget({ onEndCall(); }); }); + peerInstance.current = peer; } useEffect(() => { @@ -154,12 +168,13 @@ export default function VideoChatWidget({ const call = async () => { if (!peerInstance.current) init(); // remote peer id is the user id - if (callStatusRef.current === CALL_STATUS.IDLE) { - setCallStatusWrapper(CALL_STATUS.CALLING); - } + // if (callStatusRef.current === CALL_STATUS.IDLE) { + setCallStatusWrapper(CALL_STATUS.CALLING); + // } // call will fail if the other user is not ready to receive the call - const remotePeerId = `${roomId}-${otherUser?.userId}`; + const remotePeerId = + remotePeerIdFromCall || `${roomId}-${otherUser?.userId}`; console.log("DEBUG: calling", remotePeerId); console.log("DEBUG: READY TO CALL"); @@ -186,11 +201,26 @@ export default function VideoChatWidget({ console.log("DEBUG: call closed in caller"); onEndCall(); }); + + const conn = peerInstance.current.connect(remotePeerId); + + // When the connection is open, send a message + conn.on("open", () => { + console.log("DEBUG: connection open"); + + conn.send("Hello, Peer!"); + peerInstance.current.on("close", () => { + console.log("DEBUG: peer connection closed"); + // when the peer connection is closed, tell the other + conn.send({ callStatus: "ended" }); + }); + }); }; function onEndCall() { // cleanup setCallStatusWrapper(CALL_STATUS.IDLE); + if (selfVideoRef.current) selfVideoRef.current.srcObject = null; if (remoteVideoRef.current) remoteVideoRef.current.srcObject = null; @@ -270,6 +300,7 @@ export default function VideoChatWidget({ useEffect(() => { setDomReady(true); }, []); + if (!otherUser && !remotePeerIdFromCall) return null; return ( diff --git a/peer-prep/src/components/TestCases/TestCasesWrapper.tsx b/peer-prep/src/components/TestCases/TestCasesWrapper.tsx index a697fa8e0a..8da57a1395 100644 --- a/peer-prep/src/components/TestCases/TestCasesWrapper.tsx +++ b/peer-prep/src/components/TestCases/TestCasesWrapper.tsx @@ -125,8 +125,6 @@ export default function TestCasesWrapper({ attemptRef.current = attemptRef.current + 1; } - console.log(attemptCodeMap, "asdnashjkdhbj"); - const onMessage = (event: MessageEvent) => { console.log("LOG: event source on message"); console.log(event); @@ -316,7 +314,6 @@ export default function TestCasesWrapper({ return "red"; } } - console.log({ colorScheme }); return ( diff --git a/peer-prep/src/pages/Session/SessionPage/SessionPage.tsx b/peer-prep/src/pages/Session/SessionPage/SessionPage.tsx index 852306eeac..09d1057864 100644 --- a/peer-prep/src/pages/Session/SessionPage/SessionPage.tsx +++ b/peer-prep/src/pages/Session/SessionPage/SessionPage.tsx @@ -116,7 +116,6 @@ export default function SessionPage() { roomIdReceived: string; otherUserIdReceived: string; } = location.state || {}; - console.log({ questionReceived }); const question = questionReceived || dummyQuestion; const roomId = useParams().roomId; @@ -149,9 +148,7 @@ export default function SessionPage() { // when true, don't show modal when # users in room < 2 // const [isWaitingForRejoin, setIsWaitingForRejoin] = useState(false); const isWaitingForRejoinRef = useRef(false); - console.log("LOG: in session page, latestAttempt = ", { - latestResultsRef: latestResultsRef.current, - }); + // don't need to rerender! const currentValueRef = useRef(""); const peopleInRoomFromCollabServiceRef = useRef(0); From e612a8a7ca702a82cc1f8ec4b546d196186bbaf5 Mon Sep 17 00:00:00 2001 From: hollag Date: Thu, 14 Nov 2024 00:56:19 +0800 Subject: [PATCH 2/3] wip: video call --- .../Communication/Video/VideoChatWidget.tsx | 33 ++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/peer-prep/src/components/Communication/Video/VideoChatWidget.tsx b/peer-prep/src/components/Communication/Video/VideoChatWidget.tsx index c941cf5a2b..780493153e 100644 --- a/peer-prep/src/components/Communication/Video/VideoChatWidget.tsx +++ b/peer-prep/src/components/Communication/Video/VideoChatWidget.tsx @@ -84,9 +84,11 @@ export default function VideoChatWidget({ // only when this is populated are we ready to make a call (connection wise) const [remotePeerIdValue, setRemotePeerIdValue] = useState(""); - const peerInstance = useRef(null); + const peerInstance = useRef(null); const mediaConnection = useRef(null); + const [localStream, setLocalStream] = useState(null); + const remoteStreamRef = useRef(null); function init() { console.log("DEBUG: auth.user", auth.user); if (!auth.user) { @@ -139,6 +141,8 @@ export default function VideoChatWidget({ audio: true, }); + setLocalStream(stream); + selfVideoRef.current.srcObject = stream; selfVideoRef.current.play(); selfVideoRef.current.muted = true; @@ -152,6 +156,7 @@ export default function VideoChatWidget({ call.on("close", () => { console.log("DEBUG: call closed in receiver"); + onEndCall(); }); }); @@ -184,6 +189,10 @@ export default function VideoChatWidget({ audio: true, }); + console.log("DEBUG: stream", stream); + setLocalStream(stream); + console.log("DEBUG: local stream", localStream); + selfVideoRef.current.srcObject = stream; selfVideoRef.current.play(); selfVideoRef.current.muted = true; @@ -199,6 +208,14 @@ export default function VideoChatWidget({ call.on("close", () => { console.log("DEBUG: call closed in caller"); + console.log("DEBUG: ", { + localStream: call.localStream, + remoteStream: call.remoteStream, + call, + mediaConnection: mediaConnection.current, + }); + call.localStream?.getTracks().forEach((track) => track.stop()); + call.remoteStream?.getTracks().forEach((track) => track.stop()); onEndCall(); }); @@ -218,6 +235,20 @@ export default function VideoChatWidget({ }; function onEndCall() { + // console.log("DEBUG: call end function"); + // console.log("DEBUG: ", { + // mediaConnection: mediaConnection.current, + // localStream, + // }); + + // console.log("DEBUG: localstream.getracks", localStream?.getTracks()); + + // stop use of webcam + localStream?.getTracks().forEach((t) => (t.enabled = false)); + localStream?.getTracks().forEach((track) => track.stop()); + + setLocalStream(null); + // cleanup setCallStatusWrapper(CALL_STATUS.IDLE); From 4cd0bef771fc0ec0e3e518a78c27e1c310e4d20a Mon Sep 17 00:00:00 2001 From: hollag Date: Thu, 14 Nov 2024 01:11:49 +0800 Subject: [PATCH 3/3] fix: disable test case running for database questions --- .../components/TestCases/TestCasesWrapper.tsx | 43 ++++++++++++++----- .../pages/Session/SessionPage/SessionPage.tsx | 4 +- 2 files changed, 34 insertions(+), 13 deletions(-) diff --git a/peer-prep/src/components/TestCases/TestCasesWrapper.tsx b/peer-prep/src/components/TestCases/TestCasesWrapper.tsx index 8da57a1395..b2ca5627b2 100644 --- a/peer-prep/src/components/TestCases/TestCasesWrapper.tsx +++ b/peer-prep/src/components/TestCases/TestCasesWrapper.tsx @@ -16,6 +16,7 @@ import { Space, Text, Title, + Tooltip, useMantineColorScheme, } from "@mantine/core"; import classes from "./TestCasesWrapper.module.css"; @@ -43,9 +44,7 @@ import ReactMarkdown from "react-markdown"; import { useAi } from "../../hooks/useAi"; type TestCasesWrapperProps = { - testCases: TestCase[]; // array of test cases channelId: string | null; - questionId: string | null; // to decide if we want to pass down a function from parent instead of passing down solutioncode // runAllTestCases: () => void; @@ -57,7 +56,8 @@ type TestCasesWrapperProps = { latestResultsRef: React.MutableRefObject; roomId: string; - question: string; + + question: Question; }; const STATUS_PARTIAL = 206; @@ -65,11 +65,12 @@ const STATUS_COMPLETE = 200; const STATUS_CONNECTED = 201; const STATUS_STARTED = 202; +const BLOCKED_CATEGORY_IDS = [2]; + export default function TestCasesWrapper({ - testCases, channelId, // runAllTestCases, - questionId, + currentValueRef, userId, @@ -78,8 +79,17 @@ export default function TestCasesWrapper({ latestResultsRef, roomId, + question, }: TestCasesWrapperProps) { + const questionString = question.description.descriptionText; + const questionId = question._id; + const testCases = question.testCases; + + const isBlockedFromRunningTestCase = question.categoriesId.some((id) => + BLOCKED_CATEGORY_IDS.includes(id) + ); + const [latestResults, setLatestResults] = useState([]); const [currentTestCase, setCurrentTestCase] = useState( @@ -325,10 +335,23 @@ export default function TestCasesWrapper({ > Test Cases ({testCases.length}) - + + + <> {/* <> diff --git a/peer-prep/src/pages/Session/SessionPage/SessionPage.tsx b/peer-prep/src/pages/Session/SessionPage/SessionPage.tsx index 09d1057864..de8efc8103 100644 --- a/peer-prep/src/pages/Session/SessionPage/SessionPage.tsx +++ b/peer-prep/src/pages/Session/SessionPage/SessionPage.tsx @@ -686,15 +686,13 @@ export default function SessionPage() {