diff --git a/backend/collaboration-service/package.json b/backend/collaboration-service/package.json index 236a9e15cc..0db507e47c 100644 --- a/backend/collaboration-service/package.json +++ b/backend/collaboration-service/package.json @@ -9,7 +9,8 @@ "test": "jest", "lint": "eslint . --fix --no-error-on-unmatched-pattern && prettier --write --ignore-unknown .", "start": "npm run build && node dist/server.js", - "dev": "nodemon src/server.ts" + "dev": "nodemon src/server.ts", + "format": "prettier --write ." }, "license": "MIT", "dependencies": { diff --git a/backend/collaboration-service/src/services/socketio.service.ts b/backend/collaboration-service/src/services/socketio.service.ts index 860b453eda..c58749d098 100644 --- a/backend/collaboration-service/src/services/socketio.service.ts +++ b/backend/collaboration-service/src/services/socketio.service.ts @@ -61,6 +61,19 @@ export class WebSocketConnection { } }) + socket.on('end-session', async () => { + const socketsInRoom = this.io.sockets.adapter.rooms.get(roomId) + if (socketsInRoom) { + socketsInRoom.forEach((socketId) => { + const socket = this.io.sockets.sockets.get(socketId) + if (socket) { + socket.leave(roomId) + socket.disconnect(true) + } + }) + } + }) + socket.on('disconnect', async () => { const room = this.io.sockets.adapter.rooms.get(roomId) socket.leave(roomId) diff --git a/frontend/pages/code/[id]/index.tsx b/frontend/pages/code/[id]/index.tsx index d1895ec0ab..eb9450eb01 100644 --- a/frontend/pages/code/[id]/index.tsx +++ b/frontend/pages/code/[id]/index.tsx @@ -1,3 +1,5 @@ +'use client' + import { EndIcon, PlayIcon } from '@/assets/icons' import { ChatModel, ICollabDto, LanguageMode, getCodeMirrorLanguage } from '@repo/collaboration-types' import { useEffect, useRef, useState } from 'react' @@ -25,6 +27,7 @@ import { ISubmission } from '@repo/submission-types' import { mapLanguageToJudge0 } from '@/util/language-mapper' import TestResult from '../test-result' import { Cross1Icon } from '@radix-ui/react-icons' +import ConfirmDialog from '@/components/customs/confirm-dialog' import { getChatHistory, getCollabHistory } from '@/services/collaboration-service-api' import ReadOnlyCodeMirrorEditor from '../read-only-editor' import { ResultModel } from '@repo/collaboration-types' @@ -49,11 +52,12 @@ export default function Code() { const [isOtherUserOnline, setIsOtherUserOnline] = useState(true) const [isCodeRunning, setIsCodeRunning] = useState(false) const [activeTest, setActiveTest] = useState(0) + const [isViewOnly, setIsViewOnly] = useState(true) + const [isDialogOpen, setIsDialogOpen] = useState(false) const [retry, setRetry] = useState(0) const [testResult, setTestResult] = useState<{ data: ResultModel | undefined; expectedOutput: string } | undefined>( undefined ) - const [isViewOnly, setIsViewOnly] = useState(true) const retrieveMatchDetails = async (matchId: string) => { const response = await getMatchDetails(matchId).catch((err) => { @@ -94,7 +98,6 @@ export default function Code() { }) socketRef.current.on('connect', async () => { - console.log('hi') if (socketRef.current) { socketRef.current.emit('joinRoom', { roomId: id }) setChatData((await getChatHistory(id as string)) ?? []) @@ -130,6 +133,12 @@ export default function Code() { } }) + socketRef.current.on('disconnect', () => { + if (!isViewOnly) { + router.push('/') + } + }) + socketRef.current.on('receive_message', (data: ChatModel) => { setChatData((prev) => [...prev, data]) }) @@ -184,10 +193,18 @@ export default function Code() { router.push('/sessions') return } + + if (socketRef.current) { + setIsDialogOpen(true) + } + } + + function handleEndSessionConfirmation() { if (socketRef.current) { - socketRef.current.disconnect() + socketRef.current?.emit('end-session') + router.push('/') } - router.push('/') + setIsDialogOpen(false) } const renderCloseButton = () => { @@ -292,6 +309,17 @@ export default function Code() { + setIsDialogOpen(false)} + confirmHandler={handleEndSessionConfirmation} + />