Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 26 additions & 5 deletions Sources/NextcloudKit/Models/NKDataFileXML.swift
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,30 @@ public class NKDataFileXML: NSObject {
</d:propertyupdate>
"""

let requestBodySystemTags =
"""
<?xml version=\"1.0\" encoding=\"UTF-8\"?>
<d:propfind xmlns:d=\"DAV:\" xmlns:oc=\"http://owncloud.org/ns\" xmlns:nc=\"http://nextcloud.org/ns\">
<d:prop>
<oc:id />
<oc:display-name />
<nc:color />
</d:prop>
</d:propfind>
"""

let requestBodySystemTagSetColor =
"""
<?xml version=\"1.0\" encoding=\"UTF-8\"?>
<d:propertyupdate xmlns:d=\"DAV:\" xmlns:oc=\"http://owncloud.org/ns\" xmlns:nc=\"http://nextcloud.org/ns\">
<d:set>
<d:prop>
<nc:color>%@</nc:color>
</d:prop>
</d:set>
</d:propertyupdate>
"""

func getRequestBodyFileListingFavorites(createProperties: [NKProperties]?, removeProperties: [NKProperties] = []) -> String {
let request = """
<?xml version=\"1.0\"?>
Expand Down Expand Up @@ -452,11 +476,8 @@ public class NKDataFileXML: NSObject {
file.lockTimeOut = file.lockTime?.addingTimeInterval(TimeInterval(lockTimeOut))
}

let tagsElements = propstat["d:prop", "nc:system-tags"]
for element in tagsElements["nc:system-tag"] {
guard let tag = element.text else { continue }
file.tags.append(tag)
}
let tags: [NKTag] = NKTag.parse(systemTagElements: propstat["d:prop", "nc:system-tags", "nc:system-tag"])
file.tags.append(contentsOf: tags)

// NC27 -----
if let latitude = propstat["d:prop", "nc:file-metadata-gps", "latitude"].double {
Expand Down
4 changes: 2 additions & 2 deletions Sources/NextcloudKit/Models/NKFile.swift
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ public struct NKFile: Sendable {
public var shareType: [Int]
public var size: Int64
public var serverUrl: String
public var tags: [String]
public var tags: [NKTag]
public var trashbinFileName: String
public var trashbinOriginalLocation: String
public var trashbinDeletionTime: Date
Expand Down Expand Up @@ -128,7 +128,7 @@ public struct NKFile: Sendable {
shareType: [Int] = [],
size: Int64 = 0,
serverUrl: String = "",
tags: [String] = [],
tags: [NKTag] = [],
trashbinFileName: String = "",
trashbinOriginalLocation: String = "",
trashbinDeletionTime: Date = Date(),
Expand Down
62 changes: 62 additions & 0 deletions Sources/NextcloudKit/Models/NKTag.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
// SPDX-FileCopyrightText: Nextcloud GmbH
// SPDX-FileCopyrightText: 2026 Milen Pivchev
// SPDX-License-Identifier: GPL-3.0-or-later

import Foundation
import SwiftyXMLParser

public struct NKTag: Sendable, Equatable, Hashable {
public let id: String
public let name: String
public let color: String?

public init(id: String, name: String, color: String?) {
self.id = id
self.name = name
self.color = color
}

static func parse(xmlData: Data) -> [NKTag] {
let xml = XML.parse(xmlData)
let responses = xml["d:multistatus", "d:response"]
var tags: [NKTag] = []

for response in responses {
let propstat = response["d:propstat"][0]
guard let id = propstat["d:prop", "oc:id"].text,
let name = propstat["d:prop", "oc:display-name"].text else {
continue
}

let color = normalizedColor(propstat["d:prop", "nc:color"].text)

tags.append(NKTag(id: id, name: name, color: color))
}

return tags
}

static func parse(systemTagElements: XML.Accessor) -> [NKTag] {
var tags: [NKTag] = []

for element in systemTagElements {
guard let name = element.text?.trimmingCharacters(in: .whitespacesAndNewlines),
!name.isEmpty else {
continue
}

let id = element.attributes["oc:id"] ?? ""
let color = normalizedColor(element.attributes["nc:color"])
tags.append(NKTag(id: id, name: name, color: color))
}

return tags
}

private static func normalizedColor(_ rawValue: String?) -> String? {
guard let rawValue, !rawValue.isEmpty else {
return nil
}
return rawValue.hasPrefix("#") ? rawValue : "#\(rawValue)"
}
}
Loading
Loading