Skip to content

Commit

Permalink
Merge pull request #7824 from nextcloud/feature/ncfpk-2.0
Browse files Browse the repository at this point in the history
shell_integration/macOS: Upgrade to NextcloudFileProviderKit 2.0
  • Loading branch information
mgallien authored Feb 6, 2025
2 parents 6b7cf3f + bfe9a97 commit ac9af29
Show file tree
Hide file tree
Showing 11 changed files with 137 additions and 73 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -107,14 +107,25 @@ extension FileProviderExtension: NSFileProviderServicing, ChangeNotificationInte
@objc func setupDomainAccount(
user: String, userId: String, serverUrl: String, password: String
) {
let account = Account(user: user, id: userId, serverUrl: serverUrl, password: password)
guard account != ncAccount else { return }

Task {
let authTestNcKit = NextcloudKit()
authTestNcKit.setup(user: user, userId: userId, password: password, urlBase: serverUrl)
ncKit.appendSession(
account: account.ncKitAccount,
urlBase: serverUrl,
user: user,
userId: userId,
password: password,
userAgent: "Nextcloud-macOS/FileProviderExt",
nextcloudVersion: 25,
groupIdentifier: ""
)
var authAttemptState = AuthenticationAttemptResultState.connectionError // default

// Retry a few times if we have a connection issue
for authTimeout in AuthenticationTimeouts {
authAttemptState = await authTestNcKit.tryAuthenticationAttempt()
authAttemptState = await ncKit.tryAuthenticationAttempt(account: account)
guard authAttemptState == .connectionError else { break }

Logger.fileProviderExtension.info(
Expand Down Expand Up @@ -146,22 +157,12 @@ extension FileProviderExtension: NSFileProviderServicing, ChangeNotificationInte
}

Task { @MainActor in
let newNcAccount =
Account(user: user, id: userId, serverUrl: serverUrl, password: password)
guard newNcAccount != ncAccount else { return }
ncAccount = newNcAccount
ncKit.setup(
account: newNcAccount.ncKitAccount,
user: newNcAccount.username,
userId: newNcAccount.id,
password: newNcAccount.password,
urlBase: newNcAccount.serverUrl,
userAgent: "Nextcloud-macOS/FileProviderExt",
nextcloudVersion: 25,
delegate: nil) // TODO: add delegate methods for self

ncAccount = account
changeObserver = RemoteChangeObserver(
remoteInterface: ncKit, changeNotificationInterface: self, domain: domain
account: account,
remoteInterface: ncKit,
changeNotificationInterface: self,
domain: domain
)
ncKit.setup(delegate: changeObserver)
signalEnumeratorAfterAccountSetup()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,15 @@ extension FileProviderExtension: NSFileProviderThumbnailing {
) -> Void,
completionHandler: @escaping (Error?) -> Void
) -> Progress {
guard let ncAccount else {
completionHandler(NSFileProviderError(.notAuthenticated))
return Progress()
}

return NextcloudFileProviderKit.fetchThumbnails(
for: itemIdentifiers,
requestedSize: size,
account: ncAccount,
usingRemoteInterface: self.ncKit,
perThumbnailCompletionHandler: perThumbnailCompletionHandler,
completionHandler: completionHandler
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import OSLog

@objc class FileProviderExtension: NSObject, NSFileProviderReplicatedExtension {
let domain: NSFileProviderDomain
let ncKit = NextcloudKit()
let ncKit = NextcloudKit.shared
let appGroupIdentifier = Bundle.main.object(forInfoDictionaryKey: "SocketApiPrefix") as? String
var ncAccount: Account?
var changeObserver: RemoteChangeObserver?
Expand Down Expand Up @@ -104,15 +104,20 @@ import OSLog
request _: NSFileProviderRequest,
completionHandler: @escaping (NSFileProviderItem?, Error?) -> Void
) -> Progress {
if ncAccount == nil {
guard let ncAccount else {
Logger.fileProviderExtension.error(
"""
Not fetching item for identifier: \(identifier.rawValue, privacy: .public)
as account not set up yet.
"""
)
completionHandler(nil, NSFileProviderError(.notAuthenticated))
} else if let item = Item.storedItem(identifier: identifier, remoteInterface: ncKit) {
return Progress()
}

if let item = Item.storedItem(
identifier: identifier, account: ncAccount, remoteInterface: ncKit
) {
completionHandler(item, nil)
} else {
completionHandler(nil, NSFileProviderError(.noSuchItem))
Expand Down Expand Up @@ -147,7 +152,7 @@ import OSLog
return Progress()
}

guard ncAccount != nil else {
guard let ncAccount else {
Logger.fileProviderExtension.error(
"""
Not fetching contents for item: \(itemIdentifier.rawValue, privacy: .public)
Expand All @@ -159,7 +164,9 @@ import OSLog
return Progress()
}

guard let item = Item.storedItem(identifier: itemIdentifier, remoteInterface: ncKit) else {
guard let item = Item.storedItem(
identifier: itemIdentifier, account: ncAccount, remoteInterface: ncKit
) else {
Logger.fileProviderExtension.error(
"""
Not fetching contents for item: \(itemIdentifier.rawValue, privacy: .public)
Expand Down Expand Up @@ -228,6 +235,7 @@ import OSLog
contents: url,
request: request,
domain: self.domain,
account: ncAccount,
remoteInterface: ncKit,
progress: progress
)
Expand Down Expand Up @@ -283,7 +291,9 @@ import OSLog
return Progress()
}

guard let existingItem = Item.storedItem(identifier: identifier, remoteInterface: ncKit) else {
guard let existingItem = Item.storedItem(
identifier: identifier, account: ncAccount, remoteInterface: ncKit
) else {
Logger.fileProviderExtension.error(
"Not modifying item: \(ocId, privacy: .public) as item not found."
)
Expand Down Expand Up @@ -331,7 +341,7 @@ import OSLog
"Received delete request for item: \(identifier.rawValue, privacy: .public)"
)

guard ncAccount != nil else {
guard let ncAccount else {
Logger.fileProviderExtension.error(
"Not deleting item \(identifier.rawValue, privacy: .public), account not set up yet"
)
Expand All @@ -340,7 +350,9 @@ import OSLog
return Progress()
}

guard let item = Item.storedItem(identifier: identifier, remoteInterface: ncKit) else {
guard let item = Item.storedItem(
identifier: identifier, account: ncAccount, remoteInterface: ncKit
) else {
Logger.fileProviderExtension.error(
"Not deleting item \(identifier.rawValue, privacy: .public), item not found"
)
Expand All @@ -359,7 +371,7 @@ import OSLog
removeSyncAction(actionId)
}
progress.completedUnitCount = 1
completionHandler(await item.delete())
completionHandler(error)
}
return progress
}
Expand All @@ -376,6 +388,7 @@ import OSLog

return Enumerator(
enumeratedItemIdentifier: containerItemIdentifier,
account: ncAccount,
remoteInterface: ncKit,
domain: domain,
fastEnumeration: config.fastEnumerationEnabled,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -157,16 +157,20 @@ class LockViewController: NSViewController {
return
}
let serverPathString = serverPath as String
let kit = NextcloudKit()
kit.setup(
let kit = NextcloudKit.shared
kit.appendSession(
account: account.ncKitAccount,
urlBase: account.serverUrl,
user: account.username,
userId: account.username,
userId: account.id,
password: account.password,
urlBase: account.serverUrl
userAgent: "Nextcloud-macOS/FileProviderUIExt",
nextcloudVersion: 25,
groupIdentifier: ""
)
// guard let capabilities = await fetchCapabilities() else {
guard let itemMetadata = await fetchItemMetadata(
itemRelativePath: serverPathString, kit: kit
itemRelativePath: serverPathString, account: account, kit: kit
) else {
presentError("Could not get item metadata.")
return
Expand Down Expand Up @@ -200,7 +204,8 @@ class LockViewController: NSViewController {
kit.lockUnlockFile(
serverUrlFileName: serverUrlFileName,
shouldLock: locking,
completion: { _, error in
account: account.ncKitAccount,
completion: { _, _, error in
continuation.resume(returning: error)
}
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,13 @@
//

import Foundation
import NextcloudFileProviderKit
import NextcloudKit
import OSLog

func fetchItemMetadata(itemRelativePath: String, kit: NextcloudKit) async -> NKFile? {
func fetchItemMetadata(
itemRelativePath: String, account: Account, kit: NextcloudKit
) async -> NKFile? {
func slashlessPath(_ string: String) -> String {
var strCopy = string
if strCopy.hasPrefix("/") {
Expand All @@ -21,15 +24,21 @@ func fetchItemMetadata(itemRelativePath: String, kit: NextcloudKit) async -> NKF
return strCopy
}

let nkCommon = kit.nkCommonInstance
let urlBase = slashlessPath(nkCommon.urlBase)
let davSuffix = slashlessPath(nkCommon.dav)
let userId = nkCommon.userId
guard let nksession = kit.getSession(account: account.ncKitAccount) else {
Logger.metadataProvider.error("Could not get nksession for \(account.ncKitAccount)")
return nil
}

let urlBase = slashlessPath(nksession.urlBase)
let davSuffix = slashlessPath(nksession.dav)
let userId = nksession.userId
let itemRelPath = slashlessPath(itemRelativePath)

let itemFullServerPath = "\(urlBase)/\(davSuffix)/files/\(userId)/\(itemRelPath)"
return await withCheckedContinuation { continuation in
kit.readFileOrFolder(serverUrlFileName: itemFullServerPath, depth: "0") {
kit.readFileOrFolder(
serverUrlFileName: itemFullServerPath, depth: "0", account: account.ncKitAccount
) {
account, files, data, error in
guard error == .success else {
Logger.metadataProvider.error(
Expand All @@ -39,7 +48,7 @@ func fetchItemMetadata(itemRelativePath: String, kit: NextcloudKit) async -> NKF
return
}
Logger.metadataProvider.info("Successfully retrieved item metadata")
continuation.resume(returning: files.first)
continuation.resume(returning: files?.first)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,17 @@

import Combine
import Foundation
import NextcloudFileProviderKit
import NextcloudKit
import OSLog

class ShareController: ObservableObject {
@Published private(set) var share: NKShare
private let kit: NextcloudKit
private let account: Account

static func create(
account: Account,
kit: NextcloudKit,
shareType: NKShare.ShareType,
itemServerRelativePath: String,
Expand All @@ -38,6 +41,7 @@ class ShareController: ObservableObject {
publicUpload: publicUpload,
password: password,
permissions: permissions,
account: account.ncKitAccount,
options: options
) { account, share, data, error in
defer { continuation.resume(returning: error) }
Expand Down Expand Up @@ -65,8 +69,8 @@ class ShareController: ObservableObject {
shareWith: shareWith,
password: password,
permissions: permissions,
options: options,
attributes: attributes
attributes: attributes,
account: account.ncKitAccount
) { account, share, data, error in
defer { continuation.resume(returning: error) }
guard error == .success else {
Expand All @@ -82,7 +86,8 @@ class ShareController: ObservableObject {
}
}

init(share: NKShare, kit: NextcloudKit) {
init(share: NKShare, account: Account, kit: NextcloudKit) {
self.account = account
self.share = share
self.kit = kit
}
Expand Down Expand Up @@ -110,6 +115,7 @@ class ShareController: ObservableObject {
label: label,
hideDownload: hideDownload,
attributes: attributes,
account: account.ncKitAccount,
options: options
) { account, share, data, error in
Logger.shareController.info(
Expand All @@ -134,7 +140,9 @@ class ShareController: ObservableObject {
func delete() async -> NKError? {
Logger.shareController.info("Deleting share: \(self.share.url, privacy: .public)")
return await withCheckedContinuation { continuation in
kit.deleteShare(idShare: share.idShare) { account, error in
kit.deleteShare(
idShare: share.idShare, account: account.ncKitAccount
) { account, _, error in
Logger.shareController.info(
"""
Received delete response: \(self.share.url, privacy: .public)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

import AppKit
import Combine
import NextcloudFileProviderKit
import NextcloudKit
import OSLog
import SuggestionsTextFieldKit
Expand Down Expand Up @@ -34,16 +35,17 @@ class ShareOptionsView: NSView {
@IBOutlet private weak var circleShare: NSMenuItem!
@IBOutlet private weak var talkConversationShare: NSMenuItem!

var kit: NextcloudKit? {
let kit = NextcloudKit.shared
var account: Account? {
didSet {
Logger.shareOptionsView.info("Setting up the kit.")
guard let kit = kit else {
Logger.shareOptionsView.info("Setting up account.")
guard let account else {
Logger.shareOptionsView.error("Could not configure suggestions data source.")
return
}

suggestionsTextFieldDelegate.suggestionsDataSource = ShareeSuggestionsDataSource(
kit: kit
account: account, kit: kit
)
suggestionsTextFieldDelegate.confirmationHandler = { suggestion in
guard let sharee = suggestion?.data as? NKSharee else { return }
Expand Down Expand Up @@ -255,13 +257,13 @@ class ShareOptionsView: NSView {
guard !createMode else {
Logger.shareOptionsView.info("Creating new share!")

guard let dataSource = dataSource,
let kit = kit,
guard let dataSource,
let account,
let itemServerRelativePath = dataSource.itemServerRelativePath
else {
Logger.shareOptionsView.error("Cannot create new share due to missing data.")
Logger.shareOptionsView.error("dataSource: \(self.dataSource, privacy: .public)")
Logger.shareOptionsView.error("kit: \(self.kit, privacy: .public)")
Logger.shareOptionsView.error("account: \(self.account != nil, privacy: .public)")
Logger.shareOptionsView.error(
"path: \(self.dataSource?.itemServerRelativePath ?? "", privacy: .public)"
)
Expand All @@ -280,6 +282,7 @@ class ShareOptionsView: NSView {
deleteButton.isEnabled = false
saveButton.isEnabled = false
let error = await ShareController.create(
account: account,
kit: kit,
shareType: selectedShareType,
itemServerRelativePath: itemServerRelativePath,
Expand Down
Loading

0 comments on commit ac9af29

Please sign in to comment.