From 008ee941c1d3e7c69eacc88c158611cb5e490913 Mon Sep 17 00:00:00 2001 From: Claudio Cambra Date: Wed, 14 May 2025 13:49:18 +0800 Subject: [PATCH 1/4] feat(shell_integration/macOS/FileProviderExt): Add basic CustomActions FileProviderExtension extension Signed-off-by: Claudio Cambra --- .../FileProviderExtension+CustomActions.swift | 21 +++++++++++++++++++ .../project.pbxproj | 4 ++++ 2 files changed, 25 insertions(+) create mode 100644 shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/FileProviderExtension+CustomActions.swift diff --git a/shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/FileProviderExtension+CustomActions.swift b/shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/FileProviderExtension+CustomActions.swift new file mode 100644 index 0000000000..1a1d8b5b41 --- /dev/null +++ b/shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/FileProviderExtension+CustomActions.swift @@ -0,0 +1,21 @@ +// +// FileProviderExtension+CustomActions.swift +// NextcloudIntegration +// +// Created by Claudio Cambra on 14/5/25. +// + +import FileProvider +import NextcloudFileProviderKit +import OSLog + +extension FileProviderExtension: NSFileProviderCustomAction { + func performAction( + identifier actionIdentifier: NSFileProviderExtensionActionIdentifier, + onItemsWithIdentifiers itemIdentifiers: [NSFileProviderItemIdentifier], + completionHandler: @escaping ((any Error)?) -> Void + ) -> Progress { + let progress = Progress() + return progress + } +} diff --git a/shell_integration/MacOSX/NextcloudIntegration/NextcloudIntegration.xcodeproj/project.pbxproj b/shell_integration/MacOSX/NextcloudIntegration/NextcloudIntegration.xcodeproj/project.pbxproj index ce29a33758..c701ab4ae7 100644 --- a/shell_integration/MacOSX/NextcloudIntegration/NextcloudIntegration.xcodeproj/project.pbxproj +++ b/shell_integration/MacOSX/NextcloudIntegration/NextcloudIntegration.xcodeproj/project.pbxproj @@ -7,6 +7,7 @@ objects = { /* Begin PBXBuildFile section */ + 530429982DD44235004BB598 /* FileProviderExtension+CustomActions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 530429972DD44226004BB598 /* FileProviderExtension+CustomActions.swift */; }; 5307A6E62965C6FA001E0C6A /* NextcloudKit in Frameworks */ = {isa = PBXBuildFile; productRef = 5307A6E52965C6FA001E0C6A /* NextcloudKit */; }; 5307A6E82965DAD8001E0C6A /* NextcloudKit in Frameworks */ = {isa = PBXBuildFile; productRef = 5307A6E72965DAD8001E0C6A /* NextcloudKit */; }; 531522822B8E01C6002E31BE /* ShareTableItemView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 531522812B8E01C6002E31BE /* ShareTableItemView.xib */; }; @@ -152,6 +153,7 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ + 530429972DD44226004BB598 /* FileProviderExtension+CustomActions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "FileProviderExtension+CustomActions.swift"; sourceTree = ""; }; 531522812B8E01C6002E31BE /* ShareTableItemView.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = ShareTableItemView.xib; sourceTree = ""; }; 531EDE562D897B4F00FD91F9 /* Eviction.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Eviction.swift; sourceTree = ""; }; 5350E4E72B0C514400F276CB /* ClientCommunicationProtocol.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ClientCommunicationProtocol.h; sourceTree = ""; }; @@ -337,6 +339,7 @@ 53D666602B70C9A70042C03D /* FileProviderConfig.swift */, 538E396C27F4765000FA63D5 /* FileProviderExtension.swift */, 53ED472F29C9CE0B00795DB1 /* FileProviderExtension+ClientInterface.swift */, + 530429972DD44226004BB598 /* FileProviderExtension+CustomActions.swift */, 5352B36B29DC44B50011CE03 /* FileProviderExtension+Thumbnailing.swift */, 536EFBF6295CF58100F4CB13 /* FileProviderSocketLineProcessor.swift */, 538E397327F4765000FA63D5 /* FileProviderExt.entitlements */, @@ -710,6 +713,7 @@ 537630972B860D920026BFAB /* FPUIExtensionService.swift in Sources */, 535AE30E29C0A2CC0042A9BA /* Logger+Extensions.swift in Sources */, 537630952B860D560026BFAB /* FPUIExtensionServiceSource.swift in Sources */, + 530429982DD44235004BB598 /* FileProviderExtension+CustomActions.swift in Sources */, 5350E4E92B0C534A00F276CB /* ClientCommunicationService.swift in Sources */, 5352B36C29DC44B50011CE03 /* FileProviderExtension+Thumbnailing.swift in Sources */, ); From 92b0eb3bb8e569b1d04a91b7bec4c2a28a5f17a0 Mon Sep 17 00:00:00 2001 From: Claudio Cambra Date: Wed, 14 May 2025 13:49:51 +0800 Subject: [PATCH 2/4] feat(shell_integration/macOS/FileProviderExt): Add "Keep Downloaded" related menu actions Signed-off-by: Claudio Cambra --- .../FileProviderExt/Info.plist | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/Info.plist b/shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/Info.plist index 6649e742f6..ebccd214d6 100644 --- a/shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/Info.plist +++ b/shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/Info.plist @@ -10,6 +10,25 @@ $(OC_APPLICATION_REV_DOMAIN).$(PRODUCT_NAME) NSExtension + NSExtensionFileProviderActions + + + NSExtensionFileProviderActionActivationRule + SUBQUERY ( fileproviderItems, $fileproviderItem, $fileproviderItem.userInfo.displayKeepDownloaded == true ).@count > 0 + NSExtensionFileProviderActionIdentifier + com.nextcloud.desktopclient.FileProviderExt.KeepDownloadedAction + NSExtensionFileProviderActionName + Always keep downloaded + + + NSExtensionFileProviderActionActivationRule + SUBQUERY ( fileproviderItems, $fileproviderItem, $fileproviderItem.userInfo.displayAllowAutoEvicting == true ).@count > 0 + NSExtensionFileProviderActionIdentifier + com.nextcloud.desktopclient.FileProviderExt.AutoEvictAction + NSExtensionFileProviderActionName + Allow automatic freeing up space + + NSExtensionFileProviderDocumentGroup $(OC_SOCKETAPI_TEAM_IDENTIFIER_PREFIX)$(OC_APPLICATION_REV_DOMAIN) NSExtensionFileProviderSupportsEnumeration From 867b0fe1f387286a4693e47a1060f293834d82bc Mon Sep 17 00:00:00 2001 From: Claudio Cambra Date: Wed, 14 May 2025 13:50:52 +0800 Subject: [PATCH 3/4] feat(shell_integration/macOS/FileProviderExt): Implement handling of keep downloaded action Signed-off-by: Claudio Cambra --- .../FileProviderExtension+CustomActions.swift | 63 +++++++++++++++++++ 1 file changed, 63 insertions(+) diff --git a/shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/FileProviderExtension+CustomActions.swift b/shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/FileProviderExtension+CustomActions.swift index 1a1d8b5b41..49d5968308 100644 --- a/shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/FileProviderExtension+CustomActions.swift +++ b/shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/FileProviderExtension+CustomActions.swift @@ -15,7 +15,70 @@ extension FileProviderExtension: NSFileProviderCustomAction { onItemsWithIdentifiers itemIdentifiers: [NSFileProviderItemIdentifier], completionHandler: @escaping ((any Error)?) -> Void ) -> Progress { + switch actionIdentifier.rawValue { + case "com.nextcloud.desktopclient.FileProviderExt.KeepDownloadedAction": + return performKeepDownloadedAction( + keepDownloaded: true, + onItemsWithIdentifiers: itemIdentifiers, + completionHandler: completionHandler + ) + case "com.nextcloud.desktopclient.FileProviderExt.AutoEvictAction": + return performKeepDownloadedAction( + keepDownloaded: false, + onItemsWithIdentifiers: itemIdentifiers, + completionHandler: completionHandler + ) + default: + Logger.fileProviderExtension.error("Unsupported action: \(actionIdentifier.rawValue)") + completionHandler(NSError(domain: NSCocoaErrorDomain, code: NSFeatureUnsupportedError)) + return Progress() + } + } + + private func performKeepDownloadedAction( + keepDownloaded: Bool, + onItemsWithIdentifiers itemIdentifiers: [NSFileProviderItemIdentifier], + completionHandler: @escaping ((any Error)?) -> Void + ) -> Progress { + guard let ncAccount else { + Logger.fileProviderExtension.error( + "Not setting keep offline for items, account not set up yet." + ) + completionHandler(NSFileProviderError(.notAuthenticated)) + return Progress() + } + guard let dbManager else { + Logger.fileProviderExtension.error( + "Not setting keep offline for items as database is unreachable." + ) + completionHandler(NSFileProviderError(.cannotSynchronize)) + return Progress() + } + let progress = Progress() + for identifier in itemIdentifiers { + guard let item = Item.storedItem( + identifier: identifier, + account: ncAccount, + remoteInterface: ncKit, + dbManager: dbManager + ) else { + let error = NSError.fileProviderErrorForNonExistentItem(withIdentifier: identifier) + completionHandler(error) + return progress + } + + let childProgress = Progress() + progress.addChild(childProgress, withPendingUnitCount: 1) + Task { + do { + try await item.set(keepDownloaded: keepDownloaded, domain: domain) + childProgress.completedUnitCount = 1 + } catch let error { + completionHandler(error) + } + } + } return progress } } From ab416896ac805fe86142c8afb9d8e54fdecca5e7 Mon Sep 17 00:00:00 2001 From: Claudio Cambra Date: Thu, 15 May 2025 15:04:56 +0800 Subject: [PATCH 4/4] feat(shell_integration/macOS/FileProviderExt): Fix REUSE compliance Signed-off-by: Claudio Cambra --- .../FileProviderExtension+CustomActions.swift | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/FileProviderExtension+CustomActions.swift b/shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/FileProviderExtension+CustomActions.swift index 49d5968308..c8bfcd2842 100644 --- a/shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/FileProviderExtension+CustomActions.swift +++ b/shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/FileProviderExtension+CustomActions.swift @@ -1,9 +1,7 @@ -// -// FileProviderExtension+CustomActions.swift -// NextcloudIntegration -// -// Created by Claudio Cambra on 14/5/25. -// +/* + * SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: GPL-2.0-or-later + */ import FileProvider import NextcloudFileProviderKit