import React, { useState, useEffect, useCallback, useRef } from "react"; import { LeftSidebar } from "@/ui/desktop/navigation/LeftSidebar.tsx"; import { Dashboard } from "@/ui/desktop/apps/dashboard/Dashboard.tsx"; import { AppView } from "@/ui/desktop/navigation/AppView.tsx"; import { HostManager } from "@/ui/desktop/apps/host-manager/hosts/HostManager.tsx"; import { TabProvider, useTabs, } from "@/ui/desktop/navigation/tabs/TabContext.tsx"; import { TopNavbar } from "@/ui/desktop/navigation/TopNavbar.tsx"; import { CommandHistoryProvider } from "@/ui/desktop/apps/features/terminal/command-history/CommandHistoryContext.tsx"; import { AdminSettings } from "@/ui/desktop/apps/admin/AdminSettings.tsx"; import { UserProfile } from "@/ui/desktop/user/UserProfile.tsx"; import { Toaster } from "@/components/ui/sonner.tsx"; import { CommandPalette } from "@/ui/desktop/apps/command-palette/CommandPalette.tsx"; import { getUserInfo } from "@/ui/main-axios.ts"; import { useTheme } from "@/components/theme-provider"; function AppContent() { const [isAuthenticated, setIsAuthenticated] = useState(false); const [username, setUsername] = useState(null); const [isAdmin, setIsAdmin] = useState(false); const [authLoading, setAuthLoading] = useState(true); const [isTopbarOpen, setIsTopbarOpen] = useState(() => { const saved = localStorage.getItem("topNavbarOpen"); return saved !== null ? JSON.parse(saved) : true; }); const [isTransitioning, setIsTransitioning] = useState(false); const [transitionPhase, setTransitionPhase] = useState< "idle" | "fadeOut" | "fadeIn" >("idle"); const { currentTab, tabs, updateTab } = useTabs(); const [isCommandPaletteOpen, setIsCommandPaletteOpen] = useState(false); const { theme, setTheme } = useTheme(); const [rightSidebarOpen, setRightSidebarOpen] = useState(false); const [rightSidebarWidth, setRightSidebarWidth] = useState(400); const isDarkMode = theme === "dark" || (theme === "system" && window.matchMedia("(prefers-color-scheme: dark)").matches); const lineColor = isDarkMode ? "#151517" : "#f9f9f9"; const lastShiftPressTime = useRef(0); const lastAltPressTime = useRef(0); useEffect(() => { const handleKeyDown = (event: KeyboardEvent) => { if (event.code === "ShiftLeft") { if (event.repeat) { return; } const now = Date.now(); if (now - lastShiftPressTime.current < 300) { setIsCommandPaletteOpen((isOpen) => !isOpen); lastShiftPressTime.current = 0; } else { lastShiftPressTime.current = now; } } if (event.code === "AltLeft" && !event.repeat) { const now = Date.now(); if (now - lastAltPressTime.current < 300) { const currentIsDark = theme === "dark" || (theme === "system" && window.matchMedia("(prefers-color-scheme: dark)").matches); const newTheme = currentIsDark ? "light" : "dark"; setTheme(newTheme); lastAltPressTime.current = 0; } else { lastAltPressTime.current = now; } } if (event.key === "Escape") { setIsCommandPaletteOpen(false); } }; window.addEventListener("keydown", handleKeyDown); return () => { window.removeEventListener("keydown", handleKeyDown); }; }, [theme, setTheme]); useEffect(() => { const checkAuth = () => { setAuthLoading(true); getUserInfo() .then((meRes) => { if (typeof meRes === "string" || !meRes.username) { setIsAuthenticated(false); setIsAdmin(false); setUsername(null); localStorage.removeItem("jwt"); } else { setIsAuthenticated(true); setIsAdmin(!!meRes.is_admin); setUsername(meRes.username || null); } }) .catch((err) => { setIsAuthenticated(false); setIsAdmin(false); setUsername(null); localStorage.removeItem("jwt"); const errorCode = err?.response?.data?.code; if (errorCode === "SESSION_EXPIRED") { console.warn("Session expired - please log in again"); } }) .finally(() => { setAuthLoading(false); }); }; checkAuth(); const handleStorageChange = () => checkAuth(); window.addEventListener("storage", handleStorageChange); return () => window.removeEventListener("storage", handleStorageChange); }, []); useEffect(() => { localStorage.setItem("topNavbarOpen", JSON.stringify(isTopbarOpen)); }, [isTopbarOpen]); const handleSelectView = () => {}; const handleAuthSuccess = useCallback( (authData: { isAdmin: boolean; username: string | null; userId: string | null; }) => { setIsTransitioning(true); setTransitionPhase("fadeOut"); setTimeout(() => { setIsAuthenticated(true); setIsAdmin(authData.isAdmin); setUsername(authData.username); setTransitionPhase("fadeIn"); setTimeout(() => { setIsTransitioning(false); setTransitionPhase("idle"); }, 800); }, 1200); }, [], ); const handleLogout = useCallback(async () => { setIsTransitioning(true); setTransitionPhase("fadeOut"); setTimeout(async () => { try { const { logoutUser, isElectron } = await import("@/ui/main-axios.ts"); await logoutUser(); if (isElectron()) { localStorage.removeItem("jwt"); } } catch (error) { console.error("Logout failed:", error); } window.location.reload(); }, 1200); }, []); const currentTabData = tabs.find((tab) => tab.id === currentTab); const showTerminalView = currentTabData?.type === "terminal" || currentTabData?.type === "server" || currentTabData?.type === "file_manager" || currentTabData?.type === "tunnel" || currentTabData?.type === "docker"; const showHome = currentTabData?.type === "home"; const showSshManager = currentTabData?.type === "ssh_manager"; const showAdmin = currentTabData?.type === "admin"; const showProfile = currentTabData?.type === "user_profile"; if (authLoading) { return (
); } return (
{!isAuthenticated && (
)} {isAuthenticated && (
{showHome && (
)} {showSshManager && (
)} {showAdmin && (
)} {showProfile && (
)} setIsCommandPaletteOpen(true)} onRightSidebarStateChange={(isOpen, width) => { setRightSidebarOpen(isOpen); setRightSidebarWidth(width); }} />
)} {isTransitioning && (
{transitionPhase === "fadeOut" && ( <>
TERMIX
SSH SERVER MANAGER
)}
)}
); } function DesktopApp() { return ( ); } export default DesktopApp;