Selected server and better settings
This commit is contained in:
@@ -7,7 +7,7 @@
|
||||
|
||||
import Foundation
|
||||
|
||||
struct Server: Identifiable, Codable
|
||||
struct Server: Identifiable, Codable, Equatable
|
||||
{
|
||||
let serviceName: String?
|
||||
let baseURL: URL
|
||||
|
||||
@@ -9,44 +9,106 @@ import Foundation
|
||||
|
||||
struct Settings
|
||||
{
|
||||
var configuredServers: [Server]
|
||||
var selectedServer: Server?
|
||||
|
||||
var configuredServers: [Server] {
|
||||
willSet {
|
||||
// Set selected server to whatever the first server is, if we're adding the first one.
|
||||
if configuredServers.isEmpty && !newValue.isEmpty && selectedServer == nil {
|
||||
selectedServer = newValue.first
|
||||
}
|
||||
|
||||
// If the selected server is being removed, set it to something else
|
||||
if !newValue.contains(where: { $0 == selectedServer }) {
|
||||
selectedServer = newValue.first // nil if empty
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var isConfigured: Bool { !configuredServers.isEmpty }
|
||||
|
||||
static func fromDefaults() -> Settings {
|
||||
let defaults = UserDefaults.standard
|
||||
return Settings(
|
||||
selectedServer: defaults[SelectedServerKey.self],
|
||||
configuredServers: defaults[ConfiguredServersKey.self]
|
||||
)
|
||||
}
|
||||
|
||||
func save() {
|
||||
let defaults = UserDefaults.standard
|
||||
defaults[ConfiguredServersKey.self] = configuredServers
|
||||
defaults[SelectedServerKey.self] = selectedServer
|
||||
|
||||
postSettingsChanged()
|
||||
}
|
||||
|
||||
func postSettingsChanged() {
|
||||
NotificationCenter.default.post(name: .settingsChanged, object: nil)
|
||||
}
|
||||
|
||||
// MARK: - Modifiers
|
||||
|
||||
func selectedServer(_ server: Server?) -> Self {
|
||||
var copy = self
|
||||
copy.selectedServer = server
|
||||
return copy
|
||||
}
|
||||
|
||||
func configuredServers(_ servers: [Server]) -> Self {
|
||||
var copy = self
|
||||
copy.configuredServers = servers
|
||||
return copy
|
||||
}
|
||||
|
||||
var isConfigured: Bool {
|
||||
!configuredServers.isEmpty
|
||||
}
|
||||
|
||||
static func fromDefaults() -> Settings {
|
||||
let configuredServers: [Server] = {
|
||||
guard let configuredServersData = UserDefaults.standard.data(forKey: Keys.configuredServers.rawValue)
|
||||
else { return [] }
|
||||
|
||||
guard let configuredServers = try? PropertyListDecoder().decode([Server].self, from: configuredServersData)
|
||||
else { return [] }
|
||||
|
||||
return configuredServers
|
||||
}()
|
||||
|
||||
return Settings(configuredServers: configuredServers)
|
||||
}
|
||||
|
||||
func save() {
|
||||
let configuredServersData = try! PropertyListEncoder().encode(configuredServers)
|
||||
UserDefaults.standard.set(configuredServersData, forKey: Keys.configuredServers.rawValue)
|
||||
NotificationCenter.default.post(name: .settingsChanged, object: nil)
|
||||
return copy
|
||||
}
|
||||
|
||||
// MARK: - Types
|
||||
|
||||
enum Keys: String
|
||||
{
|
||||
case selectedServer
|
||||
case configuredServers
|
||||
}
|
||||
|
||||
fileprivate protocol Key
|
||||
{
|
||||
associatedtype Value: Codable
|
||||
|
||||
static var defaultValue: Value { get }
|
||||
static var key: String { get }
|
||||
}
|
||||
|
||||
private struct ConfiguredServersKey: Key {
|
||||
static var defaultValue: [Server] { [] }
|
||||
}
|
||||
|
||||
private struct SelectedServerKey: Key {
|
||||
static var defaultValue: Server? { nil }
|
||||
}
|
||||
}
|
||||
|
||||
extension UserDefaults
|
||||
{
|
||||
fileprivate subscript<T: Settings.Key>(_ type: T.Type) -> T.Value {
|
||||
get {
|
||||
guard let data = data(forKey: type.key)
|
||||
else { return type.defaultValue }
|
||||
|
||||
guard let value = try? PropertyListDecoder().decode(type.Value, from: data)
|
||||
else { return type.defaultValue }
|
||||
|
||||
return value
|
||||
}
|
||||
|
||||
set {
|
||||
let data = try? PropertyListEncoder().encode(newValue)
|
||||
set(data, forKey: type.key)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension Settings.Key
|
||||
{
|
||||
static var key: String { Mirror(reflecting: Self.self).description }
|
||||
}
|
||||
|
||||
extension Notification.Name
|
||||
|
||||
Reference in New Issue
Block a user