diff --git a/Sources/NextcloudKit/Models/DirectEditing/NKDirectEditingCapabilitiesConverter.swift b/Sources/NextcloudKit/Models/DirectEditing/NKDirectEditingCapabilitiesConverter.swift new file mode 100644 index 00000000..911dedf7 --- /dev/null +++ b/Sources/NextcloudKit/Models/DirectEditing/NKDirectEditingCapabilitiesConverter.swift @@ -0,0 +1,24 @@ +// SPDX-FileCopyrightText: Nextcloud GmbH +// SPDX-FileCopyrightText: 2025 Marino Faggiana +// SPDX-License-Identifier: GPL-3.0-or-later + +import Foundation + +public enum NKDirectEditingCapabilitiesConverter { + + /// Parses and converts raw JSON `Data` into `[NKDirectEditingEditor]` and `[NKDirectEditingCreator]`. + /// - Parameter data: Raw JSON `Data` from the editors/creators endpoint. + /// - Returns: A tuple with editors and creators. + /// - Throws: Decoding error if parsing fails. + public static func from(data: Data) throws -> (editors: [NKDirectEditingEditor], creators: [NKDirectEditingCreator]) { + let decoded = try JSONDecoder().decode(NKDirectEditingCapabilitiesResponse.self, from: data) + let editors = Array(decoded.ocs.data.editors.values) + let creators = Array(decoded.ocs.data.creators.values) + + if NKLogFileManager.shared.logLevel == .verbose { + data.printJson() + } + + return (editors, creators) + } +} diff --git a/Sources/NextcloudKit/Models/EditorDetails/NKEditorDetailsResponse.swift b/Sources/NextcloudKit/Models/DirectEditing/NKDirectEditingCapabilitiesResponse.swift similarity index 61% rename from Sources/NextcloudKit/Models/EditorDetails/NKEditorDetailsResponse.swift rename to Sources/NextcloudKit/Models/DirectEditing/NKDirectEditingCapabilitiesResponse.swift index 72055382..7292061d 100644 --- a/Sources/NextcloudKit/Models/EditorDetails/NKEditorDetailsResponse.swift +++ b/Sources/NextcloudKit/Models/DirectEditing/NKDirectEditingCapabilitiesResponse.swift @@ -4,32 +4,62 @@ import Foundation -public struct NKEditorDetailsResponse: Codable, Sendable { +public struct NKDirectEditingCapabilitiesResponse: Codable, Sendable { public let ocs: OCS public struct OCS: Codable, Sendable { public let data: DataClass public struct DataClass: Codable, Sendable { - public let editors: [String: NKEditorDetailsEditor] - public let creators: [String: NKEditorDetailsCreator] + public let editors: [String: NKDirectEditingEditor] + public let creators: [String: NKDirectEditingCreator] } } } -public struct NKEditorTemplateResponse: Codable, Sendable { +public struct NKDirectEditingTemplateResponse: Codable, Sendable { public let ocs: OCS public struct OCS: Codable, Sendable { public let data: DataClass public struct DataClass: Codable, Sendable { - public let editors: [NKEditorTemplate] + public let templates: [String: NKDirectEditingTemplate] } } } -public struct NKEditorDetailsEditor: Codable, Sendable { +public struct NKDirectEditingTemplate: Codable, Sendable { + public let ext: String + public let identifier: String + public let mimetype: String + public let name: String + public let preview: String? + + enum CodingKeys: String, CodingKey { + case ext = "extension" + case identifier = "id" + case mimetype + case name = "title" + case preview + } + + public init( + ext: String = "", + identifier: String = "", + mimetype: String = "", + name: String = "", + preview: String? = nil + ) { + self.ext = ext + self.identifier = identifier + self.mimetype = mimetype + self.name = name + self.preview = preview + } +} + +public struct NKDirectEditingEditor: Codable, Sendable { public let identifier: String public let mimetypes: [String] public let name: String @@ -45,7 +75,7 @@ public struct NKEditorDetailsEditor: Codable, Sendable { } } -public struct NKEditorDetailsCreator: Codable, Sendable { +public struct NKDirectEditingCreator: Codable, Sendable { public let identifier: String public let templates: Bool public let mimetype: String @@ -62,24 +92,3 @@ public struct NKEditorDetailsCreator: Codable, Sendable { case ext = "extension" } } - -public struct NKEditorTemplate: Codable, Sendable { - public var ext: String - public var identifier: String - public var name: String - public var preview: String - - enum CodingKeys: String, CodingKey { - case ext = "extension" - case identifier = "id" - case name - case preview - } - - public init(ext: String = "", identifier: String = "", name: String = "", preview: String = "") { - self.ext = ext - self.identifier = identifier - self.name = name - self.preview = preview - } -} diff --git a/Sources/NextcloudKit/Models/EditorDetails/NKEditorDetailsConverter.swift b/Sources/NextcloudKit/Models/EditorDetails/NKEditorDetailsConverter.swift deleted file mode 100644 index 51d2aec6..00000000 --- a/Sources/NextcloudKit/Models/EditorDetails/NKEditorDetailsConverter.swift +++ /dev/null @@ -1,24 +0,0 @@ -// SPDX-FileCopyrightText: Nextcloud GmbH -// SPDX-FileCopyrightText: 2025 Marino Faggiana -// SPDX-License-Identifier: GPL-3.0-or-later - -import Foundation - -public enum NKEditorDetailsConverter { - - /// Parses and converts raw JSON `Data` into `[NKEditorDetailsEditors]` and `[NKEditorDetailsCreators]`. - /// - Parameter data: Raw JSON `Data` from the editors/creators endpoint. - /// - Returns: A tuple with editors and creators. - /// - Throws: Decoding error if parsing fails. - public static func from(data: Data) throws -> (editors: [NKEditorDetailsEditor], creators: [NKEditorDetailsCreator]) { - let decoded = try JSONDecoder().decode(NKEditorDetailsResponse.self, from: data) - let editors = decoded.ocs.data.editorsArray() - let creators = decoded.ocs.data.creatorsArray() - - if NKLogFileManager.shared.logLevel == .verbose { - data.printJson() - } - - return (editors, creators) - } -} diff --git a/Sources/NextcloudKit/Models/EditorDetails/NKEditorDetailsResponse+NKConversion.swift b/Sources/NextcloudKit/Models/EditorDetails/NKEditorDetailsResponse+NKConversion.swift deleted file mode 100644 index 7d4a1953..00000000 --- a/Sources/NextcloudKit/Models/EditorDetails/NKEditorDetailsResponse+NKConversion.swift +++ /dev/null @@ -1,15 +0,0 @@ -// SPDX-FileCopyrightText: Nextcloud GmbH -// SPDX-FileCopyrightText: 2025 Marino Faggiana -// SPDX-License-Identifier: GPL-3.0-or-later - -import Foundation - -public extension NKEditorDetailsResponse.OCS.DataClass { - func editorsArray() -> [NKEditorDetailsEditor] { - Array(editors.values) - } - - func creatorsArray() -> [NKEditorDetailsCreator] { - Array(creators.values) - } -} diff --git a/Sources/NextcloudKit/NextcloudKit+Capabilities.swift b/Sources/NextcloudKit/NextcloudKit+Capabilities.swift index 67f13fe2..9da5270d 100644 --- a/Sources/NextcloudKit/NextcloudKit+Capabilities.swift +++ b/Sources/NextcloudKit/NextcloudKit+Capabilities.swift @@ -521,32 +521,30 @@ final public class NKCapabilities: Sendable { /// /// The version of the locking API. /// - public var filesLockVersion: String = "" // NC 24 - public var filesComments: Bool = false // NC 20 - public var filesBigfilechunking: Bool = false - public var userStatusEnabled: Bool = false - public var userStatusSupportsBusy: Bool = false - public var externalSites: Bool = false - public var activityEnabled: Bool = false - public var governanceEnabled: Bool = false - public var groupfoldersEnabled: Bool = false // NC27 - public var assistantEnabled: Bool = false // NC28 - public var isLivePhotoServerAvailable: Bool = false // NC28 - public var securityGuardDiagnostics = false + public var filesLockVersion: String = "" // NC 24 + public var filesComments: Bool = false // NC 20 + public var filesBigfilechunking: Bool = false + public var userStatusEnabled: Bool = false + public var userStatusSupportsBusy: Bool = false + public var externalSites: Bool = false + public var activityEnabled: Bool = false + public var governanceEnabled: Bool = false + public var groupfoldersEnabled: Bool = false // NC27 + public var assistantEnabled: Bool = false // NC28 + public var isLivePhotoServerAvailable: Bool = false // NC28 + public var securityGuardDiagnostics = false /// Only taken into account for major version >= 32 - public var windowsCompatibleFilenamesEnabled = false - public var forbiddenFileNames: [String] = [] - public var forbiddenFileNameBasenames: [String] = [] - public var forbiddenFileNameCharacters: [String] = [] - public var forbiddenFileNameExtensions: [String] = [] - public var recommendations: Bool = false - public var termsOfService: Bool = false -// public var declarativeUIEnabled: Bool = false -// public var declarativeUIContextMenu: [ContextMenuItem] = [] - public var clientIntegration: NKClientIntegration? = nil - public var editorEditors: [NKEditorDetailsEditor] = [] - public var editorCreators: [NKEditorDetailsCreator] = [] - public var editorTemplates: [NKEditorTemplate] = [] + public var windowsCompatibleFilenamesEnabled = false + public var forbiddenFileNames: [String] = [] + public var forbiddenFileNameBasenames: [String] = [] + public var forbiddenFileNameCharacters: [String] = [] + public var forbiddenFileNameExtensions: [String] = [] + public var recommendations: Bool = false + public var termsOfService: Bool = false + public var clientIntegration: NKClientIntegration? = nil + public var directEditingEditors: [NKDirectEditingEditor] = [] + public var directEditingCreators: [NKDirectEditingCreator] = [] + public var directEditingTemplates: [NKDirectEditingTemplate] = [] public init() {} diff --git a/Sources/NextcloudKit/NextcloudKit+NCText.swift b/Sources/NextcloudKit/NextcloudKit+DirectEditing.swift similarity index 67% rename from Sources/NextcloudKit/NextcloudKit+NCText.swift rename to Sources/NextcloudKit/NextcloudKit+DirectEditing.swift index 2bf019af..1356fe36 100644 --- a/Sources/NextcloudKit/NextcloudKit+NCText.swift +++ b/Sources/NextcloudKit/NextcloudKit+DirectEditing.swift @@ -14,10 +14,10 @@ public extension NextcloudKit { /// - options: Optional request configuration such as headers, queue, or API version. /// - taskHandler: Callback to track the underlying URLSessionTask. /// - completion: Returns the account, array of editors, array of creators, the raw response data, and NKError. - func textObtainEditorDetails(account: String, - options: NKRequestOptions = NKRequestOptions(), - taskHandler: @escaping (_ task: URLSessionTask) -> Void = { _ in }, - completion: @escaping (_ account: String, _ editors: [NKEditorDetailsEditor]?, _ creators: [NKEditorDetailsCreator]?, _ responseData: AFDataResponse?, _ error: NKError) -> Void) { + func getDirectEditingCapabilities(account: String, + options: NKRequestOptions = NKRequestOptions(), + taskHandler: @escaping (_ task: URLSessionTask) -> Void = { _ in }, + completion: @escaping (_ account: String, _ editors: [NKDirectEditingEditor]?, _ creators: [NKDirectEditingCreator]?, _ responseData: AFDataResponse?, _ error: NKError) -> Void) { let endpoint = "ocs/v2.php/apps/files/api/v1/directEditing" guard let nkSession = nkCommonInstance.nksessions.session(forAccount: account), let url = nkCommonInstance.createStandardUrl(serverUrl: nkSession.urlBase, endpoint: endpoint), @@ -36,10 +36,10 @@ public extension NextcloudKit { case .success(let responseData): Task { do { - let (editors, creators) = try NKEditorDetailsConverter.from(data: responseData) + let (editors, creators) = try NKDirectEditingCapabilitiesConverter.from(data: responseData) let capabilities = await NKCapabilities.shared.getCapabilities(for: account) - capabilities.editorEditors = editors - capabilities.editorCreators = creators + capabilities.directEditingEditors = editors + capabilities.directEditingCreators = creators await NKCapabilities.shared.setCapabilities(for: account, capabilities: capabilities) options.queue.async { @@ -47,7 +47,7 @@ public extension NextcloudKit { } } catch { - nkLog(error: "Parsing error in NKEditorDetailsConverter: \(error)") + nkLog(error: "Parsing error in NKDirectEditingCapabilitiesConverter: \(error)") options.queue.async { completion(account, nil, nil, response, .invalidData) } @@ -64,20 +64,20 @@ public extension NextcloudKit { /// - options: Configuration for the request, including headers and execution queue. /// - taskHandler: Optional callback to monitor the underlying network task. /// - Returns: A tuple containing the account, list of editors, list of creators, raw response, and NKError. - func textObtainEditorDetailsAsync(account: String, - options: NKRequestOptions = NKRequestOptions(), - taskHandler: @escaping (_ task: URLSessionTask) -> Void = { _ in } + func getDirectEditingCapabilitiesAsync(account: String, + options: NKRequestOptions = NKRequestOptions(), + taskHandler: @escaping (_ task: URLSessionTask) -> Void = { _ in } ) async -> ( account: String, - editors: [NKEditorDetailsEditor]?, - creators: [NKEditorDetailsCreator]?, + editors: [NKDirectEditingEditor]?, + creators: [NKDirectEditingCreator]?, responseData: AFDataResponse?, error: NKError ) { await withCheckedContinuation { continuation in - textObtainEditorDetails(account: account, - options: options, - taskHandler: taskHandler) { account, editors, creators, responseData, error in + getDirectEditingCapabilities(account: account, + options: options, + taskHandler: taskHandler) { account, editors, creators, responseData, error in continuation.resume(returning: ( account: account, editors: editors, @@ -94,24 +94,24 @@ public extension NextcloudKit { /// Parameters: /// - fileNamePath: The path of the file to open on the server. /// - fileId: Optional file identifier used to reference the file more precisely. - /// - editor: The identifier of the text editor to use. + /// - editorId: The identifier of the text editor to use. /// - account: The account initiating the file open request. /// - options: Optional configuration for the request (headers, API version, etc.). /// - taskHandler: Callback triggered with the underlying URLSessionTask. /// - completion: Returns the account, the resulting file editor URL, raw response data, and an NKError. - func textOpenFile(fileNamePath: String, - fileId: String? = nil, - editor: String, - account: String, - options: NKRequestOptions = NKRequestOptions(), - taskHandler: @escaping (_ task: URLSessionTask) -> Void = { _ in }, - completion: @escaping (_ account: String, _ url: String?, _ responseData: AFDataResponse?, _ error: NKError) -> Void) { + func openFileForDirectEditing(fileNamePath: String, + fileId: String? = nil, + editorId: String, + account: String, + options: NKRequestOptions = NKRequestOptions(), + taskHandler: @escaping (_ task: URLSessionTask) -> Void = { _ in }, + completion: @escaping (_ account: String, _ url: String?, _ responseData: AFDataResponse?, _ error: NKError) -> Void) { guard let fileNamePath = fileNamePath.urlEncoded else { return options.queue.async { completion(account, nil, nil, .urlError) } } - var endpoint = "ocs/v2.php/apps/files/api/v1/directEditing/open?path=/\(fileNamePath)&editorId=\(editor)" + var endpoint = "ocs/v2.php/apps/files/api/v1/directEditing/open?path=/\(fileNamePath)&editorId=\(editorId)" if let fileId = fileId { - endpoint = "ocs/v2.php/apps/files/api/v1/directEditing/open?path=/\(fileNamePath)&fileId=\(fileId)&editorId=\(editor)" + endpoint = "ocs/v2.php/apps/files/api/v1/directEditing/open?path=/\(fileNamePath)&fileId=\(fileId)&editorId=\(editorId)" } guard let nkSession = nkCommonInstance.nksessions.session(forAccount: account), let url = nkCommonInstance.createStandardUrl(serverUrl: nkSession.urlBase, endpoint: endpoint), @@ -140,17 +140,17 @@ public extension NextcloudKit { /// - Parameters: /// - fileNamePath: Path of the file on the server. /// - fileId: Optional file ID to assist in uniquely identifying the file. - /// - editor: Identifier of the text editor to be used. + /// - editorId: Identifier of the editor to be used. /// - account: Account performing the operation. /// - options: Configuration options for the request. /// - taskHandler: Optional monitoring for the underlying URLSessionTask. /// - Returns: A tuple containing the account, resulting URL, raw response data, and NKError. - func textOpenFileAsync(fileNamePath: String, - fileId: String? = nil, - editor: String, - account: String, - options: NKRequestOptions = NKRequestOptions(), - taskHandler: @escaping (_ task: URLSessionTask) -> Void = { _ in } + func openFileForDirectEditingAsync(fileNamePath: String, + fileId: String? = nil, + editorId: String, + account: String, + options: NKRequestOptions = NKRequestOptions(), + taskHandler: @escaping (_ task: URLSessionTask) -> Void = { _ in } ) async -> ( account: String, url: String?, @@ -158,12 +158,12 @@ public extension NextcloudKit { error: NKError ) { await withCheckedContinuation { continuation in - textOpenFile(fileNamePath: fileNamePath, - fileId: fileId, - editor: editor, - account: account, - options: options, - taskHandler: taskHandler) { account, url, responseData, error in + openFileForDirectEditing(fileNamePath: fileNamePath, + fileId: fileId, + editorId: editorId, + account: account, + options: options, + taskHandler: taskHandler) { account, url, responseData, error in continuation.resume(returning: ( account: account, url: url, @@ -178,14 +178,18 @@ public extension NextcloudKit { /// /// Parameters: /// - account: The account requesting the list of templates. + /// - editorId: Identifier of the editor to be used. + /// - creatorId: The identifier of the creator (e.g., "document", "spreadsheet"). /// - options: Optional request configuration such as headers, queue, or API version. /// - taskHandler: Callback triggered with the underlying URLSessionTask. - /// - completion: Returns the account, an optional array of NKEditorTemplate, the raw response, and an NKError. - func textGetListOfTemplates(account: String, - options: NKRequestOptions = NKRequestOptions(), - taskHandler: @escaping (_ task: URLSessionTask) -> Void = { _ in }, - completion: @escaping (_ account: String, _ templates: [NKEditorTemplate]?, _ responseData: AFDataResponse?, _ error: NKError) -> Void) { - let endpoint = "ocs/v2.php/apps/files/api/v1/directEditing/templates/text/textdocumenttemplate" + /// - completion: Returns the account, an optional array of NKDirectEditingTemplate, the raw response, and an NKError. + func getDirectEditingTemplates(account: String, + editorId: String, + creatorId: String, + options: NKRequestOptions = NKRequestOptions(), + taskHandler: @escaping (_ task: URLSessionTask) -> Void = { _ in }, + completion: @escaping (_ account: String, _ templates: [NKDirectEditingTemplate]?, _ responseData: AFDataResponse?, _ error: NKError) -> Void) { + let endpoint = "ocs/v2.php/apps/files/api/v1/directEditing/templates/\(editorId)/\(creatorId)" guard let nkSession = nkCommonInstance.nksessions.session(forAccount: account), let url = nkCommonInstance.createStandardUrl(serverUrl: nkSession.urlBase, endpoint: endpoint), let headers = nkCommonInstance.getStandardHeaders(account: account, options: options) else { @@ -203,17 +207,20 @@ public extension NextcloudKit { case .success(let data): Task { do { - let decoded = try JSONDecoder().decode(NKEditorTemplateResponse.self, from: data) - let templates = decoded.ocs.data.editors - // Update capabilities + let decoded = try JSONDecoder().decode(NKDirectEditingTemplateResponse.self, from: data) + let templates = Array(decoded.ocs.data.templates.values) let capabilities = await NKCapabilities.shared.getCapabilities(for: account) - capabilities.editorTemplates = templates + capabilities.directEditingTemplates = templates await NKCapabilities.shared.setCapabilities(for: account, capabilities: capabilities) - options.queue.async { completion(account, templates, response, .success) } + options.queue.async { + completion(account, templates, response, .success) + } } catch { nkLog(error: "Failed to decode template list: \(error)") - options.queue.async { completion(account, nil, response, .invalidData) } + options.queue.async { + completion(account, nil, response, .invalidData) + } } } } @@ -225,21 +232,27 @@ public extension NextcloudKit { /// - Parameters: /// - account: The account requesting the templates. /// - options: Request configuration options (queue, headers, etc.). + /// - editorId: Identifier of the editor to be used. + /// - creatorId: The identifier of the creator (e.g., "document", "spreadsheet"). /// - taskHandler: Optional callback to monitor the underlying URLSessionTask. /// - Returns: A tuple containing the account, list of templates (if any), raw response, and error information. - func textGetListOfTemplatesAsync(account: String, - options: NKRequestOptions = NKRequestOptions(), - taskHandler: @escaping (_ task: URLSessionTask) -> Void = { _ in } + func getDirectEditingTemplatesAsync(account: String, + editorId: String, + creatorId: String, + options: NKRequestOptions = NKRequestOptions(), + taskHandler: @escaping (_ task: URLSessionTask) -> Void = { _ in } ) async -> ( account: String, - templates: [NKEditorTemplate]?, + templates: [NKDirectEditingTemplate]?, responseData: AFDataResponse?, error: NKError ) { await withCheckedContinuation { continuation in - textGetListOfTemplates(account: account, - options: options, - taskHandler: taskHandler) { account, templates, responseData, error in + getDirectEditingTemplates(account: account, + editorId: editorId, + creatorId: creatorId, + options: options, + taskHandler: taskHandler) { account, templates, responseData, error in continuation.resume(returning: ( account: account, templates: templates, @@ -261,14 +274,14 @@ public extension NextcloudKit { /// - options: Optional request configuration (headers, queue, version, etc.). /// - taskHandler: Callback to monitor the underlying URLSessionTask. /// - completion: Returns the account, the resulting file URL (if any), the raw response, and NKError. - func textCreateFile(fileNamePath: String, - editorId: String, - creatorId: String, - templateId: String, - account: String, - options: NKRequestOptions = NKRequestOptions(), - taskHandler: @escaping (_ task: URLSessionTask) -> Void = { _ in }, - completion: @escaping (_ account: String, _ url: String?, _ responseData: AFDataResponse?, _ error: NKError) -> Void) { + func createFileForDirectEditing(fileNamePath: String, + editorId: String, + creatorId: String, + templateId: String, + account: String, + options: NKRequestOptions = NKRequestOptions(), + taskHandler: @escaping (_ task: URLSessionTask) -> Void = { _ in }, + completion: @escaping (_ account: String, _ url: String?, _ responseData: AFDataResponse?, _ error: NKError) -> Void) { guard let fileNamePath = fileNamePath.urlEncoded else { return options.queue.async { completion(account, nil, nil, .urlError) } } @@ -305,19 +318,19 @@ public extension NextcloudKit { /// - Parameters: /// - fileNamePath: Destination path where the new file will be saved. /// - editorId: The editor's unique identifier (e.g., "richdocuments"). - /// - creatorId: The creator's identifier (e.g., "document"). + /// - creatorId: The identifier of the creator (e.g., "document", "spreadsheet"). /// - templateId: The template to use for the new file. /// - account: The Nextcloud account used for the operation. /// - options: Optional request settings (e.g., headers, queue, etc.). /// - taskHandler: Optional callback to observe the URLSessionTask. /// - Returns: A tuple containing the account, the resulting file URL, raw response data, and NKError. - func textCreateFileAsync(fileNamePath: String, - editorId: String, - creatorId: String, - templateId: String, - account: String, - options: NKRequestOptions = NKRequestOptions(), - taskHandler: @escaping (_ task: URLSessionTask) -> Void = { _ in } + func createFileForDirectEditingAsync(fileNamePath: String, + editorId: String, + creatorId: String, + templateId: String, + account: String, + options: NKRequestOptions = NKRequestOptions(), + taskHandler: @escaping (_ task: URLSessionTask) -> Void = { _ in } ) async -> ( account: String, url: String?, @@ -325,13 +338,13 @@ public extension NextcloudKit { error: NKError ) { await withCheckedContinuation { continuation in - textCreateFile(fileNamePath: fileNamePath, - editorId: editorId, - creatorId: creatorId, - templateId: templateId, - account: account, - options: options, - taskHandler: taskHandler) { account, url, responseData, error in + createFileForDirectEditing(fileNamePath: fileNamePath, + editorId: editorId, + creatorId: creatorId, + templateId: templateId, + account: account, + options: options, + taskHandler: taskHandler) { account, url, responseData, error in continuation.resume(returning: ( account: account, url: url, diff --git a/Sources/NextcloudKit/NextcloudKit+Richdocuments.swift b/Sources/NextcloudKit/NextcloudKit+Richdocuments.swift index 32d3b5bb..53b946a5 100644 --- a/Sources/NextcloudKit/NextcloudKit+Richdocuments.swift +++ b/Sources/NextcloudKit/NextcloudKit+Richdocuments.swift @@ -7,27 +7,27 @@ import Alamofire import SwiftyJSON public extension NextcloudKit { - /// Requests a URL for editing or viewing a file via the Richdocuments (Collabora/OnlyOffice) app. + /// Requests a URL for editing or viewing a file via Richdocuments (Nextcloud Office/Collabora). /// /// Parameters: - /// - fileID: The unique identifier of the file for which the document URL is requested. + /// - fileId: The unique identifier of the file for which the document URL is requested. /// - account: The Nextcloud account performing the request. /// - options: Optional configuration such as custom headers, queue, or API version. /// - taskHandler: Callback invoked when the underlying URLSessionTask is created. /// - completion: Completion handler returning the account, document URL (if available), - /// the raw HTTP response, and an NKError object. - func createUrlRichdocuments(fileID: String, - account: String, - options: NKRequestOptions = NKRequestOptions(), - taskHandler: @escaping (_ task: URLSessionTask) -> Void = { _ in }, - completion: @escaping (_ account: String, _ url: String?, _ responseData: AFDataResponse?, _ error: NKError) -> Void) { + /// the raw HTTP response, and an NKError object. + func createRichdocumentsEditorURL(fileId: String, + account: String, + options: NKRequestOptions = NKRequestOptions(), + taskHandler: @escaping (_ task: URLSessionTask) -> Void = { _ in }, + completion: @escaping (_ account: String, _ url: String?, _ responseData: AFDataResponse?, _ error: NKError) -> Void) { let endpoint = "ocs/v2.php/apps/richdocuments/api/v1/document" guard let nkSession = nkCommonInstance.nksessions.session(forAccount: account), let url = nkCommonInstance.createStandardUrl(serverUrl: nkSession.urlBase, endpoint: endpoint), let headers = nkCommonInstance.getStandardHeaders(account: account, options: options) else { return options.queue.async { completion(account, nil, nil, .urlError) } } - let parameters: [String: Any] = ["fileId": fileID] + let parameters: [String: Any] = ["fileId": fileId] nkSession.sessionData.request(url, method: .post, parameters: parameters, encoding: URLEncoding.default, headers: headers, interceptor: NKInterceptor(nkCommonInstance: nkCommonInstance)).validate(statusCode: 200..<300).onURLSessionTaskCreation { task in task.taskDescription = options.taskDescription @@ -49,18 +49,18 @@ public extension NextcloudKit { } } - /// Asynchronously retrieves the URL for opening a file in Richdocuments (e.g., Collabora or OnlyOffice). + /// Asynchronously retrieves the URL for opening a file in Richdocuments (Nextcloud Office/Collabora). /// /// - Parameters: - /// - fileID: The identifier of the target file. + /// - fileId: The identifier of the target file. /// - account: The Nextcloud account used for the operation. /// - options: Request configuration (headers, queue, version, etc.). /// - taskHandler: Optional handler to observe the URLSessionTask. /// - Returns: A tuple containing the account, the richdocument URL (if any), the raw response data, and any NKError. - func createUrlRichdocumentsAsync(fileID: String, - account: String, - options: NKRequestOptions = NKRequestOptions(), - taskHandler: @escaping (_ task: URLSessionTask) -> Void = { _ in } + func createRichdocumentsEditorURLAsync(fileId: String, + account: String, + options: NKRequestOptions = NKRequestOptions(), + taskHandler: @escaping (_ task: URLSessionTask) -> Void = { _ in } ) async -> ( account: String, url: String?, @@ -68,10 +68,10 @@ public extension NextcloudKit { error: NKError ) { await withCheckedContinuation { continuation in - createUrlRichdocuments(fileID: fileID, - account: account, - options: options, - taskHandler: taskHandler) { account, url, responseData, error in + createRichdocumentsEditorURL(fileId: fileId, + account: account, + options: options, + taskHandler: taskHandler) { account, url, responseData, error in continuation.resume(returning: ( account: account, url: url, @@ -85,17 +85,17 @@ public extension NextcloudKit { /// Retrieves the list of Richdocuments templates of a given type (e.g., "document", "spreadsheet"). /// /// Parameters: - /// - typeTemplate: The type of template to retrieve (e.g., "document", "presentation"). + /// - templateType: The type of template to retrieve (e.g., "document", "presentation"). /// - account: The Nextcloud account performing the request. /// - options: Optional configuration (headers, queue, API version, etc.). /// - taskHandler: Callback invoked when the underlying URLSessionTask is created. /// - completion: Completion handler returning the account, array of templates, response data, and NKError. - func getTemplatesRichdocuments(typeTemplate: String, + func getRichdocumentsTemplates(templateType: String, account: String, options: NKRequestOptions = NKRequestOptions(), taskHandler: @escaping (_ task: URLSessionTask) -> Void = { _ in }, completion: @escaping (_ account: String, _ templates: [NKRichdocumentsTemplate]?, _ responseData: AFDataResponse?, _ error: NKError) -> Void) { - let endpoint = "ocs/v2.php/apps/richdocuments/api/v1/templates/\(typeTemplate)" + let endpoint = "ocs/v2.php/apps/richdocuments/api/v1/templates/\(templateType)" guard let nkSession = nkCommonInstance.nksessions.session(forAccount: account), let url = nkCommonInstance.createStandardUrl(serverUrl: nkSession.urlBase, endpoint: endpoint), let headers = nkCommonInstance.getStandardHeaders(account: account, options: options) else { @@ -137,12 +137,12 @@ public extension NextcloudKit { /// Asynchronously fetches Richdocuments templates filtered by type. /// /// - Parameters: - /// - typeTemplate: The type of template to retrieve (e.g., "document"). + /// - templateType: The type of template to retrieve (e.g., "document"). /// - account: The Nextcloud account for which templates are requested. /// - options: Optional request configuration. /// - taskHandler: Optional handler to observe the `URLSessionTask`. /// - Returns: A tuple containing the account, array of templates, raw response data, and any NKError. - func getTemplatesRichdocumentsAsync(typeTemplate: String, + func getRichdocumentsTemplatesAsync(templateType: String, account: String, options: NKRequestOptions = NKRequestOptions(), taskHandler: @escaping (_ task: URLSessionTask) -> Void = { _ in } @@ -153,7 +153,7 @@ public extension NextcloudKit { error: NKError ) { await withCheckedContinuation { continuation in - getTemplatesRichdocuments(typeTemplate: typeTemplate, + getRichdocumentsTemplates(templateType: templateType, account: account, options: options, taskHandler: taskHandler) { account, templates, responseData, error in @@ -170,25 +170,25 @@ public extension NextcloudKit { /// Creates a new Richdocuments file using a specific template. /// /// Parameters: - /// - path: The target path where the new document should be created. + /// - filePath: The target path where the new document should be created. /// - templateId: The ID of the Richdocuments template to use. /// - account: The Nextcloud account performing the request. /// - options: Optional request configuration (headers, queue, API version, etc.). /// - taskHandler: Callback invoked when the underlying URLSessionTask is created. - /// - completion: Completion handler returning the account, resulting file URL, raw response, and NKError. - func createRichdocuments(path: String, - templateId: String, - account: String, - options: NKRequestOptions = NKRequestOptions(), - taskHandler: @escaping (_ task: URLSessionTask) -> Void = { _ in }, - completion: @escaping (_ account: String, _ url: String?, _ responseData: AFDataResponse?, _ error: NKError) -> Void) { + /// - completion: Completion handler returning the account, emporary asset URL, raw response, and NKError. + func createRichdocumentsFileFromTemplate(filePath: String, + templateId: String, + account: String, + options: NKRequestOptions = NKRequestOptions(), + taskHandler: @escaping (_ task: URLSessionTask) -> Void = { _ in }, + completion: @escaping (_ account: String, _ url: String?, _ responseData: AFDataResponse?, _ error: NKError) -> Void) { let endpoint = "ocs/v2.php/apps/richdocuments/api/v1/templates/new" guard let nkSession = nkCommonInstance.nksessions.session(forAccount: account), let url = nkCommonInstance.createStandardUrl(serverUrl: nkSession.urlBase, endpoint: endpoint), let headers = nkCommonInstance.getStandardHeaders(account: account, options: options) else { return options.queue.async { completion(account, nil, nil, .urlError) } } - let parameters: [String: Any] = ["path": path, "template": templateId] + let parameters: [String: Any] = ["path": filePath, "template": templateId] nkSession.sessionData.request(url, method: .post, parameters: parameters, encoding: URLEncoding.default, headers: headers, interceptor: NKInterceptor(nkCommonInstance: nkCommonInstance)).validate(statusCode: 200..<300).onURLSessionTaskCreation { task in task.taskDescription = options.taskDescription @@ -213,17 +213,17 @@ public extension NextcloudKit { /// Asynchronously creates a new Richdocuments file from a given template. /// /// - Parameters: - /// - path: Destination path for the new document. + /// - filePath: Destination path for the new document. /// - templateId: Template ID used to generate the new file. /// - account: The Nextcloud account performing the operation. /// - options: Optional request parameters. /// - taskHandler: Optional monitoring of the underlying task. /// - Returns: A tuple with account, resulting URL (if successful), raw response, and error result. - func createRichdocumentsAsync(path: String, - templateId: String, - account: String, - options: NKRequestOptions = NKRequestOptions(), - taskHandler: @escaping (_ task: URLSessionTask) -> Void = { _ in } + func createRichdocumentsFileFromTemplateAsync(filePath: String, + templateId: String, + account: String, + options: NKRequestOptions = NKRequestOptions(), + taskHandler: @escaping (_ task: URLSessionTask) -> Void = { _ in } ) async -> ( account: String, url: String?, @@ -231,11 +231,11 @@ public extension NextcloudKit { error: NKError ) { await withCheckedContinuation { continuation in - createRichdocuments(path: path, - templateId: templateId, - account: account, - options: options, - taskHandler: taskHandler) { account, url, responseData, error in + createRichdocumentsFileFromTemplate(filePath: filePath, + templateId: templateId, + account: account, + options: options, + taskHandler: taskHandler) { account, url, responseData, error in continuation.resume(returning: ( account: account, url: url, @@ -246,26 +246,26 @@ public extension NextcloudKit { } } - /// Creates a new Richdocuments file based on a default asset (no template). + /// Creates a temporary Richdocuments asset URL for an existing file. /// /// Parameters: - /// - path: The destination path where the asset will be created. + /// - filePath: Path of the existing file to expose temporarily to Collabora. /// - account: The Nextcloud account initiating the creation. /// - options: Optional configuration for the request (e.g. headers, queue, API version). /// - taskHandler: Callback invoked when the underlying URLSessionTask is created. - /// - completion: Completion handler returning account, resulting file URL, raw response data, and NKError. - func createAssetRichdocuments(path: String, - account: String, - options: NKRequestOptions = NKRequestOptions(), - taskHandler: @escaping (_ task: URLSessionTask) -> Void = { _ in }, - completion: @escaping (_ account: String, _ url: String?, _ responseData: AFDataResponse?, _ error: NKError) -> Void) { + /// - completion: Completion handler returning account, emporary asset URL, raw response data, and NKError. + func createRichdocumentsAssetURL(filePath: String, + account: String, + options: NKRequestOptions = NKRequestOptions(), + taskHandler: @escaping (_ task: URLSessionTask) -> Void = { _ in }, + completion: @escaping (_ account: String, _ url: String?, _ responseData: AFDataResponse?, _ error: NKError) -> Void) { let endpoint = "index.php/apps/richdocuments/assets" guard let nkSession = nkCommonInstance.nksessions.session(forAccount: account), let url = nkCommonInstance.createStandardUrl(serverUrl: nkSession.urlBase, endpoint: endpoint), let headers = nkCommonInstance.getStandardHeaders(account: account, options: options) else { return options.queue.async { completion(account, nil, nil, .urlError) } } - let parameters: [String: Any] = ["path": path] + let parameters: [String: Any] = ["path": filePath] nkSession.sessionData.request(url, method: .post, parameters: parameters, encoding: URLEncoding.default, headers: headers, interceptor: NKInterceptor(nkCommonInstance: nkCommonInstance)).validate(statusCode: 200..<300).onURLSessionTaskCreation { task in task.taskDescription = options.taskDescription @@ -283,18 +283,18 @@ public extension NextcloudKit { } } - /// Asynchronously creates a Richdocuments asset file at a specified path. + /// Asynchronously creates a temporary Richdocuments asset URL for an existing file. /// /// - Parameters: - /// - path: Target path for the asset document. + /// - filePath: Path of the existing file to expose temporarily to Collabora. /// - account: The Nextcloud account performing the operation. /// - options: Optional request customization. /// - taskHandler: Optional monitoring of the underlying task. /// - Returns: A tuple with account, resulting URL, raw response, and error. - func createAssetRichdocumentsAsync(path: String, - account: String, - options: NKRequestOptions = NKRequestOptions(), - taskHandler: @escaping (_ task: URLSessionTask) -> Void = { _ in } + func createRichdocumentsAssetURLAsync(filePath: String, + account: String, + options: NKRequestOptions = NKRequestOptions(), + taskHandler: @escaping (_ task: URLSessionTask) -> Void = { _ in } ) async -> ( account: String, url: String?, @@ -302,10 +302,10 @@ public extension NextcloudKit { error: NKError ) { await withCheckedContinuation { continuation in - createAssetRichdocuments(path: path, - account: account, - options: options, - taskHandler: taskHandler) { account, url, responseData, error in + createRichdocumentsAssetURL(filePath: filePath, + account: account, + options: options, + taskHandler: taskHandler) { account, url, responseData, error in continuation.resume(returning: ( account: account, url: url,