feat: Enhanced security, UI improvements, and animations #432

Merged
ZacharyZcR merged 22 commits from main into dev-1.8.1 2025-11-09 01:48:33 +00:00
5 changed files with 119 additions and 25 deletions
Showing only changes of commit a2761c1ebf - Show all commits
+23
View File
@@ -1571,5 +1571,28 @@
"cpu": "CPU", "cpu": "CPU",
"ram": "RAM", "ram": "RAM",
"notAvailable": "Nicht verfügbar" "notAvailable": "Nicht verfügbar"
},
"commandPalette": {
"searchPlaceholder": "Nach Hosts oder Schnellaktionen suchen...",
"recentActivity": "Kürzliche Aktivität",
"navigation": "Navigation",
"addHost": "Host hinzufügen",
"addCredential": "Anmeldedaten hinzufügen",
"adminSettings": "Admin-Einstellungen",
"userProfile": "Benutzerprofil",
"updateLog": "Aktualisierungsprotokoll",
"hosts": "Hosts",
"openServerDetails": "Serverdetails öffnen",
"openFileManager": "Dateimanager öffnen",
"edit": "Bearbeiten",
"links": "Links",
"github": "GitHub",
"support": "Support",
"discord": "Discord",
"donate": "Spenden",
"press": "Drücken Sie",
"toToggle": "zum Umschalten",
"close": "Schließen",
"hostManager": "Host-Manager"
} }
} }
+23
View File
@@ -1689,5 +1689,28 @@
"cpu": "CPU", "cpu": "CPU",
"ram": "RAM", "ram": "RAM",
"notAvailable": "N/A" "notAvailable": "N/A"
},
"commandPalette": {
"searchPlaceholder": "Search for hosts or quick actions...",
"recentActivity": "Recent Activity",
"navigation": "Navigation",
"addHost": "Add Host",
"addCredential": "Add Credential",
"adminSettings": "Admin Settings",
"userProfile": "User Profile",
"updateLog": "Update Log",
"hosts": "Hosts",
"openServerDetails": "Open Server Details",
"openFileManager": "Open File Manager",
"edit": "Edit",
"links": "Links",
"github": "GitHub",
"support": "Support",
"discord": "Discord",
"donate": "Donate",
"press": "Press",
"toToggle": "to toggle",
"close": "Close",
"hostManager": "Host Manager"
} }
} }
+23
View File
@@ -1657,5 +1657,28 @@
"cpu": "CPU", "cpu": "CPU",
"ram": "RAM", "ram": "RAM",
"notAvailable": "N/A" "notAvailable": "N/A"
},
"commandPalette": {
"searchPlaceholder": "Поиск хостов или быстрых действий...",
"recentActivity": "Недавняя активность",
"navigation": "Навигация",
"addHost": "Добавить хост",
"addCredential": "Добавить учетные данные",
"adminSettings": "Настройки администратора",
"userProfile": "Профиль пользователя",
"updateLog": "Журнал обновлений",
"hosts": "Хосты",
"openServerDetails": "Открыть детали сервера",
"openFileManager": "Открыть файловый менеджер",
"edit": "Редактировать",
"links": "Ссылки",
"github": "GitHub",
"support": "Поддержка",
"discord": "Discord",
"donate": "Пожертвовать",
"press": "Нажмите",
"toToggle": "для переключения",
"close": "Закрыть",
"hostManager": "Менеджер хостов"
} }
} }
+23
View File
@@ -1582,5 +1582,28 @@
"cpu": "CPU", "cpu": "CPU",
"ram": "内存", "ram": "内存",
"notAvailable": "不可用" "notAvailable": "不可用"
},
"commandPalette": {
"searchPlaceholder": "搜索主机或快速操作...",
"recentActivity": "最近活动",
"navigation": "导航",
"addHost": "添加主机",
"addCredential": "添加凭据",
"adminSettings": "管理员设置",
"userProfile": "用户资料",
"updateLog": "更新日志",
"hosts": "主机",
"openServerDetails": "打开服务器详情",
"openFileManager": "打开文件管理器",
"edit": "编辑",
"links": "链接",
"github": "GitHub",
"support": "支持",
"discord": "Discord",
"donate": "捐赠",
"press": "按下",
"toToggle": "来切换",
"close": "关闭",
"hostManager": "主机管理器"
} }
} }
@@ -20,6 +20,7 @@ import {
Pencil, Pencil,
EllipsisVertical, EllipsisVertical,
} from "lucide-react"; } from "lucide-react";
import { useTranslation } from "react-i18next";
import { BiMoney, BiSupport } from "react-icons/bi"; import { BiMoney, BiSupport } from "react-icons/bi";
import { BsDiscord } from "react-icons/bs"; import { BsDiscord } from "react-icons/bs";
import { GrUpdate } from "react-icons/gr"; import { GrUpdate } from "react-icons/gr";
@@ -64,6 +65,7 @@ export function CommandPalette({
isOpen: boolean; isOpen: boolean;
setIsOpen: (isOpen: boolean) => void; setIsOpen: (isOpen: boolean) => void;
}) { }) {
const { t } = useTranslation();
const inputRef = useRef<HTMLInputElement>(null); const inputRef = useRef<HTMLInputElement>(null);
const { addTab, setCurrentTab, tabs: tabList, updateTab } = useTabs(); const { addTab, setCurrentTab, tabs: tabList, updateTab } = useTabs();
const [recentActivity, setRecentActivity] = useState<RecentActivityItem[]>( const [recentActivity, setRecentActivity] = useState<RecentActivityItem[]>(
@@ -91,7 +93,7 @@ export function CommandPalette({
} else { } else {
const id = addTab({ const id = addTab({
type: "ssh_manager", type: "ssh_manager",
title: "Host Manager", title: t("commandPalette.hostManager"),
initialTab: "add_host", initialTab: "add_host",
}); });
setCurrentTab(id); setCurrentTab(id);
@@ -107,7 +109,7 @@ export function CommandPalette({
} else { } else {
const id = addTab({ const id = addTab({
type: "ssh_manager", type: "ssh_manager",
title: "Host Manager", title: t("commandPalette.hostManager"),
initialTab: "add_credential", initialTab: "add_credential",
}); });
setCurrentTab(id); setCurrentTab(id);
@@ -120,7 +122,7 @@ export function CommandPalette({
if (adminTab) { if (adminTab) {
setCurrentTab(adminTab.id); setCurrentTab(adminTab.id);
} else { } else {
const id = addTab({ type: "admin", title: "Admin Settings" }); const id = addTab({ type: "admin", title: t("commandPalette.adminSettings") });
setCurrentTab(id); setCurrentTab(id);
} }
setIsOpen(false); setIsOpen(false);
@@ -131,7 +133,7 @@ export function CommandPalette({
if (userProfileTab) { if (userProfileTab) {
setCurrentTab(userProfileTab.id); setCurrentTab(userProfileTab.id);
} else { } else {
const id = addTab({ type: "user_profile", title: "User Profile" }); const id = addTab({ type: "user_profile", title: t("commandPalette.userProfile") });
setCurrentTab(id); setCurrentTab(id);
} }
setIsOpen(false); setIsOpen(false);
@@ -214,7 +216,7 @@ export function CommandPalette({
: `${host.username}@${host.ip}:${host.port}`; : `${host.username}@${host.ip}:${host.port}`;
addTab({ addTab({
type: "ssh_manager", type: "ssh_manager",
title: "Host Manager", title: t("commandPalette.hostManager"),
hostConfig: host, hostConfig: host,
initialTab: "add_host", initialTab: "add_host",
}); });
@@ -235,7 +237,7 @@ export function CommandPalette({
> >
<CommandInput <CommandInput
ref={inputRef} ref={inputRef}
placeholder="Search for hosts or quick actions..." placeholder={t("commandPalette.searchPlaceholder")}
/> />
<CommandList <CommandList
key={recentActivity.length} key={recentActivity.length}
@@ -244,7 +246,7 @@ export function CommandPalette({
> >
{recentActivity.length > 0 && ( {recentActivity.length > 0 && (
<> <>
<CommandGroup heading="Recent Activity"> <CommandGroup heading={t("commandPalette.recentActivity")}>
{recentActivity.map((item, index) => ( {recentActivity.map((item, index) => (
<CommandItem <CommandItem
key={`recent-activity-${index}-${item.type}-${item.hostId}-${item.timestamp}`} key={`recent-activity-${index}-${item.type}-${item.hostId}-${item.timestamp}`}
@@ -259,30 +261,30 @@ export function CommandPalette({
<CommandSeparator /> <CommandSeparator />
</> </>
)} )}
<CommandGroup heading="Navigation"> <CommandGroup heading={t("commandPalette.navigation")}>
<CommandItem onSelect={handleAddHost}> <CommandItem onSelect={handleAddHost}>
<Server /> <Server />
<span>Add Host</span> <span>{t("commandPalette.addHost")}</span>
</CommandItem> </CommandItem>
<CommandItem onSelect={handleAddCredential}> <CommandItem onSelect={handleAddCredential}>
<Key /> <Key />
<span>Add Credential</span> <span>{t("commandPalette.addCredential")}</span>
</CommandItem> </CommandItem>
<CommandItem onSelect={handleOpenAdminSettings}> <CommandItem onSelect={handleOpenAdminSettings}>
<Settings /> <Settings />
<span>Admin Settings</span> <span>{t("commandPalette.adminSettings")}</span>
</CommandItem> </CommandItem>
<CommandItem onSelect={handleOpenUserProfile}> <CommandItem onSelect={handleOpenUserProfile}>
<User /> <User />
<span>User Profile</span> <span>{t("commandPalette.userProfile")}</span>
</CommandItem> </CommandItem>
<CommandItem onSelect={handleOpenUpdateLog}> <CommandItem onSelect={handleOpenUpdateLog}>
<GrUpdate /> <GrUpdate />
<span>Update Log</span> <span>{t("commandPalette.updateLog")}</span>
</CommandItem> </CommandItem>
</CommandGroup> </CommandGroup>
<CommandSeparator /> <CommandSeparator />
<CommandGroup heading="Hosts"> <CommandGroup heading={t("commandPalette.hosts")}>
{hosts.map((host, index) => { {hosts.map((host, index) => {
const title = host.name?.trim() const title = host.name?.trim()
? host.name ? host.name
@@ -329,7 +331,7 @@ export function CommandPalette({
className="flex items-center gap-2 cursor-pointer px-3 py-2 hover:bg-dark-hover text-gray-300" className="flex items-center gap-2 cursor-pointer px-3 py-2 hover:bg-dark-hover text-gray-300"
> >
<Server className="h-4 w-4" /> <Server className="h-4 w-4" />
<span className="flex-1">Open Server Details</span> <span className="flex-1">{t("commandPalette.openServerDetails")}</span>
</DropdownMenuItem> </DropdownMenuItem>
<DropdownMenuItem <DropdownMenuItem
onClick={(e) => { onClick={(e) => {
@@ -339,7 +341,7 @@ export function CommandPalette({
className="flex items-center gap-2 cursor-pointer px-3 py-2 hover:bg-dark-hover text-gray-300" className="flex items-center gap-2 cursor-pointer px-3 py-2 hover:bg-dark-hover text-gray-300"
> >
<FolderOpen className="h-4 w-4" /> <FolderOpen className="h-4 w-4" />
<span className="flex-1">Open File Manager</span> <span className="flex-1">{t("commandPalette.openFileManager")}</span>
</DropdownMenuItem> </DropdownMenuItem>
<DropdownMenuItem <DropdownMenuItem
onClick={(e) => { onClick={(e) => {
@@ -349,7 +351,7 @@ export function CommandPalette({
className="flex items-center gap-2 cursor-pointer px-3 py-2 hover:bg-dark-hover text-gray-300" className="flex items-center gap-2 cursor-pointer px-3 py-2 hover:bg-dark-hover text-gray-300"
> >
<Pencil className="h-4 w-4" /> <Pencil className="h-4 w-4" />
<span className="flex-1">Edit</span> <span className="flex-1">{t("commandPalette.edit")}</span>
</DropdownMenuItem> </DropdownMenuItem>
</DropdownMenuContent> </DropdownMenuContent>
</DropdownMenu> </DropdownMenu>
@@ -359,36 +361,36 @@ export function CommandPalette({
})} })}
</CommandGroup> </CommandGroup>
<CommandSeparator /> <CommandSeparator />
<CommandGroup heading="Links"> <CommandGroup heading={t("commandPalette.links")}>
<CommandItem onSelect={handleGitHub}> <CommandItem onSelect={handleGitHub}>
<Github /> <Github />
<span>GitHub</span> <span>{t("commandPalette.github")}</span>
</CommandItem> </CommandItem>
<CommandItem onSelect={handleSupport}> <CommandItem onSelect={handleSupport}>
<BiSupport /> <BiSupport />
<span>Support</span> <span>{t("commandPalette.support")}</span>
</CommandItem> </CommandItem>
<CommandItem onSelect={handleDiscord}> <CommandItem onSelect={handleDiscord}>
<BsDiscord /> <BsDiscord />
<span>Discord</span> <span>{t("commandPalette.discord")}</span>
</CommandItem> </CommandItem>
<CommandItem onSelect={handleDonate}> <CommandItem onSelect={handleDonate}>
<BiMoney /> <BiMoney />
<span>Donate</span> <span>{t("commandPalette.donate")}</span>
</CommandItem> </CommandItem>
</CommandGroup> </CommandGroup>
</CommandList> </CommandList>
<div className="border-t border-dark-border px-4 py-2 bg-dark-hover/50 flex items-center justify-between text-xs text-muted-foreground"> <div className="border-t border-dark-border px-4 py-2 bg-dark-hover/50 flex items-center justify-between text-xs text-muted-foreground">
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
<span>Press</span> <span>{t("commandPalette.press")}</span>
<KbdGroup> <KbdGroup>
<Kbd>Shift</Kbd> <Kbd>Shift</Kbd>
<Kbd>Shift</Kbd> <Kbd>Shift</Kbd>
</KbdGroup> </KbdGroup>
<span>to toggle</span> <span>{t("commandPalette.toToggle")}</span>
</div> </div>
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
<span>Close</span> <span>{t("commandPalette.close")}</span>
<Kbd>Esc</Kbd> <Kbd>Esc</Kbd>
</div> </div>
</div> </div>