diff --git a/apps/backend/src/server.ts b/apps/backend/src/server.ts index 3acad20..5ca8d0b 100644 --- a/apps/backend/src/server.ts +++ b/apps/backend/src/server.ts @@ -16,6 +16,7 @@ interface Message { time: string; } type SocketTypes = + | 'check-room' | 'create-room' | 'join-room' | 'send-message' @@ -52,6 +53,10 @@ wss.on('connection', (ws: WebSocket) => { const data: WebSocketData = JSON.parse(message); switch (data.type) { + case 'check-room': + const exists = rooms.has(data.roomId!); + ws.send(JSON.stringify({ type: 'room-check-result', exists })); + break; case 'create-room': const roomId = generateRoomId(); rooms.set(roomId, { diff --git a/apps/web/src/app/not-found.tsx b/apps/web/src/app/not-found.tsx new file mode 100644 index 0000000..19301db --- /dev/null +++ b/apps/web/src/app/not-found.tsx @@ -0,0 +1,41 @@ +'use client'; + +import { Button } from '@/components/ui/button'; +import { useRouter } from 'next/navigation'; +import { Home, Search, XCircle } from 'lucide-react'; + +export default function RoomNotFound() { + const router = useRouter(); + + return ( +
+
+
+ +
+ +

404: Page Not Found

+ +

+ The page or room doesn't exist. It might have been closed or + never existed. +

+ +
+ +
+
+
+ ); +} diff --git a/apps/web/src/app/room/[roomId]/page.tsx b/apps/web/src/app/room/[roomId]/page.tsx index 5b93255..11610b6 100644 --- a/apps/web/src/app/room/[roomId]/page.tsx +++ b/apps/web/src/app/room/[roomId]/page.tsx @@ -8,6 +8,7 @@ import RoomHeader from '@/components/room/header'; import RoomChat from '@/components/room/chat'; import { RoomData, VideoMetadata } from '@/types/room'; import { formatDistanceToNow } from 'date-fns'; +import { useRouter } from 'next/navigation'; interface YouTubePlayer { playVideo: () => void; pauseVideo: () => void; @@ -16,11 +17,6 @@ interface YouTubePlayer { getPlayerState: () => number; } -type VideoEvent = - | { type: 'video-play'; timestamp: number } - | { type: 'video-pause'; timestamp: number } - | { type: 'video-seek'; timestamp: number }; - declare global { interface Window { // eslint-disable-next-line @typescript-eslint/no-explicit-any @@ -29,7 +25,8 @@ declare global { } } -export default function RoomPage() { +export default function ClientPage() { + const router = useRouter(); const params = useParams(); const roomId = params.roomId as string; const { @@ -42,14 +39,12 @@ export default function RoomPage() { syncVideoState, addToPlaylist, subscribeToPlaylistUpdates, - nextVideo, videoEnded, } = useSocket(); const [messages, setMessages] = useState([]); const [participants, setParticipants] = useState(0); const [videoUrl, setVideoUrl] = useState(''); - const [username] = useState(`User-${Math.floor(Math.random() * 1000)}`); const [videoMetadata, setVideoMetadata] = useState({ title: '', creator: '', @@ -86,7 +81,6 @@ export default function RoomPage() { }); } else if (playerState === 0) { videoEnded(roomId); - // nextVideo(roomId); } }, [roomId, syncVideoState, videoEnded] @@ -107,11 +101,12 @@ export default function RoomPage() { } } catch (error) { console.error('Error joining room:', error); + router.push('/room-not-found'); } }; fetchRoomData(); - }, [isConnected, joinRoom, roomId]); + }, [isConnected, joinRoom, roomId, router]); useEffect(() => { if (!isConnected) return; diff --git a/apps/web/src/app/room/[roomId]/server__bla_page.tsx b/apps/web/src/app/room/[roomId]/server__bla_page.tsx new file mode 100644 index 0000000..28810b7 --- /dev/null +++ b/apps/web/src/app/room/[roomId]/server__bla_page.tsx @@ -0,0 +1,55 @@ +import { notFound, redirect } from 'next/navigation'; +import ClientPage from './page'; + +async function checkRoomExists(roomId: string): Promise { + return new Promise((resolve) => { + try { + const ws = new WebSocket(process.env.NEXT_PUBLIC_WEBSOCKET_URL!); + + ws.onopen = () => { + ws.send(JSON.stringify({ type: 'check-room', roomId })); + }; + + ws.onmessage = (event) => { + try { + const response = JSON.parse(event.data); + if (response.type === 'room-check-result') { + ws.close(); + resolve(response.exists); + } + } catch (error) { + console.error('Error parsing response:', error); + ws.close(); + resolve(false); + } + }; + + ws.onerror = () => { + ws.close(); + resolve(false); + }; + + setTimeout(() => { + ws.close(); + resolve(false); + }, 5000); + } catch (error) { + console.error('Error checking room:', error); + resolve(false); + } + }); +} + +export default async function RoomPage({ + params, +}: { + params: { roomId: string }; +}) { + const { roomId } = await params; + const roomExists = await checkRoomExists(roomId); + + if (!roomExists) { + notFound(); + } + return ; +}