mirror of
https://github.com/nextcloud/desktop.git
synced 2025-10-26 11:17:43 +00:00
Merge pull request #8237 from nextcloud/feature/disable-vfs-trash
feat(shell_integration/macOS/FileProviderExt): Add option to disable deletion of items in Trash
This commit is contained in:
commit
565f145fa2
@ -12,6 +12,7 @@ import Foundation
|
||||
struct FileProviderConfig {
|
||||
private enum ConfigKey: String {
|
||||
case fastEnumerationEnabled = "fastEnumerationEnabled"
|
||||
case trashDeletionEnabled = "trashDeletionEnabled"
|
||||
}
|
||||
|
||||
let domainIdentifier: NSFileProviderDomainIdentifier
|
||||
@ -32,6 +33,13 @@ struct FileProviderConfig {
|
||||
}
|
||||
}
|
||||
|
||||
var trashDeletionEnabled: Bool {
|
||||
get { internalConfig[ConfigKey.trashDeletionEnabled.rawValue] as? Bool ?? true }
|
||||
set { internalConfig[ConfigKey.trashDeletionEnabled.rawValue] = newValue }
|
||||
}
|
||||
|
||||
lazy var trashDeletionSet = internalConfig[ConfigKey.trashDeletionEnabled.rawValue] != nil
|
||||
|
||||
var fastEnumerationEnabled: Bool {
|
||||
get { internalConfig[ConfigKey.fastEnumerationEnabled.rawValue] as? Bool ?? true }
|
||||
set { internalConfig[ConfigKey.fastEnumerationEnabled.rawValue] = newValue }
|
||||
|
||||
@ -422,6 +422,17 @@ import OSLog
|
||||
}
|
||||
|
||||
let progress = Progress(totalUnitCount: 1)
|
||||
guard config.trashDeletionEnabled || item.parentItemIdentifier != .trashContainer else {
|
||||
Logger.fileProviderExtension.warning(
|
||||
"""
|
||||
System requested deletion of item in trash, but deleting trash items is disabled.
|
||||
item: \(item.filename, privacy: .public)
|
||||
"""
|
||||
)
|
||||
completionHandler(NSError.fileProviderErrorForRejectedDeletion(of: item))
|
||||
return progress
|
||||
}
|
||||
|
||||
Task {
|
||||
let error = await item.delete(dbManager: dbManager)
|
||||
if error != nil {
|
||||
|
||||
@ -20,6 +20,8 @@
|
||||
- (void)createDebugLogStringWithCompletionHandler:(void(^)(NSString *debugLogString, NSError *error))completionHandler;
|
||||
- (void)getFastEnumerationStateWithCompletionHandler:(void(^)(BOOL enabled, BOOL set))completionHandler;
|
||||
- (void)setFastEnumerationEnabled:(BOOL)enabled;
|
||||
- (void)getTrashDeletionEnabledStateWithCompletionHandler:(void(^)(BOOL enabled, BOOL set))completionHandler;
|
||||
- (void)setTrashDeletionEnabled:(BOOL)enabled;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@ -101,4 +101,17 @@ class ClientCommunicationService: NSObject, NSFileProviderServiceSource, NSXPCLi
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func getTrashDeletionEnabledState(completionHandler: @escaping (Bool, Bool) -> Void) {
|
||||
let enabled = fpExtension.config.trashDeletionEnabled
|
||||
let set = fpExtension.config.trashDeletionSet
|
||||
completionHandler(enabled, set)
|
||||
}
|
||||
|
||||
func setTrashDeletionEnabled(_ enabled: Bool) {
|
||||
fpExtension.config.trashDeletionEnabled = enabled
|
||||
Logger.fileProviderExtension.info(
|
||||
"Trash deletion setting changed to: \(enabled, privacy: .public)"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@ -37,6 +37,8 @@ public:
|
||||
[[nodiscard]] Q_INVOKABLE float remoteStorageUsageGbForAccount(const QString &userIdAtHost) const;
|
||||
[[nodiscard]] Q_INVOKABLE bool fastEnumerationEnabledForAccount(const QString &userIdAtHost) const;
|
||||
[[nodiscard]] Q_INVOKABLE bool fastEnumerationSetForAccount(const QString &userIdAtHost) const;
|
||||
[[nodiscard]] Q_INVOKABLE bool trashDeletionEnabledForAccount(const QString &userIdAtHost) const;
|
||||
[[nodiscard]] Q_INVOKABLE bool trashDeletionSetForAccount(const QString &userIdAtHost) const;
|
||||
|
||||
[[nodiscard]] Q_INVOKABLE QAbstractListModel *materialisedItemsModelForAccount(const QString &userIdAtHost);
|
||||
[[nodiscard]] Q_INVOKABLE FileProviderDomainSyncStatus *domainSyncStatusForAccount(const QString &userIdAtHost) const;
|
||||
@ -44,6 +46,7 @@ public:
|
||||
public slots:
|
||||
void setVfsEnabledForAccount(const QString &userIdAtHost, const bool setEnabled);
|
||||
void setFastEnumerationEnabledForAccount(const QString &userIdAtHost, const bool setEnabled);
|
||||
void setTrashDeletionEnabledForAccount(const QString &userIdAtHost, const bool setEnabled);
|
||||
|
||||
void createEvictionWindowForAccount(const QString &userIdAtHost);
|
||||
void refreshMaterialisedItemsForAccount(const QString &userIdAtHost);
|
||||
@ -57,6 +60,8 @@ signals:
|
||||
void materialisedItemsForAccountChanged(const QString &userIdAtHost);
|
||||
void fastEnumerationEnabledForAccountChanged(const QString &userIdAtHost);
|
||||
void fastEnumerationSetForAccountChanged(const QString &userIdAtHost);
|
||||
void trashDeletionEnabledForAccountChanged(const QString &userIdAtHost);
|
||||
void trashDeletionSetForAccountChanged(const QString &userIdAtHost);
|
||||
|
||||
private:
|
||||
explicit FileProviderSettingsController(QObject *parent = nullptr);
|
||||
|
||||
@ -412,6 +412,44 @@ void FileProviderSettingsController::setFastEnumerationEnabledForAccount(const Q
|
||||
emit fastEnumerationSetForAccountChanged(userIdAtHost);
|
||||
}
|
||||
|
||||
bool FileProviderSettingsController::trashDeletionEnabledForAccount(const QString &userIdAtHost) const
|
||||
{
|
||||
const auto xpc = FileProvider::instance()->xpc();
|
||||
if (!xpc) {
|
||||
return true;
|
||||
}
|
||||
if (const auto trashDeletionState = xpc->trashDeletionEnabledStateForExtension(userIdAtHost)) {
|
||||
return trashDeletionState->first;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FileProviderSettingsController::trashDeletionSetForAccount(const QString &userIdAtHost) const
|
||||
{
|
||||
const auto xpc = FileProvider::instance()->xpc();
|
||||
if (!xpc) {
|
||||
return false;
|
||||
}
|
||||
if (const auto state = xpc->trashDeletionEnabledStateForExtension(userIdAtHost)) {
|
||||
return state->second;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void FileProviderSettingsController::setTrashDeletionEnabledForAccount(const QString &userIdAtHost, const bool setEnabled)
|
||||
{
|
||||
const auto xpc = FileProvider::instance()->xpc();
|
||||
if (!xpc) {
|
||||
// Reset state of UI elements
|
||||
emit trashDeletionEnabledForAccountChanged(userIdAtHost);
|
||||
emit trashDeletionSetForAccountChanged(userIdAtHost);
|
||||
return;
|
||||
}
|
||||
xpc->setTrashDeletionEnabledForExtension(userIdAtHost, setEnabled);
|
||||
emit trashDeletionEnabledForAccountChanged(userIdAtHost);
|
||||
emit trashDeletionSetForAccountChanged(userIdAtHost);
|
||||
}
|
||||
|
||||
unsigned long long FileProviderSettingsController::localStorageUsageForAccount(const QString &userIdAtHost) const
|
||||
{
|
||||
return d->localStorageUsageForAccount(userIdAtHost);
|
||||
|
||||
@ -31,6 +31,8 @@ public:
|
||||
// Returns enabled and set state of fast enumeration for the given extension
|
||||
[[nodiscard]] std::optional<std::pair<bool, bool>> fastEnumerationStateForExtension(const QString &extensionAccountId) const;
|
||||
|
||||
[[nodiscard]] std::optional<std::pair<bool, bool>> trashDeletionEnabledStateForExtension(const QString &extensionAccountId) const;
|
||||
|
||||
public slots:
|
||||
void connectToExtensions();
|
||||
void configureExtensions();
|
||||
@ -39,6 +41,7 @@ public slots:
|
||||
void createDebugArchiveForExtension(const QString &extensionAccountId, const QString &filename);
|
||||
|
||||
void setFastEnumerationEnabledForExtension(const QString &extensionAccountId, bool enabled) const;
|
||||
void setTrashDeletionEnabledForExtension(const QString &extensionAccountId, bool enabled) const;
|
||||
|
||||
private slots:
|
||||
void slotAccountStateChanged(AccountState::State state) const;
|
||||
|
||||
@ -235,4 +235,38 @@ void FileProviderXPC::setFastEnumerationEnabledForExtension(const QString &exten
|
||||
[service setFastEnumerationEnabled:enabled];
|
||||
}
|
||||
|
||||
std::optional<std::pair<bool, bool>> FileProviderXPC::trashDeletionEnabledStateForExtension(const QString &extensionAccountId) const
|
||||
{
|
||||
qCInfo(lcFileProviderXPC) << "Checking if fast enumeration is enabled for extension" << extensionAccountId;
|
||||
const auto service = (NSObject<ClientCommunicationProtocol> *)_clientCommServices.value(extensionAccountId);
|
||||
if (service == nil) {
|
||||
qCWarning(lcFileProviderXPC) << "Could not get service for extension" << extensionAccountId;
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
__block BOOL receivedTrashDeletionEnabled = YES; // What is the value of the setting being used by the extension?
|
||||
__block BOOL receivedTrashDeletionEnabledSet = NO; // Has the setting been set by the user?
|
||||
__block BOOL receivedResponse = NO;
|
||||
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
|
||||
[service getTrashDeletionEnabledStateWithCompletionHandler:^(BOOL enabled, BOOL set) {
|
||||
receivedTrashDeletionEnabled = enabled;
|
||||
receivedTrashDeletionEnabledSet = set;
|
||||
receivedResponse = YES;
|
||||
dispatch_semaphore_signal(semaphore);
|
||||
}];
|
||||
dispatch_semaphore_wait(semaphore, dispatch_time(DISPATCH_TIME_NOW, semaphoreWaitDelta));
|
||||
if (!receivedResponse) {
|
||||
qCWarning(lcFileProviderXPC) << "Did not receive response for fast enumeration state";
|
||||
return std::nullopt;
|
||||
}
|
||||
return std::optional<std::pair<bool, bool>>{{receivedTrashDeletionEnabled, receivedTrashDeletionEnabledSet}};
|
||||
}
|
||||
|
||||
void FileProviderXPC::setTrashDeletionEnabledForExtension(const QString &extensionAccountId, bool enabled) const
|
||||
{
|
||||
qCInfo(lcFileProviderXPC) << "Setting trash deletion enabled for extension" << extensionAccountId << "to" << enabled;
|
||||
const auto service = (NSObject<ClientCommunicationProtocol> *)_clientCommServices.value(extensionAccountId);
|
||||
[service setTrashDeletionEnabled:enabled];
|
||||
}
|
||||
|
||||
} // namespace OCC::Mac
|
||||
|
||||
@ -131,6 +131,12 @@ Page {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CheckBox {
|
||||
text: qsTr("Allow deletion of items in Trash")
|
||||
checked: root.controller.trashDeletionEnabledForAccount(root.accountUserIdAtHost)
|
||||
onClicked: root.controller.setTrashDeletionEnabledForAccount(root.accountUserIdAtHost, checked)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user