// // 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 { 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 backend: Constants.Backend { get { Constants.Backend(rawValue: backendString) ?? .de } set { backendString = newValue.rawValue } } public var backendString: String = Constants.Backend.de.rawValue { didSet { defaults.backendString = backendString } } 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: \.backendString, for: \.backendString) observe(key: \.user, for: \.userData) register(defaultValues: [ .recognizeAlternativeOrder: false, .recognizeShortenedNumbers: false, .defaultRegion: "761", .recordBeep: false, .showDebugInfo: false, .backendString: Constants.Backend.de.rawValue ]) } 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 })) } }