diff --git a/swift/apple/FirezoneKit/Sources/FirezoneKit/Models/Configuration.swift b/swift/apple/FirezoneKit/Sources/FirezoneKit/Models/Configuration.swift index 8c9b1b690..e4fbff3ca 100644 --- a/swift/apple/FirezoneKit/Sources/FirezoneKit/Models/Configuration.swift +++ b/swift/apple/FirezoneKit/Sources/FirezoneKit/Models/Configuration.swift @@ -80,7 +80,7 @@ public class Configuration: Codable { } } - func isOverridden(key: String) -> Bool { + func isOverridden(_ key: String) -> Bool { return overriddenKeys.contains(key) } } diff --git a/swift/apple/FirezoneKit/Sources/FirezoneKit/Views/SettingsView.swift b/swift/apple/FirezoneKit/Sources/FirezoneKit/Views/SettingsView.swift index 25be49020..ea859b957 100644 --- a/swift/apple/FirezoneKit/Sources/FirezoneKit/Views/SettingsView.swift +++ b/swift/apple/FirezoneKit/Sources/FirezoneKit/Views/SettingsView.swift @@ -72,6 +72,11 @@ class SettingsViewModel: ObservableObject { @Published var authURLString: String @Published var apiURLString: String @Published var logFilterString: String + @Published private(set) var isAuthURLOverridden = false + @Published private(set) var isApiURLOverridden = false + @Published private(set) var isLogFilterOverridden = false + @Published private(set) var shouldDisableApplyButton = false + @Published private(set) var shouldDisableResetButton = false @Published private(set) var areSettingsDefault = true @Published private(set) var areSettingsValid = true @Published private(set) var areSettingsSaved = true @@ -85,6 +90,7 @@ class SettingsViewModel: ObservableObject { updateDerivedState() + // Update our state from our text fields Publishers.CombineLatest3($authURLString, $apiURLString, $logFilterString) .receive(on: RunLoop.main) .sink { [weak self] (_, _, _) in @@ -93,6 +99,18 @@ class SettingsViewModel: ObservableObject { self.updateDerivedState() } .store(in: &cancellables) + + // Update our state from configuration updates + store.$configuration + .receive(on: RunLoop.main) + .sink { [weak self] newConfiguration in + self?.isAuthURLOverridden = newConfiguration?.isOverridden(Configuration.Keys.authURL) ?? false + self?.isApiURLOverridden = newConfiguration?.isOverridden(Configuration.Keys.apiURL) ?? false + self?.isLogFilterOverridden = newConfiguration?.isOverridden(Configuration.Keys.logFilter) ?? false + + self?.updateDerivedState() + } + .store(in: &cancellables) } private func updateDerivedState() { @@ -119,6 +137,14 @@ class SettingsViewModel: ObservableObject { self.areSettingsDefault = (self.authURLString == Configuration.defaultAuthURL.absoluteString && self.apiURLString == Configuration.defaultApiURL.absoluteString && self.logFilterString == Configuration.defaultLogFilter) + + self.shouldDisableApplyButton = ( + isAuthURLOverridden && isApiURLOverridden && isLogFilterOverridden + ) || areSettingsSaved || !areSettingsValid + + self.shouldDisableResetButton = ( + isAuthURLOverridden && isApiURLOverridden && isLogFilterOverridden + ) || areSettingsDefault } func applySettingsToStore() async throws { @@ -237,9 +263,7 @@ public struct SettingsView: View { withErrorHandler { try await action.performAction(on: self) } } } - .disabled( - (viewModel.areSettingsSaved || !viewModel.areSettingsValid) - ) + .disabled(viewModel.shouldDisableApplyButton) } ToolbarItem(placement: .navigationBarLeading) { Button("Cancel") { @@ -315,18 +339,21 @@ public struct SettingsView: View { text: $viewModel.authURLString, prompt: Text(PlaceholderText.authBaseURL) ) + .disabled(viewModel.isAuthURLOverridden) TextField( "API URL:", text: $viewModel.apiURLString, prompt: Text(PlaceholderText.apiURL) ) + .disabled(viewModel.isApiURLOverridden) TextField( "Log Filter:", text: $viewModel.logFilterString, prompt: Text(PlaceholderText.logFilter) ) + .disabled(viewModel.isLogFilterOverridden) Text(FootnoteText.forAdvanced ?? "") .foregroundStyle(.secondary) @@ -344,7 +371,7 @@ public struct SettingsView: View { } } ) - .disabled(viewModel.areSettingsSaved || !viewModel.areSettingsValid) + .disabled(viewModel.shouldDisableApplyButton) Button( "Reset to Defaults", @@ -352,7 +379,7 @@ public struct SettingsView: View { viewModel.revertToDefaultSettings() } ) - .disabled(viewModel.areSettingsDefault) + .disabled(viewModel.shouldDisableResetButton) } .padding(.top, 5) } @@ -383,6 +410,7 @@ public struct SettingsView: View { .autocorrectionDisabled() .textInputAutocapitalization(.never) .submitLabel(.done) + .disabled(viewModel.isAuthURLOverridden) } VStack(alignment: .leading, spacing: 2) { Text("API URL") @@ -395,6 +423,7 @@ public struct SettingsView: View { .autocorrectionDisabled() .textInputAutocapitalization(.never) .submitLabel(.done) + .disabled(viewModel.isApiURLOverridden) } VStack(alignment: .leading, spacing: 2) { Text("Log Filter") @@ -407,6 +436,7 @@ public struct SettingsView: View { .autocorrectionDisabled() .textInputAutocapitalization(.never) .submitLabel(.done) + .disabled(viewModel.isLogFilterOverridden) } HStack { Spacer() @@ -416,7 +446,7 @@ public struct SettingsView: View { viewModel.revertToDefaultSettings() } ) - .disabled(viewModel.areSettingsDefault) + .disabled(viewModel.shouldDisableResetButton) Spacer() } },