From d3532a24ee1d77769d7635d0f21af8bf709464c6 Mon Sep 17 00:00:00 2001 From: thorved <54140516+thorved@users.noreply.github.com> Date: Sat, 4 Oct 2025 15:03:51 +0530 Subject: [PATCH] Feature request: Add delete confirmation dialog to file manager - Added confirmation dialog before deleting files/folders - Users must confirm deletion with a warning message - Works for both Delete key and right-click delete - Shows different messages for single file, folder, or multiple items - Includes permanent deletion warning - Follows existing design patterns using confirmWithToast --- src/locales/en/translation.json | 4 + .../Desktop/Apps/File Manager/FileManager.tsx | 121 +++++++++++------- 2 files changed, 80 insertions(+), 45 deletions(-) diff --git a/src/locales/en/translation.json b/src/locales/en/translation.json index 0e6d735e..842f24fe 100644 --- a/src/locales/en/translation.json +++ b/src/locales/en/translation.json @@ -844,8 +844,12 @@ "selectServerToEdit": "Select a server from the sidebar to start editing files", "fileOperations": "File Operations", "confirmDeleteMessage": "Are you sure you want to delete {{name}}?", + "confirmDeleteSingleItem": "Are you sure you want to permanently delete \"{{name}}\"?", + "confirmDeleteMultipleItems": "Are you sure you want to permanently delete {{count}} items?", + "confirmDeleteFolder": "Are you sure you want to permanently delete the folder \"{{name}}\" and all its contents?", "deleteDirectoryWarning": "This will delete the folder and all its contents.", "actionCannotBeUndone": "This action cannot be undone.", + "permanentDeleteWarning": "This action cannot be undone. The item(s) will be permanently deleted from the server.", "recent": "Recent", "pinned": "Pinned", "folderShortcuts": "Folder Shortcuts", diff --git a/src/ui/Desktop/Apps/File Manager/FileManager.tsx b/src/ui/Desktop/Apps/File Manager/FileManager.tsx index 0f05c589..b00efe06 100644 --- a/src/ui/Desktop/Apps/File Manager/FileManager.tsx +++ b/src/ui/Desktop/Apps/File Manager/FileManager.tsx @@ -9,6 +9,7 @@ import { FileWindow } from "./components/FileWindow"; import { DiffWindow } from "./components/DiffWindow"; import { useDragToDesktop } from "../../../hooks/useDragToDesktop"; import { useDragToSystemDesktop } from "../../../hooks/useDragToSystemDesktop"; +import { useConfirmation } from "@/hooks/use-confirmation.ts"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { toast } from "sonner"; @@ -82,6 +83,7 @@ function formatFileSize(bytes?: number): string { function FileManagerContent({ initialHost, onClose }: FileManagerProps) { const { openWindow } = useWindowManager(); const { t } = useTranslation(); + const { confirmWithToast } = useConfirmation(); const [currentHost, setCurrentHost] = useState( initialHost || null, @@ -587,54 +589,83 @@ function FileManagerContent({ initialHost, onClose }: FileManagerProps) { async function handleDeleteFiles(files: FileItem[]) { if (!sshSessionId || files.length === 0) return; - try { - await ensureSSHConnection(); - - for (const file of files) { - await deleteSSHItem( - sshSessionId, - file.path, - file.type === "directory", - currentHost?.id, - currentHost?.userId?.toString(), - ); - } - - const deletedFiles = files.map((file) => ({ - path: file.path, - name: file.name, - })); - - const undoAction: UndoAction = { - type: "delete", - description: t("fileManager.deletedItems", { count: files.length }), - data: { - operation: "cut", - deletedFiles, - targetDirectory: currentPath, - }, - timestamp: Date.now(), - }; - setUndoHistory((prev) => [...prev.slice(-9), undoAction]); - - toast.success( - t("fileManager.itemsDeletedSuccessfully", { count: files.length }), - ); - handleRefreshDirectory(); - clearSelection(); - } catch (error: any) { - if ( - error.message?.includes("connection") || - error.message?.includes("established") - ) { - toast.error( - `SSH connection failed. Please check your connection to ${currentHost?.name} (${currentHost?.ip}:${currentHost?.port})`, - ); + // Determine the confirmation message based on file count and type + let confirmMessage: string; + if (files.length === 1) { + const file = files[0]; + if (file.type === "directory") { + confirmMessage = t("fileManager.confirmDeleteFolder", { + name: file.name, + }); } else { - toast.error(t("fileManager.failedToDeleteItems")); + confirmMessage = t("fileManager.confirmDeleteSingleItem", { + name: file.name, + }); } - console.error("Delete failed:", error); + } else { + confirmMessage = t("fileManager.confirmDeleteMultipleItems", { + count: files.length, + }); } + + // Add permanent deletion warning + const fullMessage = `${confirmMessage}\n\n${t("fileManager.permanentDeleteWarning")}`; + + // Show confirmation dialog + confirmWithToast( + fullMessage, + async () => { + try { + await ensureSSHConnection(); + + for (const file of files) { + await deleteSSHItem( + sshSessionId, + file.path, + file.type === "directory", + currentHost?.id, + currentHost?.userId?.toString(), + ); + } + + const deletedFiles = files.map((file) => ({ + path: file.path, + name: file.name, + })); + + const undoAction: UndoAction = { + type: "delete", + description: t("fileManager.deletedItems", { count: files.length }), + data: { + operation: "cut", + deletedFiles, + targetDirectory: currentPath, + }, + timestamp: Date.now(), + }; + setUndoHistory((prev) => [...prev.slice(-9), undoAction]); + + toast.success( + t("fileManager.itemsDeletedSuccessfully", { count: files.length }), + ); + handleRefreshDirectory(); + clearSelection(); + } catch (error: any) { + if ( + error.message?.includes("connection") || + error.message?.includes("established") + ) { + toast.error( + `SSH connection failed. Please check your connection to ${currentHost?.name} (${currentHost?.ip}:${currentHost?.port})`, + ); + } else { + toast.error(t("fileManager.failedToDeleteItems")); + } + console.error("Delete failed:", error); + } + }, + "destructive", + ); } function handleCreateNewFolder() {