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 ;
+}