VcfImportViewModel.swift 55 lignes · 1730 octets
import Foundation

// Port of ui/importvcf/VcfImportViewModel.kt — parse a .vcf file and import
// with the repository's e-mail/phone dedup skip logic.

enum VcfImportUiState {
    case idle
    case loading
    case done(VcfImportResult)
    case error(String)
}

@MainActor
final class VcfImportViewModel: ObservableObject {
    @Published private(set) var state: VcfImportUiState = .idle

    private let repository: ContactRepository

    init(repository: ContactRepository = ContactRepository(
        dao: Card2vcfDatabase.shared.crmContactDao,
        images: ContactImageStore()
    )) {
        self.repository = repository
    }

    func importFrom(url: URL) {
        state = .loading
        Task {
            do {
                let secured = url.startAccessingSecurityScopedResource()
                defer {
                    if secured { url.stopAccessingSecurityScopedResource() }
                }
                guard let data = try? Data(contentsOf: url),
                      let text = String(data: data, encoding: .utf8)
                          ?? String(data: data, encoding: .isoLatin1) else {
                    throw NSError(
                        domain: "VcfImport",
                        code: 1,
                        userInfo: [NSLocalizedDescriptionKey: "Impossible de lire le fichier"]
                    )
                }
                let cards = VCardParser.parse(text)
                let result = try await repository.importCards(cards)
                state = .done(result)
            } catch {
                state = .error(error.localizedDescription.nilIfBlank ?? "Erreur d'import")
            }
        }
    }

    func reset() {
        state = .idle
    }
}