BusinessCard/BusinessCardClip/Models/SharedCardSnapshot.swift

54 lines
2.0 KiB
Swift

import Foundation
/// Represents a shared card fetched from CloudKit for display in the App Clip.
struct SharedCardSnapshot: Sendable {
let recordName: String
let vCardData: String
let displayName: String
let role: String
let company: String
let photoData: Data?
init(
recordName: String,
vCardData: String,
displayName: String? = nil,
role: String? = nil,
company: String? = nil,
photoData: Data? = nil
) {
self.recordName = recordName
self.vCardData = vCardData
// Parse display fields from vCard
let lines = vCardData.components(separatedBy: .newlines)
let parsedDisplayName = Self.parseField("FN:", from: lines) ?? "Contact"
let parsedRole = Self.parseField("TITLE:", from: lines) ?? ""
let parsedCompany = Self.parseField("ORG:", from: lines)?
.components(separatedBy: ";").first ?? ""
let parsedPhotoData = Self.parsePhoto(from: lines)
let cleanedDisplayName = displayName?.trimmingCharacters(in: .whitespacesAndNewlines) ?? ""
self.displayName = cleanedDisplayName.isEmpty ? parsedDisplayName : cleanedDisplayName
self.role = role ?? parsedRole
self.company = company ?? parsedCompany
self.photoData = photoData ?? parsedPhotoData
}
private static func parseField(_ prefix: String, from lines: [String]) -> String? {
lines.first { $0.hasPrefix(prefix) }?
.dropFirst(prefix.count)
.trimmingCharacters(in: .whitespaces)
}
private static func parsePhoto(from lines: [String]) -> Data? {
// Find line that starts with PHOTO; and contains base64 data
guard let photoLine = lines.first(where: { $0.hasPrefix("PHOTO;") }),
let base64Start = photoLine.range(of: ":")?.upperBound else {
return nil
}
let base64String = String(photoLine[base64Start...])
return Data(base64Encoded: base64String)
}
}