From fc39d4c9839a3e081e75a233d46e79ba9245d8e2 Mon Sep 17 00:00:00 2001 From: Florian Staske Date: Sat, 13 Dec 2025 21:47:49 +0100 Subject: [PATCH] fix(macos): Improve VFS trash behavior and add deletion warning This commit addresses issues with the macOS Virtual Files (FileProvider) trash handling to prevent accidental permanent data loss: 1. Filter server-trashed items from materialised enumeration - Prevents items that are already in the server's trash from appearing in the macOS Trash, avoiding confusion and potential data conflicts - Server trash items should only be managed through the Nextcloud web interface or desktop client 2. Add confirmation dialog when enabling permanent deletion - Shows a clear warning dialog explaining the consequences before enabling the "permanently delete files" option - Requires explicit user confirmation (Yes/No) with "No" as default - Resets UI state if user cancels 3. Improve UI clarity for trash deletion setting - Renamed checkbox to "Permanently delete files when removed from virtual drive" for clarity - Added visible warning label (red, italic) when the option is enabled - Added Connections handler to properly sync UI state with controller Signed-off-by: Florian Staske --- ...viderMaterialisedEnumerationObserver.swift | 9 +++++++- .../fileprovidersettingscontroller_mac.mm | 20 ++++++++++++++++ src/gui/macOS/ui/FileProviderSettings.qml | 23 ++++++++++++++++++- 3 files changed, 50 insertions(+), 2 deletions(-) diff --git a/shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/FileProviderMaterialisedEnumerationObserver.swift b/shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/FileProviderMaterialisedEnumerationObserver.swift index 9619ca90b06f0..6937f0a7d80d9 100644 --- a/shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/FileProviderMaterialisedEnumerationObserver.swift +++ b/shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/FileProviderMaterialisedEnumerationObserver.swift @@ -22,7 +22,14 @@ class FileProviderMaterialisedEnumerationObserver: NSObject, NSFileProviderEnume } func didEnumerate(_ updatedItems: [NSFileProviderItemProtocol]) { - let updatedItemsIds = Array(updatedItems.map(\.itemIdentifier.rawValue)) + // Filter out items that are in the trash container to prevent server-trashed + // items from appearing in the macOS Trash. Server trash items should only + // be managed through the Nextcloud web interface or desktop client. + let nonTrashItems = updatedItems.filter { item in + item.parentItemIdentifier != .trashContainer + } + + let updatedItemsIds = Array(nonTrashItems.map(\.itemIdentifier.rawValue)) for updatedItemsId in updatedItemsIds { allEnumeratedItemIds.insert(updatedItemsId) diff --git a/src/gui/macOS/fileprovidersettingscontroller_mac.mm b/src/gui/macOS/fileprovidersettingscontroller_mac.mm index 611cc9f34e151..58dc543805c59 100644 --- a/src/gui/macOS/fileprovidersettingscontroller_mac.mm +++ b/src/gui/macOS/fileprovidersettingscontroller_mac.mm @@ -6,6 +6,7 @@ #include "fileprovidersettingscontroller.h" #include +#include #include #include "gui/systray.h" @@ -269,6 +270,25 @@ void initialCheck() return; } + // Show warning dialog when enabling permanent deletion + if (setEnabled) { + const auto result = QMessageBox::warning( + nullptr, + tr("Enable permanent file deletion?"), + tr("When you delete files from the virtual drive in Finder, they will be permanently deleted from the server.\n\n" + "This action cannot be undone. The files will NOT go to the server's trash and cannot be restored.\n\n" + "Are you sure you want to enable this feature?"), + QMessageBox::Yes | QMessageBox::No, + QMessageBox::No); + + if (result != QMessageBox::Yes) { + // User cancelled, reset UI state + emit trashDeletionEnabledForAccountChanged(userIdAtHost); + emit trashDeletionSetForAccountChanged(userIdAtHost); + return; + } + } + const auto domainId = FileProviderUtils::domainIdentifierForAccountIdentifier(userIdAtHost); xpc->setTrashDeletionEnabledForFileProviderDomain(domainId, setEnabled); diff --git a/src/gui/macOS/ui/FileProviderSettings.qml b/src/gui/macOS/ui/FileProviderSettings.qml index e15b3ec63e2f5..1df470c52ffde 100644 --- a/src/gui/macOS/ui/FileProviderSettings.qml +++ b/src/gui/macOS/ui/FileProviderSettings.qml @@ -55,9 +55,30 @@ Page { } CheckBox { - text: qsTr("Allow deletion of items in Trash") + id: trashDeletionCheckBox + text: qsTr("Permanently delete files when removed from virtual drive") checked: root.controller.trashDeletionEnabledForAccount(root.accountUserIdAtHost) onClicked: root.controller.setTrashDeletionEnabledForAccount(root.accountUserIdAtHost, checked) + + Connections { + target: root.controller + function onTrashDeletionEnabledForAccountChanged(accountUserIdAtHost) { + if (root.accountUserIdAtHost !== accountUserIdAtHost) { + return; + } + trashDeletionCheckBox.checked = root.controller.trashDeletionEnabledForAccount(root.accountUserIdAtHost); + } + } + } + + EnforcedPlainTextLabel { + Layout.fillWidth: true + Layout.leftMargin: trashDeletionCheckBox.indicator.width + trashDeletionCheckBox.spacing + visible: trashDeletionCheckBox.checked + text: qsTr("⚠️ Warning: Deleted files will be permanently removed from the server and cannot be restored!") + color: "#cc0000" + wrapMode: Text.WordWrap + font.italic: true } } }