diff --git a/src/components/TopBar/index.tsx b/src/components/TopBar/index.tsx index 03e65ce4a..2585c3cdc 100644 --- a/src/components/TopBar/index.tsx +++ b/src/components/TopBar/index.tsx @@ -12,7 +12,7 @@ import { Power, ChevronDown, ChevronLeft, - House, + LayoutGrid, Share, } from "lucide-react"; import "./index.css"; @@ -253,7 +253,7 @@ function HeaderWin() { className="no-drag" onClick={() => navigate("/history")} > - + (null); + const [platform, setPlatform] = useState(""); + + useEffect(() => { + const p = window.electronAPI.getPlatform(); + setPlatform(p); + + if (p === "darwin") { + if (controlsRef.current) { + controlsRef.current.style.display = "none"; + } + } + }, []); + + if (platform === "darwin") { + return null; + } + + return ( + + window.electronAPI.minimizeWindow()} + > + + + window.electronAPI.toggleMaximizeWindow()} + > + + + { + e.stopPropagation(); + e.preventDefault(); + // Trigger window close - this will go through the before-close handler + // which checks if tasks are running and shows confirmation if needed + window.electronAPI.closeWindow(false); + }} + onMouseDown={(e) => { + e.stopPropagation(); + }} + > + + + + ); +} + diff --git a/src/pages/Login.tsx b/src/pages/Login.tsx index aa2c79f7c..3bd0e87f1 100644 --- a/src/pages/Login.tsx +++ b/src/pages/Login.tsx @@ -1,6 +1,6 @@ import { useAuthStore } from "@/store/authStore"; import { useNavigate, useLocation } from "react-router-dom"; -import { useCallback, useEffect, useState } from "react"; +import { useCallback, useEffect, useState, useRef } from "react"; import { useStackApp } from "@stackframe/react"; import loginGif from "@/assets/login.gif"; import { Button } from "@/components/ui/button"; @@ -14,6 +14,7 @@ import eyeOff from "@/assets/eye-off.svg"; import { proxyFetchPost } from "@/api/http"; import { hasStackKeys } from "@/lib"; import { useTranslation } from "react-i18next"; +import WindowControls from "@/components/WindowControls"; const HAS_STACK_KEYS = hasStackKeys(); let lock = false; @@ -34,6 +35,8 @@ export default function Login() { }); const [isLoading, setIsLoading] = useState(false); const [generalError, setGeneralError] = useState(""); + const titlebarRef = useRef(null); + const [platform, setPlatform] = useState(""); const validateEmail = (email: string) => { const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; @@ -211,12 +214,72 @@ export default function Login() { }; }, []); + useEffect(() => { + const p = window.electronAPI.getPlatform(); + setPlatform(p); + + if (platform === "darwin") { + titlebarRef.current?.classList.add("mac"); + } + }, [platform]); + + // Handle before-close event for login page + useEffect(() => { + const handleBeforeClose = () => { + // On login page, always close directly without confirmation + window.electronAPI.closeWindow(true); + }; + + window.ipcRenderer?.on("before-close", handleBeforeClose); + + return () => { + window.ipcRenderer?.off("before-close", handleBeforeClose); + }; + }, []); + return ( - - - + + {/* Titlebar with drag region and window controls */} + + {/* Left spacer for macOS */} + + {platform === "darwin" && Eigent} + + + {/* Center drag region */} + + + + + {/* Right window controls */} + e.stopPropagation()} + onClick={(e) => e.stopPropagation()} + > + + - + + {/* Main content - image extends to top, form has padding */} + + + + + @@ -319,6 +382,7 @@ export default function Login() { > {t("layout.privacy-policy")} + ); diff --git a/utils/__pycache__/__init__.cpython-310.pyc b/utils/__pycache__/__init__.cpython-310.pyc index 10d1d4a69..744ca18d8 100644 Binary files a/utils/__pycache__/__init__.cpython-310.pyc and b/utils/__pycache__/__init__.cpython-310.pyc differ diff --git a/utils/__pycache__/traceroot_wrapper.cpython-310.pyc b/utils/__pycache__/traceroot_wrapper.cpython-310.pyc index d695ee21d..b86cd68b6 100644 Binary files a/utils/__pycache__/traceroot_wrapper.cpython-310.pyc and b/utils/__pycache__/traceroot_wrapper.cpython-310.pyc differ