Skip to content

Commit 93e8db0

Browse files
committed
fix: resolve dialog and sidebar interaction issues & auto-delete room on last user exit
1 parent 651442a commit 93e8db0

File tree

10 files changed

+165
-68
lines changed

10 files changed

+165
-68
lines changed

apps/collabydraw/components/CollaborationStartBtn.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,12 @@ import { cn } from "@/lib/utils";
1111
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "./ui/tooltip";
1212
import { RoomParticipants } from "@repo/common/types";
1313

14-
export default function CollaborationStartBtn({ slug, participants }: { slug?: string, participants?: RoomParticipants[] }) {
14+
export default function CollaborationStartBtn({ slug, participants, onCloseRoom }: { slug?: string, participants?: RoomParticipants[], onCloseRoom?: () => void; }) {
1515
const pathname = usePathname();
1616
const [isOpen, setIsOpen] = useState(false);
1717
const { data: session } = useSession();
1818
const roomSlug = slug;
19-
const decodedPathname = decodeURIComponent(pathname)
19+
const decodedPathname = decodeURIComponent(pathname);
2020

2121
return (
2222
<div className="Start_Room_Session transition-transform duration-500 ease-in-out flex items-center justify-end">
@@ -42,15 +42,15 @@ export default function CollaborationStartBtn({ slug, participants }: { slug?: s
4242
</TooltipProvider>
4343
</div>
4444
</div>
45-
<Button type="butt yu65tr4e3qson" onClick={() => setIsOpen(true)}
45+
<Button type="button" onClick={() => setIsOpen(true)}
4646
className={cn("excalidraw-button collab-button relative w-auto py-3 px-4 rounded-md text-[.875rem] font-semibold shadow-none active:scale-[.98]", roomSlug ? "bg-[#0fb884] dark:bg-[#0fb884] hover:bg-[#0fb884]" : "bg-color-primary hover:bg-brand-hover active:bg-brand-active")}
4747
title="Live collaboration...">Share {roomSlug && participants && participants.length > 0 && (
4848
<div className="CollabButton-collaborators text-[.6rem] text-[#2b8a3e] bg-[#b2f2bb] font-bold font-assistant rounded-[50%] p-1 min-w-4 min-h-4 w-4 h-4 flex items-center justify-center absolute bottom-[-5px] right-[-5px]">{participants.length}</div>
4949
)}</Button>
5050

5151
{session?.user && session?.user.id ? (
5252
roomSlug ? (
53-
<RoomSharingDialog open={isOpen} onOpenChange={setIsOpen} link={`${process.env.NODE_ENV !== 'production' ? 'http://localhost:3000' : 'https://collabydraw.com'}/${decodedPathname}`} />
53+
<RoomSharingDialog onCloseRoom={onCloseRoom} open={isOpen} onOpenChange={setIsOpen} link={`${process.env.NODE_ENV !== 'production' ? 'http://localhost:3000' : 'https://collabydraw.com'}/${decodedPathname}`} />
5454
) : (
5555
<CollaborationStartdDialog open={isOpen} onOpenChange={setIsOpen} />
5656
)

apps/collabydraw/components/MainMenuStack.tsx

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -44,9 +44,10 @@ interface SidebarProps {
4444
onClearCanvas?: () => void;
4545
onExportCanvas?: () => void;
4646
onImportCanvas?: () => void;
47+
onCloseRoom?: () => void;
4748
}
4849

49-
export function MainMenuStack({ isOpen, onClose, canvasColor, setCanvasColor, isMobile, roomName, isStandalone = false, onClearCanvas, onExportCanvas, onImportCanvas }: SidebarProps) {
50+
export function MainMenuStack({ isOpen, onClose, canvasColor, setCanvasColor, isMobile, roomName, isStandalone, onClearCanvas, onExportCanvas, onImportCanvas, onCloseRoom }: SidebarProps) {
5051
const [clearDialogOpen, setClearDialogOpen] = useState(false);
5152
const { theme, setTheme } = useTheme();
5253
const { data: session } = useSession();
@@ -58,14 +59,19 @@ export function MainMenuStack({ isOpen, onClose, canvasColor, setCanvasColor, is
5859
useEffect(() => {
5960
const handleOutsideClick = (e: MouseEvent) => {
6061
const target = e.target as HTMLElement
61-
if (isOpen && !target.closest("[data-sidebar]") && !target.closest("[data-sidebar-trigger]")) {
62-
onClose()
62+
if (isOpen &&
63+
!clearDialogOpen &&
64+
!isShareOpen &&
65+
!target.closest("[data-sidebar]") &&
66+
!target.closest("[data-sidebar-trigger]")
67+
) {
68+
onClose();
6369
}
6470
}
6571

6672
document.addEventListener("mouseup", handleOutsideClick)
6773
return () => document.removeEventListener("mouseup", handleOutsideClick)
68-
}, [isOpen, onClose])
74+
}, [clearDialogOpen, isOpen, isShareOpen, onClose])
6975

7076
useEffect(() => {
7177
if (isOpen && window.innerWidth < 768) {
@@ -114,7 +120,7 @@ export function MainMenuStack({ isOpen, onClose, canvasColor, setCanvasColor, is
114120
<CopyIcon className="h-4 w-4" />
115121
Room Name: <span>{roomName}</span>
116122
</Button>
117-
<RoomSharingDialog open={isShareOpen} onOpenChange={setIsShareOpen} link={`${process.env.NODE_ENV !== 'production' ? 'http://localhost:3000' : 'https://collabydraw.com'}/${decodedPathname}`} />
123+
<RoomSharingDialog onCloseRoom={onCloseRoom} open={isShareOpen} onOpenChange={setIsShareOpen} link={`${process.env.NODE_ENV !== 'production' ? 'http://localhost:3000' : 'https://collabydraw.com'}/${decodedPathname}`} />
118124
<SidebarItem icon={Share2} label="Share collaboration" onClick={() => setIsShareOpen(true)} />
119125
<SidebarItem icon={Trash} label="Reset the canvas" onClick={() => setClearDialogOpen(true)} />
120126
</>

apps/collabydraw/components/RoomSharingDialog.tsx

Lines changed: 14 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,9 @@ import { Button } from "./ui/button";
44
import { Copy, X } from "lucide-react";
55
import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogFooter } from "./ui/dialog";
66
import { toast } from "sonner";
7-
import { deleteRoom } from "@/actions/room";
8-
import { useRouter } from "next/navigation";
9-
import { useTransition } from "react";
107

11-
export function RoomSharingDialog({ open, onOpenChange, link }: { open: boolean, onOpenChange: (open: boolean) => void, link: string }) {
8+
export function RoomSharingDialog({ open, onOpenChange, link, onCloseRoom }: { open: boolean, onOpenChange: (open: boolean) => void, link: string, onCloseRoom?: () => void; }) {
129
const roomLink = link;
13-
const [isPending, startTransition] = useTransition();
14-
const router = useRouter();
1510

1611
const copyRoomLink = async () => {
1712
try {
@@ -23,34 +18,17 @@ export function RoomSharingDialog({ open, onOpenChange, link }: { open: boolean,
2318
}
2419
};
2520

26-
const stopSession = () => {
27-
startTransition(async () => {
28-
try {
29-
if (!roomLink) {
30-
toast.error("Invalid room link.");
31-
return;
32-
}
21+
const handleStopSession = () => {
22+
console.log('handleStopSession clicked')
23+
const confirmed = window.confirm(
24+
"Stopping the session will overwrite your previous, locally stored drawing. Are you sure?\n\n(If you want to keep your local drawing, simply close the browser tab instead.)"
25+
);
3326

34-
const roomName = roomLink.split('/').pop();
35-
if (!roomName) {
36-
toast.error("Room name is missing from the link.");
37-
return;
38-
}
39-
40-
const response = await deleteRoom({ roomName });
41-
42-
if (response.success) {
43-
toast.success("Room session ended successfully!");
44-
onOpenChange(false);
45-
router.push('/');
46-
} else {
47-
toast.error(response.error || "Failed to delete the room.");
48-
}
49-
} catch (error) {
50-
toast.error('Failed to end session');
51-
console.error('Failed to end session:', error);
52-
}
53-
});
27+
if (confirmed) {
28+
onCloseRoom?.();
29+
// onOpenChange(false);
30+
toast.info('Destryoing session...')
31+
}
5432
};
5533

5634
return (
@@ -62,7 +40,7 @@ export function RoomSharingDialog({ open, onOpenChange, link }: { open: boolean,
6240

6341
<div className="space-y-6">
6442
<div className="text-text-primary-color">
65-
<p className="font-semibold mb-2">Link</p>
43+
<p className="font-semibold mb-2">Linkkkkkkkkkkkkkkkkkkkkk</p>
6644
<div className="flex items-center gap-2">
6745
<div className="flex-1 bg-collaby-textfield border border-collaby-textfield rounded-md px-3 py-2 text-text-primary-color overflow-hidden text-ellipsis">
6846
{roomLink}
@@ -92,12 +70,11 @@ export function RoomSharingDialog({ open, onOpenChange, link }: { open: boolean,
9270

9371
<DialogFooter className="flex items-center justify-center sm:justify-center">
9472
<Button
95-
onClick={stopSession}
73+
onClick={handleStopSession}
9674
className="py-2 px-6 min-h-12 rounded-md text-[.875rem] font-semibold shadow-none bg-red-500 hover:bg-red-600 active:bg-red-700 active:scale-[.98] text-white"
97-
disabled={isPending}
9875
>
9976
<X className="w-5 h-5 mr-2" />
100-
{isPending ? 'Destroying...' : 'Stop session'}
77+
Stop session
10178
</Button>
10279
</DialogFooter>
10380
</DialogContent>

apps/collabydraw/components/UserRoomsListDialog.tsx

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
'use client'
22

33
import { Button } from "./ui/button";
4-
import { LogIn, Trash } from "lucide-react";
4+
import { LogIn, Plus, Trash } from "lucide-react";
55
import { Dialog, DialogContent, DialogHeader, DialogTitle } from "./ui/dialog";
66
import { toast } from "sonner";
77
import { getUserRooms, joinRoom, deleteRoom } from "@/actions/room";
@@ -187,10 +187,18 @@ export function UserRoomsListDialog({
187187
))
188188
) : (
189189
<div className="text-center py-8 text-gray-400">
190-
<p className="mb-4">No rooms found.</p>
191-
<Button type="button" onClick={() => { setIsOpen(true); }}
192-
className="excalidraw-button collab-button relative w-auto py-3 px-4 rounded-md text-[.875rem] font-semibold shadow-none bg-color-primary hover:bg-brand-hover active:bg-brand-active active:scale-[.98]"
193-
title="Live collaboration...">Create a Room</Button>
190+
<h3 className="font-assistant font-semibold text-[0.875rem] indent-[150%] text-collaby-textfield-label mb-1 select-none">No rooms found.</h3>
191+
<Button
192+
type="button"
193+
size={"lg"}
194+
onClick={() => { setIsOpen(true); }}
195+
disabled={isPending}
196+
className="py-2 px-6 min-h-12 rounded-md text-[.875rem] font-semibold shadow-none bg-color-primary hover:bg-brand-hover active:bg-brand-active active:scale-[.98]"
197+
title="Create a Room">
198+
<div className="flex items-center justify-center gap-3 shrink-0 flex-nowrap">
199+
<Plus className="w-5 h-5" />Create a Room
200+
</div>
201+
</Button>
194202
<CollaborationStartdDialog open={isOpen} onOpenChange={setIsOpen} />
195203
</div>
196204
)}

apps/collabydraw/components/canvas/CanvasSheet.tsx

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import CollaborationStart from "../CollaborationStartBtn";
1616
import { cn } from "@/lib/utils";
1717
import { useWebSocket } from "@/hooks/useWebSocket";
1818
import { WS_DATA_TYPE } from "@repo/common/types";
19+
import { useRouter } from "next/navigation";
1920

2021
export default function CanvasSheet({ roomName, roomId, userId, userName, token }: {
2122
roomName: string; roomId: string; userId: string; userName: string; token: string;
@@ -24,6 +25,7 @@ export default function CanvasSheet({ roomName, roomId, userId, userName, token
2425
const [canvasColor, setCanvasColor] = useState<string>(canvasBgLight[0]);
2526
const canvasRef = useRef<HTMLCanvasElement>(null);
2627
const paramsRef = useRef({ roomId, roomName, userId, userName, token });
28+
const router = useRouter();
2729

2830
const [canvasState, setCanvasState] = useState({
2931
game: null as Game | null,
@@ -224,6 +226,18 @@ export default function CanvasSheet({ roomName, roomId, userId, userName, token
224226
canvasColor={canvasColor}
225227
setCanvasColor={setCanvasColor}
226228
roomName={roomName}
229+
onCloseRoom={() => {
230+
console.log("Closing room!");
231+
sendMessage(
232+
JSON.stringify({
233+
type: WS_DATA_TYPE.CLOSE_ROOM,
234+
roomName: paramsRef.current.roomId,
235+
userId: paramsRef.current.userId,
236+
userName: paramsRef.current.userName,
237+
})
238+
);
239+
router.push("/");
240+
}}
227241
/>
228242
)}
229243
</div>
@@ -262,7 +276,20 @@ export default function CanvasSheet({ roomName, roomId, userId, userName, token
262276
/>
263277

264278
{matches && (
265-
<CollaborationStart participants={participants} slug={roomName} />
279+
<CollaborationStart participants={participants} slug={roomName}
280+
onCloseRoom={() => {
281+
console.log("Closing room!");
282+
sendMessage(
283+
JSON.stringify({
284+
type: WS_DATA_TYPE.CLOSE_ROOM,
285+
roomName: paramsRef.current.roomId,
286+
userId: paramsRef.current.userId,
287+
userName: paramsRef.current.userName,
288+
})
289+
);
290+
router.push("/");
291+
}}
292+
/>
266293
)}
267294
</div>
268295

@@ -311,6 +338,18 @@ export default function CanvasSheet({ roomName, roomId, userId, userName, token
311338
setCanvasState(prev => ({ ...prev, strokeStyle: typeof newStrokeStyle === 'function' ? newStrokeStyle(prev.strokeStyle) : newStrokeStyle }))
312339
}
313340
roomName={roomName}
341+
onCloseRoom={() => {
342+
console.log("Closing room!");
343+
sendMessage(
344+
JSON.stringify({
345+
type: WS_DATA_TYPE.CLOSE_ROOM,
346+
roomName: paramsRef.current.roomId,
347+
userId: paramsRef.current.userId,
348+
userName: paramsRef.current.userName,
349+
})
350+
);
351+
router.push("/");
352+
}}
314353
/>
315354

316355
)}

apps/collabydraw/components/mobile-navbar.tsx

Lines changed: 20 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import { PaletteFilled } from "./SvgIcons"
1313
import { ToolMenuStack } from "./ToolMenuStack"
1414
import { BgFill, StrokeEdge, StrokeFill, StrokeStyle, StrokeWidth, ToolType } from "@/types/canvas"
1515
import { UserRoomsListDialog } from "./UserRoomsListDialog"
16+
import { RoomSharingDialog } from "./RoomSharingDialog"
1617

1718
interface MobileNavbarProps {
1819
canvasColor: string
@@ -33,13 +34,12 @@ interface MobileNavbarProps {
3334
setStrokeEdge: React.Dispatch<React.SetStateAction<StrokeEdge>>;
3435
strokeStyle: StrokeStyle;
3536
setStrokeStyle: React.Dispatch<React.SetStateAction<StrokeStyle>>;
36-
3737
roomName?: string
38-
3938
isStandalone?: boolean;
4039
onClearCanvas?: () => void;
4140
onExportCanvas?: () => void;
4241
onImportCanvas?: () => void;
42+
onCloseRoom?: () => void;
4343
}
4444

4545
export function MobileNavbar({ canvasColor,
@@ -63,7 +63,8 @@ export function MobileNavbar({ canvasColor,
6363
isStandalone,
6464
onClearCanvas,
6565
onExportCanvas,
66-
onImportCanvas
66+
onImportCanvas,
67+
onCloseRoom
6768
}: MobileNavbarProps) {
6869
const [colorPickerOpen, setColorPickerOpen] = useState(false);
6970
const [roomsListOpen, setRoomsListOpen] = useState(false);
@@ -130,18 +131,22 @@ export function MobileNavbar({ canvasColor,
130131
</SheetContent>
131132
</Sheet>
132133

133-
<Sheet open={roomsListOpen} onOpenChange={setRoomsListOpen}>
134-
<SheetContent side="bottom" className="h-auto max-h-[80vh] min-h-[50vh] rounded-t-[20px] px-6 py-6 Island">
135-
<SheetHeader className="mb-5">
136-
<SheetTitle>All Your Rooms</SheetTitle>
137-
</SheetHeader>
138-
<UserRoomsListDialog
139-
open={roomsListOpen}
140-
onOpenChange={setRoomsListOpen}
141-
isMobile={true}
142-
/>
143-
</SheetContent>
144-
</Sheet>
134+
{roomName ? (
135+
<RoomSharingDialog onCloseRoom={onCloseRoom} open={roomsListOpen} onOpenChange={setRoomsListOpen} link={`${process.env.NODE_ENV !== 'production' ? 'http://localhost:3000' : 'https://collabydraw.com'}/${roomName}`} />
136+
) : (
137+
<Sheet open={roomsListOpen} onOpenChange={setRoomsListOpen}>
138+
<SheetContent side="bottom" className="h-auto max-h-[80vh] min-h-[50vh] rounded-t-[20px] px-6 py-6 Island">
139+
<SheetHeader className="mb-5">
140+
<SheetTitle>All Your Rooms</SheetTitle>
141+
</SheetHeader>
142+
<UserRoomsListDialog
143+
open={roomsListOpen}
144+
onOpenChange={setRoomsListOpen}
145+
isMobile={true}
146+
/>
147+
</SheetContent>
148+
</Sheet>
149+
)}
145150
</>
146151
)
147152
}

apps/collabydraw/hooks/useWebSocket.tsx

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,7 @@ export function useWebSocket(roomId: string, roomName: string, userId: string, u
138138
}
139139

140140
const parsedContent = JSON.parse(content);
141+
console.log('parsedContent = ', parsedContent)
141142
if (socketRef.current?.readyState === WebSocket.OPEN) {
142143
const basePayload = {
143144
roomName,
@@ -170,6 +171,16 @@ export function useWebSocket(roomId: string, roomName: string, userId: string, u
170171
id: parsedContent.id
171172
}));
172173
break;
174+
175+
case WS_DATA_TYPE.CLOSE_ROOM:
176+
socketRef.current.send(JSON.stringify({
177+
...basePayload,
178+
type: WS_DATA_TYPE.CLOSE_ROOM,
179+
roomId: paramsRef.current.roomId,
180+
userId: paramsRef.current.userId,
181+
userName: paramsRef.current.userName,
182+
}));
183+
break;
173184
}
174185
} else {
175186
console.warn('Cannot send message: WebSocket not connected');

apps/collabydraw/types/canvas.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,7 @@ export enum WS_DATA_TYPE {
172172
ERASER = "ERASER",
173173
UPDATE = "UPDATE",
174174
EXISTING_PARTICIPANTS = "EXISTING_PARTICIPANTS",
175+
CLOSE_ROOM = "CLOSE_ROOM",
175176
}
176177

177178
export type WsMessage = {

0 commit comments

Comments
 (0)