// // SettingsService.swift // AutoCatCore // // Created by Selim Mustafaev on 17.08.2024. // Copyright © 2024 Selim Mustafaev. All rights reserved. // import SwiftUI @Observable public final class SettingsService: SettingsServiceProtocol { public static let shared = SettingsService(defaults: .standard) let defaults: UserDefaults var observations: [NSKeyValueObservation] = [] let jsonEncoder = JSONEncoder() let jsonDecoder = JSONDecoder() public var user: User { get { if let data = userData { let result = try? jsonDecoder.decode(User.self, from: data) return result ?? User() } else { return User() } } set { if let json = try? jsonEncoder.encode(newValue) { userData = json } } } public var userData: Data? = nil { didSet { defaults.user = userData } } public var recognizeAlternativeOrder: Bool = false { didSet { defaults.recognizeAlternativeOrder = recognizeAlternativeOrder } } public var recognizeShortenedNumbers: Bool = false { didSet { defaults.recognizeShortenedNumbers = recognizeShortenedNumbers } } public var defaultRegion: String = "161" { didSet { defaults.defaultRegion = defaultRegion } } public var recordBeep: Bool = false { didSet { defaults.recordBeep = recordBeep } } public var showDebugInfo: Bool = false { didSet { defaults.showDebugInfo = showDebugInfo } } public var useTestBackend: Bool = false { didSet { defaults.useTestBackend = useTestBackend } } public init(defaults: UserDefaults) { self.defaults = defaults observe(key: \.recognizeAlternativeOrder, for: \.recognizeAlternativeOrder) observe(key: \.recognizeShortenedNumbers, for: \.recognizeShortenedNumbers) observe(key: \.defaultRegion, for: \.defaultRegion) observe(key: \.recordBeep, for: \.recordBeep) observe(key: \.showDebugInfo, for: \.showDebugInfo) observe(key: \.useTestBackend, for: \.useTestBackend) observe(key: \.user, for: \.userData) register(defaultValues: [ .recognizeAlternativeOrder: false, .recognizeShortenedNumbers: false, .defaultRegion: "761", .recordBeep: false, .showDebugInfo: false, .useTestBackend: false ]) } deinit { observations.forEach { $0.invalidate() } } func observe(key userDefaultsKey: KeyPath, for settingsKey: ReferenceWritableKeyPath) where T: Equatable { let observation = defaults.observe(userDefaultsKey, options: [.initial, .new]) { [weak self] _, change in guard let self else { return } if let new = change.newValue, self[keyPath: settingsKey] != new { self[keyPath: settingsKey] = new } } observations.append(observation) } func register(defaultValues: [SettingsKey: Any]) { defaults.register(defaults: defaultValues.reduce(into: [:], { (partialResult: inout [String: Any], tuple) in partialResult[tuple.key.rawValue] = tuple.value })) } }