From 2596382ea84ba64017b22e52f1e39a6a523d0d80 Mon Sep 17 00:00:00 2001 From: Elijah Date: Sat, 23 May 2026 14:38:09 -0700 Subject: [PATCH] fix: resolve 404 file not found when permanently deleting files already in trash --- backend/handlers/files.go | 10 ++++----- frontend/src/components/FileExplorer.tsx | 28 ++++++++++++++---------- 2 files changed, 22 insertions(+), 16 deletions(-) diff --git a/backend/handlers/files.go b/backend/handlers/files.go index 760db5b..c38645f 100644 --- a/backend/handlers/files.go +++ b/backend/handlers/files.go @@ -529,11 +529,6 @@ func (h *FSHandler) Delete(c *fiber.Ctx) error { resolvedPath := c.Locals("resolvedPath").(string) relativePath := c.Locals("relativePath").(string) - // Check if file exists - if _, err := os.Stat(resolvedPath); os.IsNotExist(err) { - return c.Status(fiber.StatusNotFound).JSON(fiber.Map{"error": "file not found"}) - } - // Soft-delete: move to .trash directory trashPath := filepath.Join(h.Config.TrashDir, relativePath) @@ -557,6 +552,11 @@ func (h *FSHandler) Delete(c *fiber.Ctx) error { return c.JSON(fiber.Map{"message": "permanently deleted"}) } + // For soft-delete, file must exist in regular storage + if _, err := os.Stat(resolvedPath); os.IsNotExist(err) { + return c.Status(fiber.StatusNotFound).JSON(fiber.Map{"error": "file not found"}) + } + if err := os.MkdirAll(filepath.Dir(trashPath), 0755); err != nil { fmt.Printf("MkdirAll error: %v\n", err) return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": "failed to prepare trash"}) diff --git a/frontend/src/components/FileExplorer.tsx b/frontend/src/components/FileExplorer.tsx index 8dfa35d..dd4ff05 100644 --- a/frontend/src/components/FileExplorer.tsx +++ b/frontend/src/components/FileExplorer.tsx @@ -632,17 +632,22 @@ export default function FileExplorer({ onLogout }: FileExplorerProps) { async function executeDeleteSelected() { const count = selectedFiles.size; const isPermanent = activeSection === 'trash'; - for (const path of selectedFiles) { - await api.deleteFile(path, isPermanent); + try { + for (const path of selectedFiles) { + await api.deleteFile(path, isPermanent); + } + setSelectedFiles(new Set()); + if (activeSection === 'trash') { + loadTrash(); + } else { + loadFiles(undefined, true); + } + showToast(isPermanent ? `Permanently deleted ${count} item${count > 1 ? 's' : ''}` : `Deleted ${count} item${count > 1 ? 's' : ''}`); + } catch (err: any) { + showToast(`Delete failed: ${err.message}`); + } finally { + setDeleteConfirm(null); } - setSelectedFiles(new Set()); - if (activeSection === 'trash') { - loadTrash(); - } else { - loadFiles(undefined, true); - } - setDeleteConfirm(null); - showToast(isPermanent ? `Permanently deleted ${count} item${count > 1 ? 's' : ''}` : `Deleted ${count} item${count > 1 ? 's' : ''}`); } async function executeDeleteSingle(file: FileItem) { @@ -654,10 +659,11 @@ export default function FileExplorer({ onLogout }: FileExplorerProps) { } else { loadFiles(undefined, true); } - setDeleteConfirm(null); showToast(isPermanent ? `Permanently deleted ${file.name}` : `Deleted ${file.name}`); } catch (err: any) { showToast(`Delete failed: ${err.message}`); + } finally { + setDeleteConfirm(null); } }