AutoCat/AutoCatCore/Services/SettingsService/SettingsService.swift

121 lines
3.4 KiB
Swift

//
// 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 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<T>(key userDefaultsKey: KeyPath<UserDefaults,T>, for settingsKey: ReferenceWritableKeyPath<SettingsService,T>) 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
}))
}
}