import Foundation public extension UserDefaults { static var shared = UserDefaults(suiteName: "5YKZ4Y3DAW.group.com.intii.CopilotForXcode")! static func setupDefaultSettings() { shared.setupDefaultValue(for: \.quitXPCServiceOnXcodeAndAppQuit) shared.setupDefaultValue(for: \.realtimeSuggestionToggle) shared.setupDefaultValue(for: \.realtimeSuggestionDebounce) shared.setupDefaultValue(for: \.automaticallyCheckForUpdate) shared.setupDefaultValue(for: \.suggestionPresentationMode) shared.setupDefaultValue(for: \.widgetColorScheme) shared.setupDefaultValue(for: \.customCommands) let runNodeWith: NodeRunner = shared.value(for: \.runNodeWithInteractiveLoggedInShell) ? .bash : .env shared.setupDefaultValue(for: \.runNodeWith, defaultValue: runNodeWith) } } public protocol UserDefaultsStorable {} extension Int: UserDefaultsStorable {} extension Double: UserDefaultsStorable {} extension Bool: UserDefaultsStorable {} extension String: UserDefaultsStorable {} extension Data: UserDefaultsStorable {} extension URL: UserDefaultsStorable {} extension Array: RawRepresentable where Element: Codable { public init?(rawValue: String) { guard let data = rawValue.data(using: .utf8), let result = try? JSONDecoder().decode([Element].self, from: data) else { return nil } self = result } public var rawValue: String { guard let data = try? JSONEncoder().encode(self), let result = String(data: data, encoding: .utf8) else { return "[]" } return result } } public extension UserDefaults { // MARK: - Normal Types func value( for keyPath: KeyPath ) -> K.Value where K.Value: UserDefaultsStorable { let key = UserDefaultPreferenceKeys()[keyPath: keyPath] return (value(forKey: key.key) as? K.Value) ?? key.defaultValue } func set( _ value: K.Value, for keyPath: KeyPath ) where K.Value: UserDefaultsStorable { let key = UserDefaultPreferenceKeys()[keyPath: keyPath] set(value, forKey: key.key) } func setupDefaultValue( for keyPath: KeyPath ) where K.Value: UserDefaultsStorable { let key = UserDefaultPreferenceKeys()[keyPath: keyPath] if value(forKey: key.key) == nil { set(key.defaultValue, forKey: key.key) } } // MARK: - Raw Representable func value( for keyPath: KeyPath ) -> K.Value where K.Value: RawRepresentable, K.Value.RawValue == String { let key = UserDefaultPreferenceKeys()[keyPath: keyPath] guard let rawValue = value(forKey: key.key) as? String else { return key.defaultValue } return K.Value(rawValue: rawValue) ?? key.defaultValue } func value( for keyPath: KeyPath ) -> K.Value where K.Value: RawRepresentable, K.Value.RawValue == Int { let key = UserDefaultPreferenceKeys()[keyPath: keyPath] guard let rawValue = value(forKey: key.key) as? Int else { return key.defaultValue } return K.Value(rawValue: rawValue) ?? key.defaultValue } func set( _ value: K.Value, for keyPath: KeyPath ) where K.Value: RawRepresentable, K.Value.RawValue == String { let key = UserDefaultPreferenceKeys()[keyPath: keyPath] set(value.rawValue, forKey: key.key) } func set( _ value: K.Value, for keyPath: KeyPath ) where K.Value: RawRepresentable, K.Value.RawValue == Int { let key = UserDefaultPreferenceKeys()[keyPath: keyPath] set(value.rawValue, forKey: key.key) } func setupDefaultValue( for keyPath: KeyPath, defaultValue: K.Value? = nil ) where K.Value: RawRepresentable, K.Value.RawValue == String { let key = UserDefaultPreferenceKeys()[keyPath: keyPath] if value(forKey: key.key) == nil { set(defaultValue?.rawValue ?? key.defaultValue.rawValue, forKey: key.key) } } func setupDefaultValue( for keyPath: KeyPath, defaultValue: K.Value? = nil ) where K.Value: RawRepresentable, K.Value.RawValue == Int { let key = UserDefaultPreferenceKeys()[keyPath: keyPath] if value(forKey: key.key) == nil { set(defaultValue?.rawValue ?? key.defaultValue.rawValue, forKey: key.key) } } }