import React, { useState, useEffect, type FC } from "react"; import { Terminal } from "@/ui/Mobile/Apps/Terminal/Terminal.tsx"; import { TerminalKeyboard } from "@/ui/Mobile/Apps/Terminal/TerminalKeyboard.tsx"; import { BottomNavbar } from "@/ui/Mobile/Navigation/BottomNavbar.tsx"; import { LeftSidebar } from "@/ui/Mobile/Navigation/LeftSidebar.tsx"; import { TabProvider, useTabs, } from "@/ui/Mobile/Navigation/Tabs/TabContext.tsx"; import { getUserInfo, getCookie } from "@/ui/main-axios.ts"; import { HomepageAuth } from "@/ui/Mobile/Homepage/HomepageAuth.tsx"; import { useTranslation } from "react-i18next"; import { Toaster } from "@/components/ui/sonner.tsx"; const AppContent: FC = () => { const { t } = useTranslation(); const { tabs, currentTab, getTab, removeTab } = useTabs(); const [isSidebarOpen, setIsSidebarOpen] = React.useState(true); const [ready, setReady] = React.useState(true); const [isAuthenticated, setIsAuthenticated] = useState(false); const [username, setUsername] = useState(null); const [isAdmin, setIsAdmin] = useState(false); const [authLoading, setAuthLoading] = useState(true); useEffect(() => { const checkAuth = () => { setAuthLoading(true); getUserInfo() .then((meRes) => { setIsAuthenticated(true); setIsAdmin(!!meRes.is_admin); setUsername(meRes.username || null); if (!meRes.data_unlocked) { console.warn("User data is locked - re-authentication required"); setIsAuthenticated(false); setIsAdmin(false); setUsername(null); } }) .catch((err) => { setIsAuthenticated(false); setIsAdmin(false); setUsername(null); 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(() => { const interval = setInterval(() => { fitCurrentTerminal(); }, 2000); return () => clearInterval(interval); }, []); const handleAuthSuccess = (authData: { isAdmin: boolean; username: string | null; userId: string | null; }) => { setIsAuthenticated(true); setIsAdmin(authData.isAdmin); setUsername(authData.username); }; const fitCurrentTerminal = () => { const tab = getTab(currentTab as number); if (tab && tab.terminalRef?.current?.fit) { tab.terminalRef.current.fit(); } }; React.useEffect(() => { if (tabs.length > 0) { setReady(false); requestAnimationFrame(() => { requestAnimationFrame(() => { fitCurrentTerminal(); setReady(true); }); }); } }, [currentTab]); const closeSidebar = () => setIsSidebarOpen(false); const handleKeyboardLayoutChange = () => { fitCurrentTerminal(); }; function handleKeyboardInput(input: string) { const currentTerminalTab = getTab(currentTab as number); if ( currentTerminalTab && currentTerminalTab.terminalRef?.current?.sendInput ) { currentTerminalTab.terminalRef.current.sendInput(input); } } if (authLoading) { return (

{t("common.loading")}

); } if (!isAuthenticated) { return (
{}} loggedIn={isAuthenticated} authLoading={authLoading} dbError={null} setDbError={(err) => {}} onAuthSuccess={handleAuthSuccess} />
); } return (
{tabs.map((tab) => (
))} {tabs.length === 0 && (

{t("mobile.selectHostToStart")}

{t("mobile.limitedSupportMessage")}

)}
{currentTab && (
)} setIsSidebarOpen(true)} /> {isSidebarOpen && (
setIsSidebarOpen(false)} /> )}
{ e.stopPropagation(); }} className="pointer-events-auto" >
); }; export const MobileApp: FC = () => { return ( ); };