Merge pull request #8270 from nextcloud/feature/mac-vfs-keepoffline

feat(shell_integration/macOS/FileProviderExt): Add ability to mark files/folders as "Always keep downloaded" in macOS VFS
This commit is contained in:
Matthieu Gallien 2025-05-15 09:39:58 +02:00 committed by GitHub
commit e81e1f5d64
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 105 additions and 0 deletions

View File

@ -0,0 +1,82 @@
/*
* SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: GPL-2.0-or-later
*/
import FileProvider
import NextcloudFileProviderKit
import OSLog
extension FileProviderExtension: NSFileProviderCustomAction {
func performAction(
identifier actionIdentifier: NSFileProviderExtensionActionIdentifier,
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
}
}

View File

@ -10,6 +10,25 @@
<string>$(OC_APPLICATION_REV_DOMAIN).$(PRODUCT_NAME)</string>
<key>NSExtension</key>
<dict>
<key>NSExtensionFileProviderActions</key>
<array>
<dict>
<key>NSExtensionFileProviderActionActivationRule</key>
<string>SUBQUERY ( fileproviderItems, $fileproviderItem, $fileproviderItem.userInfo.displayKeepDownloaded == true ).@count &gt; 0</string>
<key>NSExtensionFileProviderActionIdentifier</key>
<string>com.nextcloud.desktopclient.FileProviderExt.KeepDownloadedAction</string>
<key>NSExtensionFileProviderActionName</key>
<string>Always keep downloaded</string>
</dict>
<dict>
<key>NSExtensionFileProviderActionActivationRule</key>
<string>SUBQUERY ( fileproviderItems, $fileproviderItem, $fileproviderItem.userInfo.displayAllowAutoEvicting == true ).@count &gt; 0</string>
<key>NSExtensionFileProviderActionIdentifier</key>
<string>com.nextcloud.desktopclient.FileProviderExt.AutoEvictAction</string>
<key>NSExtensionFileProviderActionName</key>
<string>Allow automatic freeing up space</string>
</dict>
</array>
<key>NSExtensionFileProviderDocumentGroup</key>
<string>$(OC_SOCKETAPI_TEAM_IDENTIFIER_PREFIX)$(OC_APPLICATION_REV_DOMAIN)</string>
<key>NSExtensionFileProviderSupportsEnumeration</key>

View File

@ -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 = "<group>"; };
531522812B8E01C6002E31BE /* ShareTableItemView.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = ShareTableItemView.xib; sourceTree = "<group>"; };
531EDE562D897B4F00FD91F9 /* Eviction.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Eviction.swift; sourceTree = "<group>"; };
5350E4E72B0C514400F276CB /* ClientCommunicationProtocol.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ClientCommunicationProtocol.h; sourceTree = "<group>"; };
@ -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 */,
);