diff --git a/src/ui/apps/Terminal/OldTerminal.tsx b/src/ui/apps/Terminal/OldTerminal.tsx deleted file mode 100644 index ba0be63b..00000000 --- a/src/ui/apps/Terminal/OldTerminal.tsx +++ /dev/null @@ -1,440 +0,0 @@ -import React, {useState} from 'react'; - -import { - CornerDownLeft, - Hammer, Pin, Menu -} from "lucide-react" - -import { - Button -} from "@/components/ui/button.tsx" - -import { - Sidebar, - SidebarContent, - SidebarGroup, - SidebarGroupContent, - SidebarGroupLabel, - SidebarMenu, - SidebarMenuItem, SidebarProvider, -} from "@/components/ui/sidebar.tsx" - -import { - Separator, -} from "@/components/ui/separator.tsx" -import { - Sheet, - SheetContent, - SheetHeader, - SheetTitle, - SheetTrigger -} from "@/components/ui/sheet.tsx"; -import { - Accordion, - AccordionContent, - AccordionItem, - AccordionTrigger, -} from "@/components/ui/accordion.tsx"; -import {ScrollArea} from "@/components/ui/scroll-area.tsx"; -import {Input} from "@/components/ui/input.tsx"; -import {getSSHHosts} from "@/apps/SSH/ssh-axios"; -import {Checkbox} from "@/components/ui/checkbox.tsx"; - -interface SSHHost { - id: number; - name: string; - ip: string; - port: number; - username: string; - folder: string; - tags: string[]; - pin: boolean; - authType: string; - password?: string; - key?: string; - keyPassword?: string; - keyType?: string; - enableTerminal: boolean; - enableTunnel: boolean; - enableConfigEditor: boolean; - defaultPath: string; - tunnelConnections: any[]; - createdAt: string; - updatedAt: string; -} - -export interface SidebarProps { - onSelectView: (view: string) => void; - onHostConnect: (hostConfig: any) => void; - allTabs: { id: number; title: string; terminalRef: React.RefObject }[]; - runCommandOnTabs: (tabIds: number[], command: string) => void; - onCloseSidebar?: () => void; - onAddHostSubmit?: (data: any) => void; - open?: boolean; - onOpenChange?: (open: boolean) => void; -} - -export function TerminalSidebar({ - onSelectView, - onHostConnect, - allTabs, - runCommandOnTabs, - onCloseSidebar, - open, - onOpenChange - }: SidebarProps): React.ReactElement { - const [hosts, setHosts] = useState([]); - const [hostsLoading, setHostsLoading] = useState(false); - const [hostsError, setHostsError] = useState(null); - const prevHostsRef = React.useRef([]); - - const fetchHosts = React.useCallback(async () => { - setHostsLoading(true); - setHostsError(null); - try { - const newHosts = await getSSHHosts(); - const terminalHosts = newHosts.filter(host => host.enableTerminal); - - const prevHosts = prevHostsRef.current; - const isSame = - terminalHosts.length === prevHosts.length && - terminalHosts.every((h: SSHHost, i: number) => { - const prev = prevHosts[i]; - if (!prev) return false; - return ( - h.id === prev.id && - h.name === prev.name && - h.folder === prev.folder && - h.ip === prev.ip && - h.port === prev.port && - h.username === prev.username && - h.password === prev.password && - h.authType === prev.authType && - h.key === prev.key && - h.pin === prev.pin && - JSON.stringify(h.tags) === JSON.stringify(prev.tags) - ); - }); - if (!isSame) { - setHosts(terminalHosts); - prevHostsRef.current = terminalHosts; - } - } catch (err: any) { - setHostsError('Failed to load hosts'); - } finally { - setHostsLoading(false); - } - }, []); - - React.useEffect(() => { - fetchHosts(); - const interval = setInterval(fetchHosts, 10000); - return () => clearInterval(interval); - }, [fetchHosts]); - - const [search, setSearch] = useState(""); - const [debouncedSearch, setDebouncedSearch] = useState(""); - React.useEffect(() => { - const handler = setTimeout(() => setDebouncedSearch(search), 200); - return () => clearTimeout(handler); - }, [search]); - - const filteredHosts = React.useMemo(() => { - if (!debouncedSearch.trim()) return hosts; - const q = debouncedSearch.trim().toLowerCase(); - return hosts.filter(h => { - const searchableText = [ - h.name || '', - h.username, - h.ip, - h.folder || '', - ...(h.tags || []), - h.authType, - h.defaultPath || '' - ].join(' ').toLowerCase(); - return searchableText.includes(q); - }); - }, [hosts, debouncedSearch]); - - const hostsByFolder = React.useMemo(() => { - const map: Record = {}; - filteredHosts.forEach(h => { - const folder = h.folder && h.folder.trim() ? h.folder : 'No Folder'; - if (!map[folder]) map[folder] = []; - map[folder].push(h); - }); - return map; - }, [filteredHosts]); - - const sortedFolders = React.useMemo(() => { - const folders = Object.keys(hostsByFolder); - folders.sort((a, b) => { - if (a === 'No Folder') return -1; - if (b === 'No Folder') return 1; - return a.localeCompare(b); - }); - return folders; - }, [hostsByFolder]); - - const getSortedHosts = (arr: SSHHost[]) => { - const pinned = arr.filter(h => h.pin).sort((a, b) => (a.name || '').localeCompare(b.name || '')); - const rest = arr.filter(h => !h.pin).sort((a, b) => (a.name || '').localeCompare(b.name || '')); - return [...pinned, ...rest]; - }; - - const [toolsSheetOpen, setToolsSheetOpen] = useState(false); - const [toolsCommand, setToolsCommand] = useState(""); - const [selectedTabIds, setSelectedTabIds] = useState([]); - - const handleTabToggle = (tabId: number) => { - setSelectedTabIds(prev => prev.includes(tabId) ? prev.filter(id => id !== tabId) : [...prev, tabId]); - }; - - const handleRunCommand = () => { - if (selectedTabIds.length && toolsCommand.trim()) { - let cmd = toolsCommand; - if (!cmd.endsWith("\n")) cmd += "\n"; - runCommandOnTabs(selectedTabIds, cmd); - setToolsCommand(""); - } - }; - - function getCookie(name: string) { - return document.cookie.split('; ').reduce((r, v) => { - const parts = v.split('='); - return parts[0] === name ? decodeURIComponent(parts[1]) : r; - }, ""); - } - - const updateRightClickCopyPaste = (checked) => { - document.cookie = `rightClickCopyPaste=${checked}; expires=2147483647; path=/`; - } - - return ( - - - - - - Termix / Terminal - - - - - - - - - - - - -
-
- setSearch(e.target.value)} - placeholder="Search hosts by name, username, IP, folder, tags..." - className="w-full h-8 text-sm bg-background border border-border rounded" - autoComplete="off" - /> -
-
- -
- {hostsError && ( -
-
{hostsError}
-
- )} -
- - 0 ? sortedFolders : undefined}> - {sortedFolders.map((folder, idx) => ( - - - {folder} - - {getSortedHosts(hostsByFolder[folder]).map(host => ( -
- -
- ))} -
-
- {idx < sortedFolders.length - 1 && ( -
- -
- )} -
- ))} -
-
-
-
-
-
-
-
- - - - - - - Tools - -
- - - Run multiwindow - commands - -