import { useState, useEffect } from "react"; import { NewTerminal } from "./Terminal.jsx"; import AddHostModal from "./AddHostModal.jsx"; import { Button } from "@mui/joy"; import { CssVarsProvider } from "@mui/joy"; import theme from "./theme"; import TabList from "./TabList.jsx"; import Launchpad from "./Launchpad.jsx"; import TermixIcon from "./images/termix_icon.png"; import RocketIcon from './images/launchpad_rocket.png'; function App() { const [isAddHostHidden, setIsAddHostHidden] = useState(true); const [terminals, setTerminals] = useState([]); const [activeTab, setActiveTab] = useState(null); const [nextId, setNextId] = useState(1); const [form, setForm] = useState({ name: "", ip: "", user: "", password: "", port: 22, }); const [isLaunchpadOpen, setIsLaunchpadOpen] = useState(false); const [splitTabIds, setSplitTabIds] = useState([]); useEffect(() => { const handleKeyDown = (e) => { if (e.ctrlKey && e.key === "l") { e.preventDefault(); setIsLaunchpadOpen((prev) => !prev); } }; window.addEventListener("keydown", handleKeyDown); return () => { window.removeEventListener("keydown", handleKeyDown); }; }, []); const handleAddHost = () => { if (form.ip && form.user && form.password && form.port) { const newTerminal = { id: nextId, title: form.name || form.ip, hostConfig: { ip: form.ip, user: form.user, password: form.password, port: Number(form.port), }, terminalRef: null, }; setTerminals([...terminals, newTerminal]); setActiveTab(nextId); setNextId(nextId + 1); setIsAddHostHidden(true); setForm({ name: "", ip: "", user: "", password: "", port: 22 }); } else { alert("Please fill out all fields."); } }; const closeTab = (id) => { const newTerminals = terminals.filter((t) => t.id !== id); setTerminals(newTerminals); if (activeTab === id) { setActiveTab(newTerminals[0]?.id || null); } }; const toggleSplit = (id) => { if (splitTabIds.includes(id)) { setSplitTabIds((prev) => prev.filter((splitId) => splitId !== id)); return; } if (splitTabIds.length >= 3) return; setSplitTabIds((prev) => prev.includes(id) ? prev.filter((splitId) => splitId !== id) : [...prev, id] ); }; const handleSetActiveTab = (tabId) => { setActiveTab(tabId); }; const getLayoutStyle = () => { if (splitTabIds.length === 1) { // Horizontal split (2 tabs: left-right) return "flex flex-row h-full gap-4"; } else if (splitTabIds.length > 1) { // 2x2 Grid layout (4 tabs max), with evenly spaced rows return "grid grid-cols-2 grid-rows-2 gap-4 h-full overflow-hidden"; } // No split, main tab takes the entire screen return "flex flex-col h-full"; }; return (
{/* Topbar */}
Termix Icon

Termix

{/* Launchpad Button */} {/* Add Host Button */}
{/* Terminal Views */}
{terminals.map((terminal) => (
{ if (ref && !terminal.terminalRef) { setTerminals((prev) => prev.map((t) => t.id === terminal.id ? { ...t, terminalRef: ref } : t ) ); } }} />
))}
{/* Modals */} {isLaunchpadOpen && setIsLaunchpadOpen(false)} />}
); } export default App;