diff --git a/Sources/NextcloudKit/NKCommon.swift b/Sources/NextcloudKit/NKCommon.swift index 8e5f67a7..db20a135 100644 --- a/Sources/NextcloudKit/NKCommon.swift +++ b/Sources/NextcloudKit/NKCommon.swift @@ -78,8 +78,6 @@ public struct NKCommon: Sendable { public let groupDefaultsUnavailable = "Unavailable" public let groupDefaultsToS = "ToS" - - // MARK: - Init init() { } @@ -200,11 +198,11 @@ public struct NKCommon: Sendable { // MARK: - Server Error GroupDefaults - public func appendServerErrorAccount(_ account: String, errorCode: Int) { + public func appendServerErrorAccount(_ account: String, errorCode: Int) async { guard let groupDefaults = UserDefaults(suiteName: groupIdentifier) else { return } - let capabilities = NKCapabilities.shared.getCapabilitiesBlocking(for: account) + let capabilities = await NKCapabilities.shared.getCapabilities(for: account) /// Unavailable if errorCode == 503 { @@ -239,8 +237,6 @@ public struct NKCommon: Sendable { return "\(identifier).\(account)" } - - public func getStandardHeaders(account: String, options: NKRequestOptions? = nil) -> HTTPHeaders? { guard let session = nksessions.session(forAccount: account) else { return nil diff --git a/Sources/NextcloudKit/NKMonitor.swift b/Sources/NextcloudKit/NKMonitor.swift index e579130e..863939ea 100644 --- a/Sources/NextcloudKit/NKMonitor.swift +++ b/Sources/NextcloudKit/NKMonitor.swift @@ -41,7 +41,9 @@ final class NKMonitor: EventMonitor, Sendable { let headerCheckInterceptor = request.request?.allHTTPHeaderFields?[nkCommonInstance.headerCheckInterceptor], headerCheckInterceptor.lowercased() == "true", let account = request.request?.allHTTPHeaderFields?[nkCommonInstance.headerAccount] { - nkCommonInstance.appendServerErrorAccount(account, errorCode: statusCode) + Task { + await nkCommonInstance.appendServerErrorAccount(account, errorCode: statusCode) + } } DispatchQueue.global(qos: .utility).async { diff --git a/Sources/NextcloudKit/NextcloudKit+Capabilities.swift b/Sources/NextcloudKit/NextcloudKit+Capabilities.swift index 8c116459..7b75fdb2 100644 --- a/Sources/NextcloudKit/NextcloudKit+Capabilities.swift +++ b/Sources/NextcloudKit/NextcloudKit+Capabilities.swift @@ -410,7 +410,7 @@ public extension NextcloudKit { capabilities.termsOfService = json.termsOfService?.enabled ?? false // Persist capabilities in shared store - await NKCapabilities.shared.appendCapabilitiesAsync(for: account, capabilities: capabilities) + await NKCapabilities.shared.setCapabilities(for: account, capabilities: capabilities) return capabilities } catch { nkLog(error: "Could not decode json capabilities: \(error.localizedDescription)") @@ -490,49 +490,14 @@ final public class NKCapabilities: Sendable { // MARK: - Public API - public func appendCapabilitiesAsync(for account: String, capabilities: Capabilities) async { + public func setCapabilities(for account: String, capabilities: Capabilities) async { await store.set(account, value: capabilities) } - /// Synchronously stores capabilities for the given account. - /// Blocks the current thread until the async actor completes. - /// Use only outside of async/actor contexts. - public func appendCapabilitiesBlocking(for account: String, capabilities: Capabilities) { - let group = DispatchGroup() - - group.enter() - Task.detached(priority: .userInitiated) { - await self.store.set(account, value: capabilities) - group.leave() - } - - group.wait() - } - - public func getCapabilitiesAsync(for account: String?) async -> Capabilities { + public func getCapabilities(for account: String?) async -> Capabilities { guard let account else { return Capabilities() } return await store.get(account) ?? Capabilities() } - - /// Synchronously retrieves capabilities for the given account. - /// Blocks the current thread until the async actor returns. - /// Use only outside the Swift async context (never from another actor or async function). - public func getCapabilitiesBlocking(for account: String?) -> Capabilities { - guard let account else { - return Capabilities() - } - let group = DispatchGroup() - var result: Capabilities? - - group.enter() - Task.detached(priority: .userInitiated) { - result = await self.store.get(account) - group.leave() - } - - group.wait() - return result ?? Capabilities() - } } diff --git a/Sources/NextcloudKit/NextcloudKit+NCText.swift b/Sources/NextcloudKit/NextcloudKit+NCText.swift index 03b61d5b..99c5e1d3 100644 --- a/Sources/NextcloudKit/NextcloudKit+NCText.swift +++ b/Sources/NextcloudKit/NextcloudKit+NCText.swift @@ -37,10 +37,10 @@ public extension NextcloudKit { Task { do { let (editors, creators) = try NKEditorDetailsConverter.from(data: responseData) - let capabilities = await NKCapabilities.shared.getCapabilitiesAsync(for: account) + let capabilities = await NKCapabilities.shared.getCapabilities(for: account) capabilities.directEditingEditors = editors capabilities.directEditingCreators = creators - await NKCapabilities.shared.appendCapabilitiesAsync(for: account, capabilities: capabilities) + await NKCapabilities.shared.setCapabilities(for: account, capabilities: capabilities) options.queue.async { completion(account, editors, creators, response, .success) @@ -206,10 +206,10 @@ public extension NextcloudKit { let decoded = try JSONDecoder().decode(NKEditorTemplateResponse.self, from: data) let templates = decoded.ocs.data.editors // Update capabilities - let capabilities = await NKCapabilities.shared.getCapabilitiesAsync(for: account) + let capabilities = await NKCapabilities.shared.getCapabilities(for: account) capabilities.directEditingTemplates = templates - await NKCapabilities.shared.appendCapabilitiesAsync(for: account, capabilities: capabilities) - + await NKCapabilities.shared.setCapabilities(for: account, capabilities: capabilities) + options.queue.async { completion(account, templates, response, .success) } } catch { nkLog(error: "Failed to decode template list: \(error)") diff --git a/Sources/NextcloudKit/TypeIdentifiers/NKFilePropertyResolver.swift b/Sources/NextcloudKit/TypeIdentifiers/NKFilePropertyResolver.swift index d4304476..91c3e2e9 100644 --- a/Sources/NextcloudKit/TypeIdentifiers/NKFilePropertyResolver.swift +++ b/Sources/NextcloudKit/TypeIdentifiers/NKFilePropertyResolver.swift @@ -44,10 +44,10 @@ public final class NKFilePropertyResolver { public init() {} - public func resolve(inUTI: String, account: String) -> NKFileProperty { + public func resolve(inUTI: String, account: String) async -> NKFileProperty { let fileProperty = NKFileProperty() let typeIdentifier = inUTI as String - let capabilities = NKCapabilities.shared.getCapabilitiesBlocking(for: account) + let capabilities = await NKCapabilities.shared.getCapabilities(for: account) let utiString = inUTI as String // Preferred extension diff --git a/Sources/NextcloudKit/TypeIdentifiers/NKTypeIdentifiers.swift b/Sources/NextcloudKit/TypeIdentifiers/NKTypeIdentifiers.swift index edf08cb0..de244286 100644 --- a/Sources/NextcloudKit/TypeIdentifiers/NKTypeIdentifiers.swift +++ b/Sources/NextcloudKit/TypeIdentifiers/NKTypeIdentifiers.swift @@ -26,8 +26,7 @@ public actor NKTypeIdentifiers { private init() {} // Resolves type info from file name and optional MIME type - public func getInternalType(fileName: String, mimeType inputMimeType: String, directory: Bool, account: String) -> NKTypeIdentifierCache { - + public func getInternalType(fileName: String, mimeType inputMimeType: String, directory: Bool, account: String) async -> NKTypeIdentifierCache { var ext = (fileName as NSString).pathExtension.lowercased() var mimeType = inputMimeType var classFile = "" @@ -63,7 +62,7 @@ public actor NKTypeIdentifiers { fileNameWithoutExt = fileName ext = "" } else { - let props = resolver.resolve(inUTI: typeIdentifier, account: account) + let props = await resolver.resolve(inUTI: typeIdentifier, account: account) classFile = props.classFile.rawValue iconName = props.iconName.rawValue } @@ -91,39 +90,3 @@ public actor NKTypeIdentifiers { filePropertyCache.removeAll() } } - -/// Helper class to access NKTypeIdentifiers from sync contexts (e.g. in legacy code or libraries). -public final class NKTypeIdentifiersHelper { - public static let shared = NKTypeIdentifiersHelper() - - // Internal actor reference (uses NKTypeIdentifiers.shared by default) - private let actor: NKTypeIdentifiers - - private init() { - self.actor = .shared - } - - // Init with optional custom actor (useful for testing) - public init(actor: NKTypeIdentifiers = .shared) { - self.actor = actor - } - - // Synchronously resolves file type info by calling the async actor inside a semaphore block. - public func getInternalTypeSync(fileName: String, mimeType: String, directory: Bool, account: String) -> NKTypeIdentifierCache { - var result: NKTypeIdentifierCache? - let semaphore = DispatchSemaphore(value: 0) - - Task { - result = await actor.getInternalType( - fileName: fileName, - mimeType: mimeType, - directory: directory, - account: account - ) - semaphore.signal() - } - - semaphore.wait() - return result! - } -}