import Foundation class FavoritesManager: ObservableObject { static let shared = FavoritesManager() @Published var favorites: [Wallpaper] = [] /// Latest persistence failure, surfaced so the UI/app layer can react. /// Corrupt or unwritable stored data no longer fails silently — the /// manager keeps the in-memory list intact but exposes the cause. @Published var persistenceError: String? private let key = "favoriteWallpapers" private let defaults: UserDefaults private let encoder: JSONEncoder private let decoder: JSONDecoder init( defaults: UserDefaults = .standard, encoder: JSONEncoder = JSONEncoder(), decoder: JSONDecoder = JSONDecoder() ) { self.defaults = defaults self.encoder = encoder self.decoder = decoder loadFavorites() } func toggleFavorite(_ wallpaper: Wallpaper) { if let index = favorites.firstIndex(where: { $0.id == wallpaper.id }) { favorites.remove(at: index) } else { favorites.insert(wallpaper, at: 0) } saveFavorites() } func isFavorite(_ wallpaper: Wallpaper) -> Bool { return favorites.contains(where: { $0.id == wallpaper.id }) } private func saveFavorites() { persist(currentFavorites()) } /// Public for diagnostics/testing. Encodes the current state through the /// configured encoder and reports the first failure through /// `persistenceError`. func persist(_ wallpapers: [Wallpaper]) { do { let data = try encoder.encode(wallpapers) defaults.set(data, forKey: key) persistenceError = nil } catch { persistenceError = "Failed to save favorites: \(error.localizedDescription)" } } /// Decodes the persisted list through the configured decoder. Public to /// keep the load path testable while letting the manager choose its own /// defaults in production. Sets `persistenceError` when the stored data is /// missing or undecodable so callers can react without inspecting logs. func decodeFavorites(from data: Data?) -> [Wallpaper]? { guard let data else { persistenceError = nil return nil } do { let decoded = try decoder.decode([Wallpaper].self, from: data) persistenceError = nil return decoded } catch { persistenceError = "Failed to load favorites: \(error.localizedDescription)" return nil } } private func loadFavorites() { favorites = currentFavorites() } private func currentFavorites() -> [Wallpaper] { let stored = defaults.data(forKey: key) return decodeFavorites(from: stored) ?? favorites } }