diff --git a/shell_integration/MacOSX/CMakeLists.txt b/shell_integration/MacOSX/CMakeLists.txt index a3f561484a..a9f0597978 100644 --- a/shell_integration/MacOSX/CMakeLists.txt +++ b/shell_integration/MacOSX/CMakeLists.txt @@ -69,9 +69,17 @@ if(APPLE) DESTINATION ${OSX_PLUGINS_INSTALL_DIR} USE_SOURCE_PERMISSIONS) + install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/${XCODE_TARGET_CONFIGURATION}/PackageFrameworks/RealmSwift.framework + DESTINATION ${OSX_PLUGINS_INSTALL_DIR}/FileProviderExt.appex/Contents/Frameworks + USE_SOURCE_PERMISSIONS) + install(DIRECTORY ${OSX_PLUGINS_BINARY_DIR}/FileProviderUIExt.appex - DESTINATION ${OSX_PLUGINS_INSTALL_DIR} - USE_SOURCE_PERMISSIONS) + DESTINATION ${OSX_PLUGINS_INSTALL_DIR} + USE_SOURCE_PERMISSIONS) + + install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/${XCODE_TARGET_CONFIGURATION}/PackageFrameworks/RealmSwift.framework + DESTINATION ${OSX_PLUGINS_INSTALL_DIR}/FileProviderUIExt.appex/Contents/Frameworks + USE_SOURCE_PERMISSIONS) endif() endif() endif() diff --git a/shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/FileProviderExtension+ClientInterface.swift b/shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/FileProviderExtension+ClientInterface.swift index 03da389c8e..32d7552548 100644 --- a/shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/FileProviderExtension+ClientInterface.swift +++ b/shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/FileProviderExtension+ClientInterface.swift @@ -149,6 +149,7 @@ extension FileProviderExtension: NSFileProviderServicing, ChangeNotificationInte Task { @MainActor in ncAccount = account + dbManager = FilesDatabaseManager(account: account) changeObserver = RemoteChangeObserver( account: account, remoteInterface: ncKit, @@ -166,6 +167,7 @@ extension FileProviderExtension: NSFileProviderServicing, ChangeNotificationInte "Received instruction to remove account data for user \(self.ncAccount!.username, privacy: .public) at server \(self.ncAccount!.serverUrl, privacy: .public)" ) ncAccount = nil + dbManager = nil } func updatedSyncStateReporting(oldActions: Set) { diff --git a/shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/FileProviderExtension+Thumbnailing.swift b/shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/FileProviderExtension+Thumbnailing.swift index 9fb0f0edac..f608f5acf7 100644 --- a/shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/FileProviderExtension+Thumbnailing.swift +++ b/shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/FileProviderExtension+Thumbnailing.swift @@ -24,12 +24,17 @@ extension FileProviderExtension: NSFileProviderThumbnailing { completionHandler(NSFileProviderError(.notAuthenticated)) return Progress() } + guard let dbManager else { + completionHandler(NSFileProviderError(.cannotSynchronize)) + return Progress() + } return NextcloudFileProviderKit.fetchThumbnails( for: itemIdentifiers, requestedSize: size, account: ncAccount, usingRemoteInterface: self.ncKit, + andDatabase: dbManager, perThumbnailCompletionHandler: perThumbnailCompletionHandler, completionHandler: completionHandler ) diff --git a/shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/FileProviderExtension.swift b/shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/FileProviderExtension.swift index 9f9acf6311..bfa024c423 100644 --- a/shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/FileProviderExtension.swift +++ b/shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/FileProviderExtension.swift @@ -14,6 +14,7 @@ import OSLog let ncKit = NextcloudKit.shared let appGroupIdentifier = Bundle.main.object(forInfoDictionaryKey: "SocketApiPrefix") as? String var ncAccount: Account? + var dbManager: FilesDatabaseManager? var changeObserver: RemoteChangeObserver? lazy var ncKitBackground = NKBackground(nkCommonInstance: ncKit.nkCommonInstance) lazy var socketClient: LocalSocketClient? = { @@ -105,9 +106,19 @@ import OSLog completionHandler(nil, NSFileProviderError(.notAuthenticated)) return Progress() } + guard let dbManager else { + Logger.fileProviderExtension.error( + """ + Not fetching item for identifier: \(identifier.rawValue, privacy: .public) + as database is unreachable + """ + ) + completionHandler(nil, NSFileProviderError(.cannotSynchronize)) + return Progress() + } if let item = Item.storedItem( - identifier: identifier, account: ncAccount, remoteInterface: ncKit + identifier: identifier, account: ncAccount, remoteInterface: ncKit, dbManager: dbManager ) { completionHandler(item, nil) } else { @@ -154,9 +165,22 @@ import OSLog completionHandler(nil, nil, NSFileProviderError(.notAuthenticated)) return Progress() } + guard let dbManager else { + Logger.fileProviderExtension.error( + """ + Not fetching contents for item: \(itemIdentifier.rawValue, privacy: .public) + as database is unreachable + """ + ) + completionHandler(nil, nil, NSFileProviderError(.cannotSynchronize)) + return Progress() + } guard let item = Item.storedItem( - identifier: itemIdentifier, account: ncAccount, remoteInterface: ncKit + identifier: itemIdentifier, + account: ncAccount, + remoteInterface: ncKit, + dbManager: dbManager ) else { Logger.fileProviderExtension.error( """ @@ -172,7 +196,7 @@ import OSLog let progress = Progress() Task { let (localUrl, updatedItem, error) = await item.fetchContents( - domain: self.domain, progress: progress + domain: self.domain, progress: progress, dbManager: dbManager ) removeSyncAction(actionId) completionHandler(localUrl, updatedItem, error) @@ -209,12 +233,19 @@ import OSLog """ ) insertErrorAction(actionId) - completionHandler( - itemTemplate, - NSFileProviderItemFields(), - false, - NSFileProviderError(.notAuthenticated) + completionHandler(itemTemplate, [], false, NSFileProviderError(.notAuthenticated)) + return Progress() + } + + guard let dbManager else { + Logger.fileProviderExtension.error( + """ + Not creating item: \(itemTemplate.itemIdentifier.rawValue, privacy: .public) + as database is unreachable + """ ) + insertErrorAction(actionId) + completionHandler(itemTemplate, [], false, NSFileProviderError(.cannotSynchronize)) return Progress() } @@ -228,7 +259,8 @@ import OSLog domain: self.domain, account: ncAccount, remoteInterface: ncKit, - progress: progress + progress: progress, + dbManager: dbManager ) if error != nil { @@ -282,8 +314,22 @@ import OSLog return Progress() } + + guard let dbManager else { + Logger.fileProviderExtension.error( + """ + Not modifying item: \(ocId, privacy: .public) + with filename: \(item.filename, privacy: .public) + as database is unreachable + """ + ) + insertErrorAction(actionId) + completionHandler(item, [], false, NSFileProviderError(.cannotSynchronize)) + return Progress() + } + guard let existingItem = Item.storedItem( - identifier: identifier, account: ncAccount, remoteInterface: ncKit + identifier: identifier, account: ncAccount, remoteInterface: ncKit, dbManager: dbManager ) else { Logger.fileProviderExtension.error( "Not modifying item: \(ocId, privacy: .public) as item not found." @@ -303,7 +349,8 @@ import OSLog options: options, request: request, domain: domain, - progress: progress + progress: progress, + dbManager: dbManager ) if error != nil { @@ -341,8 +388,17 @@ import OSLog return Progress() } + guard let dbManager else { + Logger.fileProviderExtension.error( + "Not deleting item \(identifier.rawValue, privacy: .public), db manager unavailable" + ) + insertErrorAction(actionId) + completionHandler(NSFileProviderError(.cannotSynchronize)) + return Progress() + } + guard let item = Item.storedItem( - identifier: identifier, account: ncAccount, remoteInterface: ncKit + identifier: identifier, account: ncAccount, remoteInterface: ncKit, dbManager: dbManager ) else { Logger.fileProviderExtension.error( "Not deleting item \(identifier.rawValue, privacy: .public), item not found" @@ -354,7 +410,7 @@ import OSLog let progress = Progress(totalUnitCount: 1) Task { - let error = await item.delete() + let error = await item.delete(dbManager: dbManager) if error != nil { insertErrorAction(actionId) signalEnumerator(completionHandler: { _ in }) @@ -372,15 +428,31 @@ import OSLog ) throws -> NSFileProviderEnumerator { guard let ncAccount else { Logger.fileProviderExtension.error( - "Not providing enumerator for container with identifier \(containerItemIdentifier.rawValue, privacy: .public) yet as account not set up" + """ + Not providing enumerator for container + with identifier \(containerItemIdentifier.rawValue, privacy: .public) yet + as account not set up + """ ) throw NSFileProviderError(.notAuthenticated) } + guard let dbManager else { + Logger.fileProviderExtension.error( + """ + Not providing enumerator for container + with identifier \(containerItemIdentifier.rawValue, privacy: .public) yet + as db manager is unavailable + """ + ) + throw NSFileProviderError(.cannotSynchronize) + } + return Enumerator( enumeratedItemIdentifier: containerItemIdentifier, account: ncAccount, remoteInterface: ncKit, + dbManager: dbManager, domain: domain, fastEnumeration: config.fastEnumerationEnabled ) @@ -394,6 +466,17 @@ import OSLog return } + guard let dbManager else { + Logger.fileProviderExtension.error( + """ + Not purging stale local file metadatas. + db manager unabilable for domain: \(self.domain.displayName, privacy: .public) + """ + ) + completionHandler() + return + } + guard let fpManager = NSFileProviderManager(for: domain) else { Logger.fileProviderExtension.error( "Could not get file provider manager for domain: \(self.domain.displayName, privacy: .public)" @@ -404,7 +487,7 @@ import OSLog let materialisedEnumerator = fpManager.enumeratorForMaterializedItems() let materialisedObserver = MaterialisedEnumerationObserver( - ncKitAccount: ncAccount.ncKitAccount + ncKitAccount: ncAccount.ncKitAccount, dbManager: dbManager ) { _ in completionHandler() } diff --git a/shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/Services/FPUIExtensionServiceSource.swift b/shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/Services/FPUIExtensionServiceSource.swift index 5b8fd45751..9db037f269 100644 --- a/shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/Services/FPUIExtensionServiceSource.swift +++ b/shell_integration/MacOSX/NextcloudIntegration/FileProviderExt/Services/FPUIExtensionServiceSource.swift @@ -53,7 +53,14 @@ class FPUIExtensionServiceSource: NSObject, NSFileProviderServiceSource, NSXPCLi return nil } - let dbManager = FilesDatabaseManager.shared + guard let account = fpExtension.ncAccount?.ncKitAccount else { + Logger.shares.error("Could not fetch ncKitAccount on parent extension") + return nil + } + guard let dbManager = fpExtension.dbManager else { + Logger.shares.error("Could not get db manager for \(account, privacy: .public)") + return nil + } guard let item = dbManager.itemMetadataFromFileProviderItemIdentifier(identifier) else { Logger.shares.error("No item \(rawIdentifier, privacy: .public) in db, no shares.") return nil diff --git a/shell_integration/MacOSX/NextcloudIntegration/NextcloudIntegration.xcodeproj/project.pbxproj b/shell_integration/MacOSX/NextcloudIntegration/NextcloudIntegration.xcodeproj/project.pbxproj index 4fd49162ff..ce29a33758 100644 --- a/shell_integration/MacOSX/NextcloudIntegration/NextcloudIntegration.xcodeproj/project.pbxproj +++ b/shell_integration/MacOSX/NextcloudIntegration/NextcloudIntegration.xcodeproj/project.pbxproj @@ -1072,6 +1072,7 @@ LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", + "@executable_path/../Frameworks", "@executable_path/../../Frameworks", ); LOCALIZATION_PREFERS_STRING_CATALOGS = YES; @@ -1132,6 +1133,7 @@ LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", + "@executable_path/../Frameworks", "@executable_path/../../Frameworks", ); LOCALIZATION_PREFERS_STRING_CATALOGS = YES; @@ -1528,7 +1530,7 @@ isa = XCRemoteSwiftPackageReference; repositoryURL = "https://github.com/claucambra/NextcloudFileProviderKit.git"; requirement = { - branch = "stable-2.0"; + branch = "stable-2.1"; kind = branch; }; };