From e8549bdccccce9d5fd7f0b4e675f90d5331e28d6 Mon Sep 17 00:00:00 2001 From: Paul Ebose Date: Tue, 30 Apr 2024 19:17:55 +0100 Subject: [PATCH 1/2] fix: distinguish between Move to Trash and Delete Immediately when right clicking a file or folder --- ...EWorkspaceFileManager+FileManagement.swift | 62 ++++++++++++++++--- .../OutlineView/ProjectNavigatorMenu.swift | 20 +++++- 2 files changed, 71 insertions(+), 11 deletions(-) diff --git a/CodeEdit/Features/CEWorkspace/Models/CEWorkspaceFileManager+FileManagement.swift b/CodeEdit/Features/CEWorkspace/Models/CEWorkspaceFileManager+FileManagement.swift index 89bfed581..b851b65d2 100644 --- a/CodeEdit/Features/CEWorkspace/Models/CEWorkspaceFileManager+FileManagement.swift +++ b/CodeEdit/Features/CEWorkspace/Models/CEWorkspaceFileManager+FileManagement.swift @@ -88,29 +88,73 @@ extension CEWorkspaceFileManager { ) } - /// This function deletes the item or folder from the current project + /// This function deletes the item or folder from the current project by moving to Trash + /// - Parameters: + /// - file: The file or folder to delete + /// - Authors: Paul Ebose + public func trash(file: CEWorkspaceFile) { + let message: String + + if !file.isFolder || file.isEmptyFolder { // if its a file or an empty folder, call it by its name + message = file.name + } else { + let fileCount = fileManager.enumerator(atPath: file.url.path)?.allObjects.count + message = "the \((fileCount ?? 0) + 1) selected items" + } + + let moveFileToTrashAlert = NSAlert() + moveFileToTrashAlert.messageText = "Do you want to move \(message) to Trash?" + moveFileToTrashAlert.informativeText = "This operation cannot be undone." + moveFileToTrashAlert.alertStyle = .critical + moveFileToTrashAlert.addButton(withTitle: "Move to Trash") + moveFileToTrashAlert.buttons.last?.hasDestructiveAction = true + moveFileToTrashAlert.addButton(withTitle: "Cancel") + + if moveFileToTrashAlert.runModal() == .alertFirstButtonReturn { // "Move to Trash" button + if fileManager.fileExists(atPath: file.url.path) { + do { + try fileManager.trashItem(at: file.url, resultingItemURL: nil) + } catch { + fatalError(error.localizedDescription) + } + } + } + } + + /// This function deletes the item or folder from the current project by erasing immediately. /// - Parameters: /// - file: The file to delete /// - confirmDelete: True to present an alert to confirm the delete. - /// - Authors: Mattijs Eikelenboom, KaiTheRedNinja. *Moved from 7c27b1e* + /// - Authors: Mattijs Eikelenboom, KaiTheRedNinja., Paul Ebose *Moved from 7c27b1e* public func delete(file: CEWorkspaceFile, confirmDelete: Bool = true) { // This function also has to account for how the // - file system can change outside of the editor - let deleteConfirmation = NSAlert() - let message: String + let messageText: String + let informativeText: String + if !file.isFolder || file.isEmptyFolder { // if its a file or an empty folder, call it by its name - message = file.name + messageText = "Are you sure you want to delete \"\(file.name)\"?" + informativeText = "This item will be deleted immediately. You can't undo this action." } else { let childrenCount = try? fileManager.contentsOfDirectory( at: file.url, includingPropertiesForKeys: nil ).count - message = "the \((childrenCount ?? 0) + 1) selected items" + + if let childrenCount { + messageText = "Are you sure you want to delete the \((childrenCount) + 1) selected items?" + informativeText = "\(childrenCount) items will be deleted immediately. You can't undo this action." + } else { + messageText = "Are you sure you want to delete the selected items?" + informativeText = "Selected items will be deleted immediately. You can't undo this action." + } } - deleteConfirmation.messageText = "Do you want to move \(message) to the Trash?" - deleteConfirmation.informativeText = "This operation cannot be undone" + + let deleteConfirmation = NSAlert() + deleteConfirmation.messageText = messageText + deleteConfirmation.informativeText = informativeText deleteConfirmation.alertStyle = .critical - deleteConfirmation.addButton(withTitle: "Move to Trash") + deleteConfirmation.addButton(withTitle: "Delete") deleteConfirmation.buttons.last?.hasDestructiveAction = true deleteConfirmation.addButton(withTitle: "Cancel") if !confirmDelete || deleteConfirmation.runModal() == .alertFirstButtonReturn { // "Delete" button diff --git a/CodeEdit/Features/NavigatorArea/ProjectNavigator/OutlineView/ProjectNavigatorMenu.swift b/CodeEdit/Features/NavigatorArea/ProjectNavigator/OutlineView/ProjectNavigatorMenu.swift index 1cbe27af1..78d2b7e8d 100644 --- a/CodeEdit/Features/NavigatorArea/ProjectNavigator/OutlineView/ProjectNavigatorMenu.swift +++ b/CodeEdit/Features/NavigatorArea/ProjectNavigator/OutlineView/ProjectNavigatorMenu.swift @@ -59,9 +59,17 @@ final class ProjectNavigatorMenu: NSMenu { let newFolder = menuItem("New Folder", action: #selector(newFolder)) let rename = menuItem("Rename", action: #selector(renameFile)) - let delete = menuItem("Delete", action: + + let trash = menuItem("Move to Trash", action: + item.url != workspace?.workspaceFileManager?.folderUrl + ? #selector(trash) : nil) + + // trash has to be the previous menu item for delete.isAlternate to work correctly + let delete = menuItem("Delete Immediately...", action: item.url != workspace?.workspaceFileManager?.folderUrl ? #selector(delete) : nil) + delete.keyEquivalentModifierMask = .option + delete.isAlternate = true let duplicate = menuItem("Duplicate \(item.isFolder ? "Folder" : "File")", action: #selector(duplicate)) @@ -87,6 +95,7 @@ final class ProjectNavigatorMenu: NSMenu { newFolder, NSMenuItem.separator(), rename, + trash, delete, duplicate, NSMenuItem.separator(), @@ -229,7 +238,14 @@ final class ProjectNavigatorMenu: NSMenu { outlineView.window?.makeFirstResponder(cell.textField) } - /// Action that deletes the item. + /// Action that moves the item to trash. + @objc + private func trash() { + guard let item else { return } + workspace?.workspaceFileManager?.trash(file: item) + } + + /// Action that deletes the item immediately. @objc private func delete() { guard let item else { return } From f244f825668fcb42d36bf17eb3a90c749240e135 Mon Sep 17 00:00:00 2001 From: Paul Ebose Date: Wed, 1 May 2024 05:04:41 +0100 Subject: [PATCH 2/2] print error when fileManager cannot move item to Trash --- .../Models/CEWorkspaceFileManager+FileManagement.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CodeEdit/Features/CEWorkspace/Models/CEWorkspaceFileManager+FileManagement.swift b/CodeEdit/Features/CEWorkspace/Models/CEWorkspaceFileManager+FileManagement.swift index b851b65d2..e0add7acd 100644 --- a/CodeEdit/Features/CEWorkspace/Models/CEWorkspaceFileManager+FileManagement.swift +++ b/CodeEdit/Features/CEWorkspace/Models/CEWorkspaceFileManager+FileManagement.swift @@ -115,7 +115,7 @@ extension CEWorkspaceFileManager { do { try fileManager.trashItem(at: file.url, resultingItemURL: nil) } catch { - fatalError(error.localizedDescription) + print(error.localizedDescription) } } }