diff --git a/frontend/app/explore-rooms/explore-rooms.tsx b/frontend/app/explore-rooms/explore-rooms.tsx
new file mode 100644
index 00000000..37f35396
--- /dev/null
+++ b/frontend/app/explore-rooms/explore-rooms.tsx
@@ -0,0 +1,33 @@
+"use client";
+
+import RoomCard from "./room-card";
+import { useCallback, useEffect } from "react";
+import { useRouter } from "next/navigation";
+import { DeleteRoomEvent, RoomEntity } from "@/app/lib/dtos";
+import { chatSocket as socket } from "@/socket";
+
+export function ExploreRooms({ rooms }: { rooms: RoomEntity[] }) {
+ const router = useRouter();
+ const handleDeleteRoomEvent = useCallback(
+ (data: DeleteRoomEvent) => {
+ router.refresh();
+ },
+ [router],
+ );
+ useEffect(() => {
+ socket.on("delete-room", handleDeleteRoomEvent);
+ return () => {
+ socket.off("delete-room", handleDeleteRoomEvent);
+ };
+ }, [handleDeleteRoomEvent]);
+ return (
+
+
Explore Rooms
+
+ {rooms.map((room) => (
+
+ ))}
+
+
+ );
+}
diff --git a/frontend/app/explore-rooms/page.tsx b/frontend/app/explore-rooms/page.tsx
index f6dcc1d4..8dadd5b9 100644
--- a/frontend/app/explore-rooms/page.tsx
+++ b/frontend/app/explore-rooms/page.tsx
@@ -1,16 +1,11 @@
import { getRooms } from "@/app/lib/actions";
-import RoomCard from "./room-card";
+import { ExploreRooms } from "./explore-rooms";
export default async function ExploreRoomsPage() {
const rooms = await getRooms({ joined: false });
return (
-
-
Explore Rooms
-
- {rooms.map((room) => (
-
- ))}
-
-
+ <>
+
+ >
);
}
diff --git a/frontend/app/lib/client-socket-provider.tsx b/frontend/app/lib/client-socket-provider.tsx
index 44243e22..4166a55e 100644
--- a/frontend/app/lib/client-socket-provider.tsx
+++ b/frontend/app/lib/client-socket-provider.tsx
@@ -7,10 +7,7 @@ import { useCallback, useEffect } from "react";
import { useAuthContext } from "./client-auth";
import {
DenyEvent,
- DeleteRoomEvent,
- EnterRoomEvent,
InviteEvent,
- LeaveRoomEvent,
MatchEvent,
MessageEvent,
PublicUserEntity,
@@ -32,56 +29,6 @@ export default function SocketProvider() {
});
};
- const handleDeleteRoomEvent = useCallback(
- (data: DeleteRoomEvent) => {
- if (pathName === "/room/" + data.roomId.toString()) {
- showDeleteRoomNotificationToast();
- router.push("/room");
- router.refresh();
- } else if (
- pathName.startsWith("/room/") ||
- pathName === "/explore-rooms"
- ) {
- router.refresh();
- }
- },
- [pathName, router],
- );
-
- const handleEnterRoomEvent = useCallback(
- (data: EnterRoomEvent) => {
- if (pathName === "/room/" + data.roomId.toString()) {
- router.refresh();
- } else if (
- (pathName.startsWith("/room/") || pathName === "/room") &&
- currentUser?.id === data.userId
- ) {
- router.refresh();
- }
- },
- [currentUser, pathName, router],
- );
-
- const handleLeaveRoomEvent = useCallback(
- (data: LeaveRoomEvent) => {
- if (
- pathName === "/room/" + data.roomId.toString() &&
- data.userId === currentUser?.id
- ) {
- router.push("/room");
- router.refresh();
- } else if (pathName === "/room/" + data.roomId.toString()) {
- router.refresh();
- } else if (
- (pathName.startsWith("/room/") || pathName === "/room") &&
- currentUser?.id === data.userId
- ) {
- router.refresh();
- }
- },
- [currentUser, pathName, router],
- );
-
const MatchPong = (data: MatchEvent) => {
router.push(`/pong/${data.roomId}?mode=player`);
};
@@ -168,13 +115,10 @@ export default function SocketProvider() {
const handler = (event: string, data: any) => {
if (event === "message") {
showMessageToast(data);
- } else if (event === "delete-room") {
- handleDeleteRoomEvent(data);
- } else if (event === "enter-room") {
- handleEnterRoomEvent(data);
- } else if (event === "leave") {
- handleLeaveRoomEvent(data);
} else if (
+ event === "delete-room" ||
+ event === "enter-room" ||
+ event === "leave" ||
event === "mute" ||
event === "unmute" ||
event === "update-role"
@@ -202,12 +146,6 @@ export default function SocketProvider() {
chatSocket.offAny(handler);
chatSocket.disconnect();
};
- }, [
- currentUser,
- handleDeleteRoomEvent,
- handleEnterRoomEvent,
- handleLeaveRoomEvent,
- toast,
- ]);
+ }, [currentUser, toast]);
return <>>;
}
diff --git a/frontend/app/lib/hooks/useKick.ts b/frontend/app/lib/hooks/useKick.ts
index 5c22abbc..edd9e519 100644
--- a/frontend/app/lib/hooks/useKick.ts
+++ b/frontend/app/lib/hooks/useKick.ts
@@ -1,11 +1,12 @@
"use client";
import { kickUserOnRoom } from "@/app/lib/actions";
-import type { UserOnRoomEntity } from "@/app/lib/dtos";
+import type { LeaveRoomEvent, UserOnRoomEntity } from "@/app/lib/dtos";
import { toast } from "@/components/ui/use-toast";
-import { useCallback, useState } from "react";
+import { useCallback, useEffect, useState } from "react";
import { useRouter } from "next/navigation";
import { chatSocket as socket } from "@/socket";
+import { usePathname } from "next/navigation";
const showKickErrorToast = () => {
toast({
@@ -14,9 +15,37 @@ const showKickErrorToast = () => {
});
};
-export function useKick(roomId: number, userId: number) {
+export function useKick(roomId: number, userId: number, meId: number) {
const router = useRouter();
const [kickPending, setKickPending] = useState(false);
+ const pathName = usePathname();
+
+ const handleLeaveRoomEvent = useCallback(
+ (data: LeaveRoomEvent) => {
+ if (
+ pathName === "/room/" + data.roomId.toString() &&
+ data.userId === meId
+ ) {
+ router.push("/room");
+ router.refresh();
+ } else if (pathName === "/room/" + data.roomId.toString()) {
+ router.refresh();
+ } else if (
+ (pathName.startsWith("/room/") || pathName === "/room") &&
+ meId === data.userId
+ ) {
+ router.refresh();
+ }
+ },
+ [meId, pathName, router],
+ );
+
+ useEffect(() => {
+ socket.on("leave", handleLeaveRoomEvent);
+ return () => {
+ socket.off("leave", handleLeaveRoomEvent);
+ };
+ }, [handleLeaveRoomEvent]);
const kick = useCallback(async () => {
setKickPending(true);
diff --git a/frontend/app/room/[id]/sidebar-item.tsx b/frontend/app/room/[id]/sidebar-item.tsx
index 5177c83a..36d62963 100644
--- a/frontend/app/room/[id]/sidebar-item.tsx
+++ b/frontend/app/room/[id]/sidebar-item.tsx
@@ -1,6 +1,8 @@
"use client";
import type {
+ DeleteRoomEvent,
+ EnterRoomEvent,
PublicUserEntity,
RoomEntity,
UserOnRoomEntity,
@@ -13,6 +15,7 @@ import {
ContextMenuSeparator,
ContextMenuTrigger,
} from "@/components/ui/context-menu";
+import { useCallback, useEffect } from "react";
import { useRouter } from "next/navigation";
import { useBlock } from "@/app/lib/hooks/useBlock";
import { useInviteToGame } from "@/app/lib/hooks/useInviteToGame";
@@ -20,6 +23,7 @@ import { useKick } from "@/app/lib/hooks/useKick";
import { useMute } from "@/app/lib/hooks/useMute";
import { useUpdateRole } from "@/app/lib/hooks/useUpdateRole";
import MuteMenu from "./mute-menu";
+import { chatSocket as socket } from "@/socket";
function truncateString(str: string | undefined, num: number): string {
if (!str) {
@@ -51,7 +55,7 @@ export default function SidebarItem({
);
const { invitePending, isInvitingToGame, inviteToGame, cancelInviteToGame } =
useInviteToGame(user.userId);
- const { kickPending, kick } = useKick(room.id, user.userId);
+ const { kickPending, kick } = useKick(room.id, user.userId, me.userId);
const { mutePending, isMuted, mute, unmute } = useMute(
room.id,
user.userId,
@@ -73,6 +77,35 @@ export default function SidebarItem({
router.push(`/user/${user.userId}`);
}
};
+ const handleEnterRoomEvent = useCallback(
+ (data: EnterRoomEvent) => {
+ if (room.id === data.roomId) {
+ router.refresh();
+ }
+ },
+ [router, room.id],
+ );
+ const handleDeleteRoomEvent = useCallback(
+ (data: DeleteRoomEvent) => {
+ if (room.id === data.roomId) {
+ router.push("/room");
+ router.refresh();
+ } else {
+ router.refresh();
+ }
+ },
+ [room.id, router],
+ );
+
+ useEffect(() => {
+ socket.on("enter-room", handleEnterRoomEvent);
+ socket.on("delete-room", handleDeleteRoomEvent);
+ return () => {
+ socket.off("enter-room", handleEnterRoomEvent);
+ socket.off("delete-room", handleDeleteRoomEvent);
+ };
+ }, [handleEnterRoomEvent, handleDeleteRoomEvent]);
+
return (
<>
diff --git a/frontend/app/room/rooms-sidebar.tsx b/frontend/app/room/rooms-sidebar.tsx
index 0cccc078..be78908a 100644
--- a/frontend/app/room/rooms-sidebar.tsx
+++ b/frontend/app/room/rooms-sidebar.tsx
@@ -1,9 +1,12 @@
"use client";
-import type { RoomEntity } from "@/app/lib/dtos";
+import type { EnterRoomEvent, RoomEntity } from "@/app/lib/dtos";
import { Stack } from "@/components/layout/stack";
import Link from "next/link";
+import { useCallback, useEffect } from "react";
import { usePathname, useRouter } from "next/navigation";
import CreateRoomDialog from "./create-room-dialog";
+import { useAuthContext } from "@/app/lib/client-auth";
+import { chatSocket as socket } from "@/socket";
function RoomButton({
room,
@@ -42,10 +45,28 @@ function ExploreButton() {
export default function RoomsSidebar({ rooms }: { rooms: RoomEntity[] }) {
const pathname = usePathname();
+ const { currentUser } = useAuthContext();
+ const router = useRouter();
let selectedRoomId: number | undefined;
if (pathname.startsWith("/room/")) {
selectedRoomId = parseInt(pathname.split("/")[2], 10);
}
+
+ const handleEnterRoomEvent = useCallback(
+ (data: EnterRoomEvent) => {
+ if (currentUser?.id === data.userId) {
+ router.refresh();
+ }
+ },
+ [currentUser, router],
+ );
+ useEffect(() => {
+ socket.on("enter-room", handleEnterRoomEvent);
+ return () => {
+ socket.off("enter-room", handleEnterRoomEvent);
+ };
+ }, [handleEnterRoomEvent]);
+
return (