| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161 |
- import CoreData
- import Foundation
- import SwiftUI
- import Swinject
- protocol ContactImageStorage {
- func fetchContactImageEntries() async -> [ContactImageEntry]
- func storeContactImageEntry(_ entry: ContactImageEntry) async
- func updateContactImageEntry(_ contactImageEntry: ContactImageEntry) async
- func deleteContactImageEntry(_ objectID: NSManagedObjectID) async
- }
- final class BaseContactImageStorage: ContactImageStorage, Injectable {
- @Injected() private var settingsManager: SettingsManager!
- private let backgroundContext = CoreDataStack.shared.newTaskContext()
- init(resolver: Resolver) {
- injectServices(resolver)
- }
- /// Fetches all stored Contact Trick entries.
- ///
- /// The method retrieves `ContactImageEntryStored` objects from Core Data, maps them to
- /// `ContactImageEntry` objects, and returns the results.
- ///
- /// - Returns: An array of `ContactImageEntry` objects.
- func fetchContactImageEntries() async -> [ContactImageEntry] {
- do {
- let results = try await CoreDataStack.shared.fetchEntitiesAsync(
- ofType: ContactImageEntryStored.self,
- onContext: backgroundContext,
- predicate: NSPredicate.all,
- key: "hasHighContrast",
- ascending: false
- )
- return try await backgroundContext.perform {
- guard let fetchedContactImageEntries = results as? [ContactImageEntryStored]
- else { throw CoreDataError.fetchError(function: #function, file: #file)
- }
- return fetchedContactImageEntries.compactMap { entry in
- ContactImageEntry(
- name: entry.name ?? String(localized: "No name provided"),
- layout: ContactImageLayout(rawValue: entry.layout ?? "Default") ?? .default,
- ring: ContactImageLargeRing(rawValue: entry.ring ?? "Hidden") ?? .none,
- primary: ContactImageValue(rawValue: entry.primary ?? "Glucose Reading") ?? .glucose,
- top: ContactImageValue(rawValue: entry.top ?? "None") ?? .none,
- bottom: ContactImageValue(rawValue: entry.bottom ?? "None") ?? .none,
- contactId: entry.contactId?.string,
- hasHighContrast: entry.hasHighContrast,
- ringWidth: ContactImageEntry.RingWidth(rawValue: Int(entry.ringWidth)) ?? .regular,
- ringGap: ContactImageEntry.RingGap(rawValue: Int(entry.ringGap)) ?? .small,
- colorMode: ContactImageEntry.ColorMode(rawValue: entry.colorMode ?? "Color") ?? .color,
- fontSize: ContactImageEntry.FontSize(rawValue: Int(entry.fontSize)) ?? .regular,
- secondaryFontSize: ContactImageEntry.FontSize(rawValue: Int(entry.fontSizeSecondary)) ?? .small,
- fontWeight: Font.Weight.fromString(entry.fontWeight ?? "regular"),
- fontWidth: Font.Width.fromString(entry.fontWidth ?? "standard"),
- managedObjectID: entry.objectID
- )
- }
- }
- } catch {
- debug(.default, "\(DebuggingIdentifiers.failed) Error fetching contact image entries: \(error)")
- return []
- }
- }
- /// Stores a new Contact Trick entry.
- ///
- /// This method creates a new `ContactImageEntryStored` object in the background context,
- /// populates its properties with the values from the provided `ContactImageEntry`, and
- /// saves the context if changes exist.
- ///
- /// - Parameter contactImageEntry: The `ContactImageEntry` object to be stored.
- func storeContactImageEntry(_ contactImageEntry: ContactImageEntry) async {
- await backgroundContext.perform {
- let newContactImageEntry = ContactImageEntryStored(context: self.backgroundContext)
- newContactImageEntry.id = UUID()
- newContactImageEntry.name = contactImageEntry.name
- newContactImageEntry.contactId = contactImageEntry.contactId
- newContactImageEntry.layout = contactImageEntry.layout.rawValue
- newContactImageEntry.ring = contactImageEntry.ring.rawValue
- newContactImageEntry.primary = contactImageEntry.primary.rawValue
- newContactImageEntry.top = contactImageEntry.top.rawValue
- newContactImageEntry.bottom = contactImageEntry.bottom.rawValue
- newContactImageEntry.hasHighContrast = contactImageEntry.hasHighContrast
- newContactImageEntry.ringWidth = Int16(contactImageEntry.ringWidth.rawValue)
- newContactImageEntry.ringGap = Int16(contactImageEntry.ringGap.rawValue)
- newContactImageEntry.colorMode = contactImageEntry.colorMode.rawValue
- newContactImageEntry.fontSize = Int16(contactImageEntry.fontSize.rawValue)
- newContactImageEntry.fontSizeSecondary = Int16(contactImageEntry.secondaryFontSize.rawValue)
- newContactImageEntry.fontWidth = contactImageEntry.fontWidth.asString
- newContactImageEntry.fontWeight = contactImageEntry.fontWeight.asString
- do {
- guard self.backgroundContext.hasChanges else { return }
- try self.backgroundContext.save()
- } catch let error as NSError {
- debugPrint(
- "\(DebuggingIdentifiers.failed) \(#file) \(#function) Failed to save Contact Trick Entry to Core Data with error: \(error.userInfo)"
- )
- }
- }
- }
- /// Updates an existing Contact Trick entry in Core Data.
- ///
- /// This method finds the existing `ContactImageEntryStored` object by its `contactId` and updates
- /// its properties with the values from the provided `ContactImageEntry`. If no matching entry exists,
- /// it does nothing.
- ///
- /// - Parameter contactImageEntry: The `ContactImageEntry` object with updated values.
- func updateContactImageEntry(_ contactImageEntry: ContactImageEntry) async {
- await backgroundContext.perform {
- let fetchRequest: NSFetchRequest<ContactImageEntryStored> = ContactImageEntryStored.fetchRequest()
- fetchRequest.predicate = NSPredicate(format: "contactId == %@", contactImageEntry.contactId ?? "")
- do {
- if let existingEntry = try self.backgroundContext.fetch(fetchRequest).first {
- // Update the properties of the existing entry
- existingEntry.name = contactImageEntry.name
- existingEntry.layout = contactImageEntry.layout.rawValue
- existingEntry.ring = contactImageEntry.ring.rawValue
- existingEntry.primary = contactImageEntry.primary.rawValue
- existingEntry.top = contactImageEntry.top.rawValue
- existingEntry.bottom = contactImageEntry.bottom.rawValue
- existingEntry.hasHighContrast = contactImageEntry.hasHighContrast
- existingEntry.ringWidth = Int16(contactImageEntry.ringWidth.rawValue)
- existingEntry.ringGap = Int16(contactImageEntry.ringGap.rawValue)
- existingEntry.colorMode = contactImageEntry.colorMode.rawValue
- existingEntry.fontSize = Int16(contactImageEntry.fontSize.rawValue)
- existingEntry.fontSizeSecondary = Int16(contactImageEntry.secondaryFontSize.rawValue)
- existingEntry.fontWeight = contactImageEntry.fontWeight.asString
- existingEntry.fontWidth = contactImageEntry.fontWidth.asString
- guard self.backgroundContext.hasChanges else { return }
- try self.backgroundContext.save()
- } else {
- debugPrint(
- "\(DebuggingIdentifiers.failed) \(#file) \(#function) No matching Contact Trick Entry found to update."
- )
- }
- } catch let error as NSError {
- debugPrint(
- "\(DebuggingIdentifiers.failed) \(#file) \(#function) Failed to update Contact Trick Entry with error: \(error.userInfo)"
- )
- }
- }
- }
- /// Deletes a Contact Trick entry from Core Data.
- ///
- /// - Parameter objectID: The `NSManagedObjectID` of the object to delete.
- func deleteContactImageEntry(_ objectID: NSManagedObjectID) async {
- await CoreDataStack.shared.deleteObject(identifiedBy: objectID)
- }
- }
|