From ffaf0fc7d55e98def5eb28d17e22beedffd0a5ac Mon Sep 17 00:00:00 2001 From: Subha12125 Date: Mon, 25 May 2026 15:21:02 +0530 Subject: [PATCH] fix(#98): Remove redundant event listeners, duplicate JSX wrappers, and consolidate isMobile state - Eliminated duplicate state declarations (isMobile, containerRef, previewRef) - Removed duplicate useEffect hooks for resize and drag event listeners - Consolidated drag handlers (handleDragStart, handleDragMove, handleDragEnd) - Fixed splitRatio layout logic to properly use unified isMobile state - Restored missing handleFullscreenToggle function for fullscreen API - Fixed mobile layout padding (56px bottom) for bottom navigation - Resolved React state conflicts causing layout breakage on mobile This fixes the layout flickering and event listener leaks reported in #98. --- app/page.tsx | 135 +++++++++------------------------------------- package-lock.json | 10 ++++ 2 files changed, 35 insertions(+), 110 deletions(-) diff --git a/app/page.tsx b/app/page.tsx index 0cffb45..9ca1590 100644 --- a/app/page.tsx +++ b/app/page.tsx @@ -185,109 +185,10 @@ export default function CodeEditor() { const [autoRun, setAutoRun] = useState(true) const [splitRatio, setSplitRatio] = useState(50) const [isResizing, setIsResizing] = useState(false) - - - // use effect for handling full screen mode - useEffect(() => { - const handleFullscreenChange = () => { - setIsFullscreen(Boolean(document.fullscreenElement)); - }; - - document.addEventListener("fullscreenchange", handleFullscreenChange); - return () => { - document.removeEventListener("fullscreenchange", handleFullscreenChange); - }; - }, []); - - const handleFullscreenToggle = async () => { - try { - if (document.fullscreenElement) { - if (document.exitFullscreen) { - await document.exitFullscreen(); - } - return; - } - - if (isFullscreen) { - setIsFullscreen(false); - return; - } - - if (containerRef.current?.requestFullscreen) { - await containerRef.current.requestFullscreen(); - return; - } - - setIsFullscreen(true); - } catch (err) { - console.error("Error attempting to toggle fullscreen:", err); - setIsFullscreen((prev) => !prev); - } - }; - -const containerRef = useRef(null) -const previewRef = useRef(null) -const [isMobile, setIsMobile] = useState(false) - -useEffect(() => { - const updateIsMobile = () => { - setIsMobile(window.innerWidth < 768) - } - - updateIsMobile() - window.addEventListener("resize", updateIsMobile) - - return () => { - window.removeEventListener("resize", updateIsMobile) - } -}, []) - -const handleDragStart = () => { - isDragging.current = true; - setIsResizing(true); - document.body.style.userSelect = "none"; -}; - -const handleDragMove = useCallback((clientX: number, clientY: number) => { - if (!isDragging.current || !containerRef.current) return; - - const rect = containerRef.current.getBoundingClientRect(); - - let newRatio; - if (isMobile) { - newRatio = ((clientY - rect.top) / rect.height) * 100; - } else { - newRatio = ((clientX - rect.left) / rect.width) * 100; - } - - const clampedRatio = Math.max(20, Math.min(80, newRatio)); - setSplitRatio(clampedRatio); -}, [isMobile]); - -const handleMouseMove = useCallback((e: globalThis.MouseEvent) => { - handleDragMove(e.clientX, e.clientY); -}, [handleDragMove]); - -const handleTouchMove = useCallback((e: globalThis.TouchEvent) => { - if (isDragging.current) { - handleDragMove(e.touches[0].clientX, e.touches[0].clientY); - } -}, [handleDragMove]); - -const handleDragEnd = useCallback(() => { - isDragging.current = false; - setIsResizing(false); - document.body.style.userSelect = "auto"; - document.body.style.cursor = "default"; -}, []); - - // Tracks which template is currently active - const [isMobile, setIsMobile] = useState(false) const [consoleErrors, setConsoleErrors] = useState>([]) const [consoleOpen, setConsoleOpen] = useState(false) const [moreSheetOpen, setMoreSheetOpen] = useState(false) - const [currentTemplateId, setCurrentTemplateId] = useState(null) const [templateSnapshots, setTemplateSnapshots] = useState>(() => { if (typeof window === "undefined") return {} @@ -378,6 +279,18 @@ const handleDragEnd = useCallback(() => { } } + const handleFullscreenToggle = async () => { + try { + if (document.fullscreenElement) { + if (document.exitFullscreen) await document.exitFullscreen() + } else if (containerRef.current?.requestFullscreen) { + await containerRef.current.requestFullscreen() + } + } catch (err) { + console.error("Error toggling fullscreen:", err) + } + } + const handleDragStart = useCallback(() => { isDragging.current = true setIsResizing(true) @@ -607,7 +520,7 @@ if (layout === "preview") setLayout("split") id: "action-fullscreen", label: isFullscreen ? "Exit fullscreen" : "Enter fullscreen", group: "Actions", icon: isFullscreen ? : , keywords: "expand maximize zoom", - perform: () => setIsFullscreen((v) => !v), + perform: handleFullscreenToggle, }, { id: "action-theme", label: theme === "light" ? "Switch to dark mode" : "Switch to light mode", group: "Actions", @@ -666,7 +579,7 @@ if (layout === "preview") setLayout("split") { label: "Import file", icon: , action: importCode }, { label: "Share link", icon: , action: copyShareLink }, { label: "Open in tab", icon: , action: () => { if (previewRef.current?.src) window.open(previewRef.current.src, "_blank") } }, - { label: isFullscreen ? "Exit fullscreen" : "Fullscreen", icon: isFullscreen ? : , action: () => { setIsFullscreen(v => !v); setMoreSheetOpen(false) } }, + { label: isFullscreen ? "Exit fullscreen" : "Fullscreen", icon: isFullscreen ? : , action: handleFullscreenToggle }, { label: "Command palette", icon: , action: () => { setMoreSheetOpen(false); setPaletteOpen(true) } }, { label: theme === "light" ? "Dark mode" : "Light mode", icon: theme === "light" ? : , action: () => { toggleTheme(); setMoreSheetOpen(false) } }, ].map((item) => ( @@ -736,7 +649,7 @@ if (layout === "preview") setLayout("split") -