From f51fac6afd0c7e7ec2d5128d8b917478a23de62b Mon Sep 17 00:00:00 2001 From: Arkaprabha Chakraborty Date: Thu, 30 Oct 2025 21:32:09 +0530 Subject: [PATCH] style again --- client/app/api/socket/route.ts | 53 ++++------- client/app/room/page.tsx | 156 +++++++++++++++++++++++++++---- client/components/LeftPanel.tsx | 103 ++++++++++++++++---- client/components/RightPanel.tsx | 2 +- 4 files changed, 240 insertions(+), 74 deletions(-) diff --git a/client/app/api/socket/route.ts b/client/app/api/socket/route.ts index dc8ecf6..d4143c2 100644 --- a/client/app/api/socket/route.ts +++ b/client/app/api/socket/route.ts @@ -1,38 +1,17 @@ -import { NextRequest } from "next/server"; -import { WebSocketServer } from "ws"; - -interface ExtendedNextRequest extends NextRequest { - socket: { - server: { - wss?: WebSocketServer; - }; - on: (event: string, listener: (...args: any[]) => void) => void; - }; -} - -export async function GET(req: ExtendedNextRequest) { - const { socket } = req; - - if (!socket?.server?.wss) { - const wss = new WebSocketServer({ noServer: true }); - socket.server.wss = wss; - - wss.on("connection", (ws) => { - ws.on("message", (message) => { - wss.clients.forEach((client) => { - if (client.readyState === client.OPEN) { - client.send(message.toString()); - } - }); - }); - }); - - socket.on("upgrade", (request: any, socket: any, head: any) => { - wss.handleUpgrade(request, socket, head, (ws) => { - wss.emit("connection", ws, request); - }); - }); - } - - return new Response("WebSocket setup complete"); +export async function GET() { + // In App Router, WebSocket connections should be handled differently + // This endpoint is mainly for checking WebSocket server availability + // The actual WebSocket server is running separately on the Go backend + + const wsUrl = process.env.NEXT_PUBLIC_WS_URL || "ws://localhost:8100/o/socket"; + + return new Response(JSON.stringify({ + message: "WebSocket endpoint available", + wsUrl: wsUrl, + timestamp: new Date().toISOString() + }), { + headers: { + "Content-Type": "application/json", + }, + }); } diff --git a/client/app/room/page.tsx b/client/app/room/page.tsx index f828ff5..9f30421 100644 --- a/client/app/room/page.tsx +++ b/client/app/room/page.tsx @@ -219,7 +219,73 @@ const Room = () => { const [windowWidth, setWindowWidth] = useState(0); const [leftPanelForced, setLeftPanelForced] = useState(false); const [rightPanelForced, setRightPanelForced] = useState(false); - const [popupMessage, setPopupMessage] = useState(null); + const [popupMessage, setPopupMessage] = useState<{text: string; type?: 'default' | 'warning'} | null>(null); + const [isMobile, setIsMobile] = useState(false); + + // Detect mobile screen size + useEffect(() => { + const checkMobile = () => { + setIsMobile(window.innerWidth < 768); // md breakpoint + }; + + checkMobile(); + window.addEventListener('resize', checkMobile); + + return () => window.removeEventListener('resize', checkMobile); + }, []); + + // Mobile swipe gesture handling + useEffect(() => { + if (!isMobile) return; + + let touchStartX = 0; + let touchStartY = 0; + let touchStartTime = 0; + + const handleTouchStart = (e: TouchEvent) => { + const touch = e.touches[0]; + touchStartX = touch.clientX; + touchStartY = touch.clientY; + touchStartTime = Date.now(); + }; + + const handleTouchEnd = (e: TouchEvent) => { + const touch = e.changedTouches[0]; + const touchEndX = touch.clientX; + const touchEndY = touch.clientY; + const touchEndTime = Date.now(); + + const deltaX = touchEndX - touchStartX; + const deltaY = touchEndY - touchStartY; + const deltaTime = touchEndTime - touchStartTime; + + // Only consider it a swipe if: + // 1. The gesture is fast enough (less than 500ms) + // 2. The horizontal distance is significant (at least 100px) + // 3. The vertical distance is less than horizontal (to avoid conflicting with scrolling) + if ( + deltaTime < 500 && + Math.abs(deltaX) > 100 && + Math.abs(deltaX) > Math.abs(deltaY) + ) { + if (deltaX < 0 && leftPanelForced) { + // Swipe left - close left panel + setLeftPanelForced(false); + } else if (deltaX > 0 && rightPanelForced) { + // Swipe right - close right panel + setRightPanelForced(false); + } + } + }; + + document.addEventListener('touchstart', handleTouchStart, { passive: true }); + document.addEventListener('touchend', handleTouchEnd, { passive: true }); + + return () => { + document.removeEventListener('touchstart', handleTouchStart); + document.removeEventListener('touchend', handleTouchEnd); + }; + }, [isMobile, leftPanelForced, rightPanelForced]); const contentRef = useRef(content); @@ -593,11 +659,19 @@ const Room = () => { const handleFileUpload = async (files: FileList) => { if (!files || files.length === 0 || !currentUser) return; + const maxFileSize = 10 * 1024 * 1024; // 10MB in bytes const httpUrl = process.env.NEXT_PUBLIC_HTTP_URL || "http://localhost:8081"; for (let i = 0; i < files.length; i++) { const file = files[i]; + // Check file size limit + if (file.size > maxFileSize) { + const fileSizeInMB = (file.size / (1024 * 1024)).toFixed(2); + showPopup(`File "${file.name}" (${fileSizeInMB}MB) exceeds 10MB limit`, 'warning'); + continue; // Skip this file and continue with others + } + try { // Create form data for file upload const formData = new FormData(); @@ -651,8 +725,8 @@ const Room = () => { } }; - const showPopup = (message: string) => { - setPopupMessage(message); + const showPopup = (message: string, type: 'default' | 'warning' = 'default') => { + setPopupMessage({text: message, type}); setTimeout(() => setPopupMessage(null), 2000); }; @@ -668,8 +742,8 @@ const Room = () => {
{ {getThemeById(currentThemeId)?.name || "Switch theme"} + + {/* Mobile Panel Controls */} + {isMobile && ( + <> + + + + + + toggle users & media panel + + + + + + + + toggle comments panel + + + + )}
@@ -770,15 +876,25 @@ const Room = () => { {error}
)} - + {isMobile ? ( +