import { Command, CommandInput, CommandItem, CommandList, CommandGroup, CommandSeparator, } from "@/components/ui/command.tsx"; import React, { useEffect, useRef, useState } from "react"; import { cn } from "@/lib/utils"; import { Kbd, KbdGroup } from "@/components/ui/kbd"; import { Key, Server, Settings, User, Github, Terminal, FolderOpen, Pencil, EllipsisVertical, } from "lucide-react"; import { useTranslation } from "react-i18next"; import { BiMoney, BiSupport } from "react-icons/bi"; import { BsDiscord } from "react-icons/bs"; import { GrUpdate } from "react-icons/gr"; import { useTabs } from "@/ui/desktop/navigation/tabs/TabContext.tsx"; import { getRecentActivity, getSSHHosts } from "@/ui/main-axios.ts"; import type { RecentActivityItem } from "@/ui/main-axios.ts"; import { DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuItem, } from "@/components/ui/dropdown-menu"; import { Button } from "@/components/ui/button.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; enableFileManager: boolean; defaultPath: string; tunnelConnections: unknown[]; createdAt: string; updatedAt: string; } export function CommandPalette({ isOpen, setIsOpen, }: { isOpen: boolean; setIsOpen: (isOpen: boolean) => void; }) { const { t } = useTranslation(); const inputRef = useRef(null); const { addTab, setCurrentTab, tabs: tabList, updateTab } = useTabs(); const [recentActivity, setRecentActivity] = useState( [], ); const [hosts, setHosts] = useState([]); useEffect(() => { if (isOpen) { inputRef.current?.focus(); getRecentActivity(50).then((activity) => { setRecentActivity(activity.slice(0, 5)); }); getSSHHosts().then((allHosts) => { setHosts(allHosts); }); } }, [isOpen]); const handleAddHost = () => { const sshManagerTab = tabList.find((t) => t.type === "ssh_manager"); if (sshManagerTab) { updateTab(sshManagerTab.id, { initialTab: "add_host" }); setCurrentTab(sshManagerTab.id); } else { const id = addTab({ type: "ssh_manager", title: t("commandPalette.hostManager"), initialTab: "add_host", }); setCurrentTab(id); } setIsOpen(false); }; const handleAddCredential = () => { const sshManagerTab = tabList.find((t) => t.type === "ssh_manager"); if (sshManagerTab) { updateTab(sshManagerTab.id, { initialTab: "add_credential" }); setCurrentTab(sshManagerTab.id); } else { const id = addTab({ type: "ssh_manager", title: t("commandPalette.hostManager"), initialTab: "add_credential", }); setCurrentTab(id); } setIsOpen(false); }; const handleOpenAdminSettings = () => { const adminTab = tabList.find((t) => t.type === "admin"); if (adminTab) { setCurrentTab(adminTab.id); } else { const id = addTab({ type: "admin", title: t("commandPalette.adminSettings") }); setCurrentTab(id); } setIsOpen(false); }; const handleOpenUserProfile = () => { const userProfileTab = tabList.find((t) => t.type === "user_profile"); if (userProfileTab) { setCurrentTab(userProfileTab.id); } else { const id = addTab({ type: "user_profile", title: t("commandPalette.userProfile") }); setCurrentTab(id); } setIsOpen(false); }; const handleOpenUpdateLog = () => { window.open("https://github.com/Termix-SSH/Termix/releases", "_blank"); setIsOpen(false); }; const handleGitHub = () => { window.open("https://github.com/Termix-SSH/Termix", "_blank"); setIsOpen(false); }; const handleSupport = () => { window.open("https://github.com/Termix-SSH/Support/issues/new", "_blank"); setIsOpen(false); }; const handleDiscord = () => { window.open("https://discord.com/invite/jVQGdvHDrf", "_blank"); setIsOpen(false); }; const handleDonate = () => { window.open("https://github.com/sponsors/LukeGus", "_blank"); setIsOpen(false); }; const handleActivityClick = (item: RecentActivityItem) => { getSSHHosts().then((hosts) => { const host = hosts.find((h: { id: number }) => h.id === item.hostId); if (!host) return; if (item.type === "terminal") { addTab({ type: "terminal", title: item.hostName, hostConfig: host, }); } else if (item.type === "file_manager") { addTab({ type: "file_manager", title: item.hostName, hostConfig: host, }); } }); setIsOpen(false); }; const handleHostTerminalClick = (host: SSHHost) => { const title = host.name?.trim() ? host.name : `${host.username}@${host.ip}:${host.port}`; addTab({ type: "terminal", title, hostConfig: host }); setIsOpen(false); }; const handleHostFileManagerClick = (host: SSHHost) => { const title = host.name?.trim() ? host.name : `${host.username}@${host.ip}:${host.port}`; addTab({ type: "file_manager", title, hostConfig: host }); setIsOpen(false); }; const handleHostServerDetailsClick = (host: SSHHost) => { const title = host.name?.trim() ? host.name : `${host.username}@${host.ip}:${host.port}`; addTab({ type: "server", title, hostConfig: host }); setIsOpen(false); }; const handleHostEditClick = (host: SSHHost) => { const title = host.name?.trim() ? host.name : `${host.username}@${host.ip}:${host.port}`; addTab({ type: "ssh_manager", title: t("commandPalette.hostManager"), hostConfig: host, initialTab: "add_host", }); setIsOpen(false); }; return (
setIsOpen(false)} > e.stopPropagation()} > {recentActivity.length > 0 && ( <> {recentActivity.map((item, index) => ( handleActivityClick(item)} > {item.type === "terminal" ? : } {item.hostName} ))} )} {t("commandPalette.addHost")} {t("commandPalette.addCredential")} {t("commandPalette.adminSettings")} {t("commandPalette.userProfile")} {t("commandPalette.updateLog")} {hosts.map((host, index) => { const title = host.name?.trim() ? host.name : `${host.username}@${host.ip}:${host.port}`; return ( { if (host.enableTerminal) { handleHostTerminalClick(host); } }} className="flex items-center justify-between" >
{title}
e.stopPropagation()} > { e.stopPropagation(); handleHostServerDetailsClick(host); }} className="flex items-center gap-2 cursor-pointer px-3 py-2 hover:bg-dark-hover text-gray-300" > {t("commandPalette.openServerDetails")} { e.stopPropagation(); handleHostFileManagerClick(host); }} className="flex items-center gap-2 cursor-pointer px-3 py-2 hover:bg-dark-hover text-gray-300" > {t("commandPalette.openFileManager")} { e.stopPropagation(); handleHostEditClick(host); }} className="flex items-center gap-2 cursor-pointer px-3 py-2 hover:bg-dark-hover text-gray-300" > {t("commandPalette.edit")}
); })}
{t("commandPalette.github")} {t("commandPalette.support")} {t("commandPalette.discord")} {t("commandPalette.donate")}
{t("commandPalette.press")} Shift Shift {t("commandPalette.toToggle")}
{t("commandPalette.close")} Esc
); }