57 lines
1.5 KiB
Swift
57 lines
1.5 KiB
Swift
import Foundation
|
|
|
|
/// State management for the App Clip card display and save flow.
|
|
@MainActor
|
|
@Observable
|
|
final class ClipCardStore {
|
|
|
|
enum State {
|
|
case loading
|
|
case loaded(SharedCardSnapshot)
|
|
case saved
|
|
case error(String)
|
|
}
|
|
|
|
private let cloudKit: ClipCloudKitService
|
|
private let contactSave: ContactSaveService
|
|
|
|
var state: State = .loading
|
|
|
|
/// The currently loaded card snapshot, if any.
|
|
var snapshot: SharedCardSnapshot? {
|
|
if case .loaded(let snap) = state { return snap }
|
|
return nil
|
|
}
|
|
|
|
init(
|
|
cloudKit: ClipCloudKitService = ClipCloudKitService(),
|
|
contactSave: ContactSaveService = ContactSaveService()
|
|
) {
|
|
self.cloudKit = cloudKit
|
|
self.contactSave = contactSave
|
|
}
|
|
|
|
/// Loads a shared card from CloudKit.
|
|
/// - Parameter recordName: The record name (UUID) to fetch.
|
|
func load(recordName: String) async {
|
|
state = .loading
|
|
do {
|
|
let snapshot = try await cloudKit.fetchSharedCard(recordName: recordName)
|
|
state = .loaded(snapshot)
|
|
} catch {
|
|
state = .error(error.localizedDescription)
|
|
}
|
|
}
|
|
|
|
/// Saves the currently loaded card to Contacts.
|
|
func saveToContacts() async {
|
|
guard let snapshot else { return }
|
|
do {
|
|
try await contactSave.saveContact(vCardData: snapshot.vCardData)
|
|
state = .saved
|
|
} catch {
|
|
state = .error(error.localizedDescription)
|
|
}
|
|
}
|
|
}
|