Externalize complex bindings (#329)
Some bindings are too convoluted, move them out of initializers.
This commit is contained in:
parent
0804c6b38e
commit
4173c7aa6c
|
@ -47,58 +47,14 @@ extension EndpointView {
|
|||
|
||||
@State private var selectedPort: UInt16 = 0
|
||||
|
||||
// XXX: do not escape mutating 'self', use constant providerManager
|
||||
init(currentProfile: ObservableProfile) {
|
||||
let providerManager: ProviderManager = .shared
|
||||
|
||||
self.providerManager = providerManager
|
||||
self.currentProfile = currentProfile
|
||||
|
||||
_builder = .init {
|
||||
if currentProfile.value.isProvider {
|
||||
guard let server = currentProfile.value.providerServer(providerManager) else {
|
||||
assertionFailure("Server not found")
|
||||
return .init()
|
||||
}
|
||||
guard let preset = currentProfile.value.providerPreset(server) else {
|
||||
assertionFailure("Preset not found")
|
||||
return .init()
|
||||
}
|
||||
guard let cfg = preset.openVPNConfiguration else {
|
||||
assertionFailure("Preset \(preset.id) (\(preset.name)) has no OpenVPN configuration")
|
||||
return .init()
|
||||
}
|
||||
var builder = cfg.builder(withFallbacks: true)
|
||||
try? builder.setRemotes(from: preset, with: server, excludingHostname: false)
|
||||
return builder
|
||||
} else if let cfg = currentProfile.value.hostOpenVPNSettings?.configuration {
|
||||
let builder = cfg.builder(withFallbacks: true)
|
||||
// pp_log.debug("Loading OpenVPN configuration: \(builder)")
|
||||
return builder
|
||||
}
|
||||
// fall back gracefully
|
||||
return .init()
|
||||
} set: {
|
||||
if currentProfile.value.isProvider {
|
||||
// readonly
|
||||
} else {
|
||||
pp_log.debug("Saving OpenVPN configuration: \($0)")
|
||||
currentProfile.value.hostOpenVPNSettings?.configuration = $0.build()
|
||||
}
|
||||
}
|
||||
_customEndpoint = .init {
|
||||
if currentProfile.value.isProvider {
|
||||
return currentProfile.value.providerCustomEndpoint
|
||||
} else {
|
||||
return currentProfile.value.hostOpenVPNSettings?.customEndpoint
|
||||
}
|
||||
} set: {
|
||||
if currentProfile.value.isProvider {
|
||||
currentProfile.value.providerCustomEndpoint = $0
|
||||
} else {
|
||||
currentProfile.value.hostOpenVPNSettings?.customEndpoint = $0
|
||||
}
|
||||
}
|
||||
_builder = currentProfile.builderBinding(providerManager: providerManager)
|
||||
_customEndpoint = currentProfile.customEndpointBinding
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
|
@ -280,3 +236,58 @@ private extension EndpointView.OpenVPNView {
|
|||
proxy.maybeScrollTo(customEndpoint?.id)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Bindings
|
||||
|
||||
private extension ObservableProfile {
|
||||
func builderBinding(providerManager: ProviderManager) -> Binding<OpenVPN.ConfigurationBuilder> {
|
||||
.init {
|
||||
if self.value.isProvider {
|
||||
guard let server = self.value.providerServer(providerManager) else {
|
||||
assertionFailure("Server not found")
|
||||
return .init()
|
||||
}
|
||||
guard let preset = self.value.providerPreset(server) else {
|
||||
assertionFailure("Preset not found")
|
||||
return .init()
|
||||
}
|
||||
guard let cfg = preset.openVPNConfiguration else {
|
||||
assertionFailure("Preset \(preset.id) (\(preset.name)) has no OpenVPN configuration")
|
||||
return .init()
|
||||
}
|
||||
var builder = cfg.builder(withFallbacks: true)
|
||||
try? builder.setRemotes(from: preset, with: server, excludingHostname: false)
|
||||
return builder
|
||||
} else if let cfg = self.value.hostOpenVPNSettings?.configuration {
|
||||
let builder = cfg.builder(withFallbacks: true)
|
||||
// pp_log.debug("Loading OpenVPN configuration: \(builder)")
|
||||
return builder
|
||||
}
|
||||
// fall back gracefully
|
||||
return .init()
|
||||
} set: {
|
||||
if self.value.isProvider {
|
||||
// readonly
|
||||
} else {
|
||||
pp_log.debug("Saving OpenVPN configuration: \($0)")
|
||||
self.value.hostOpenVPNSettings?.configuration = $0.build()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var customEndpointBinding: Binding<Endpoint?> {
|
||||
.init {
|
||||
if self.value.isProvider {
|
||||
return self.value.providerCustomEndpoint
|
||||
} else {
|
||||
return self.value.hostOpenVPNSettings?.customEndpoint
|
||||
}
|
||||
} set: {
|
||||
if self.value.isProvider {
|
||||
self.value.providerCustomEndpoint = $0
|
||||
} else {
|
||||
self.value.hostOpenVPNSettings?.customEndpoint = $0
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -39,7 +39,6 @@ extension EndpointView {
|
|||
|
||||
// var customPeer: Binding<Endpoint?>? = nil
|
||||
|
||||
// XXX: do not escape mutating 'self', use constant providerManager
|
||||
init(currentProfile: ObservableProfile, isReadonly: Bool) {
|
||||
let providerManager: ProviderManager = .shared
|
||||
|
||||
|
@ -47,36 +46,7 @@ extension EndpointView {
|
|||
self.currentProfile = currentProfile
|
||||
self.isReadonly = isReadonly
|
||||
|
||||
_builder = .init {
|
||||
if currentProfile.value.isProvider {
|
||||
guard let server = currentProfile.value.providerServer(providerManager) else {
|
||||
assertionFailure("Server not found")
|
||||
return .init()
|
||||
}
|
||||
guard let preset = currentProfile.value.providerPreset(server) else {
|
||||
assertionFailure("Preset not found")
|
||||
return .init()
|
||||
}
|
||||
guard let cfg = preset.wireGuardConfiguration else {
|
||||
assertionFailure("Preset \(preset.id) (\(preset.name)) has no WireGuard configuration")
|
||||
return .init()
|
||||
}
|
||||
return cfg.builder()
|
||||
} else if let cfg = currentProfile.value.hostWireGuardSettings?.configuration {
|
||||
let builder = cfg.builder()
|
||||
// pp_log.debug("Loading WireGuard configuration: \(builder)")
|
||||
return builder
|
||||
}
|
||||
// fall back gracefully
|
||||
return .init()
|
||||
} set: {
|
||||
if currentProfile.value.isProvider {
|
||||
// readonly
|
||||
} else {
|
||||
pp_log.debug("Saving WireGuard configuration: \($0)")
|
||||
currentProfile.value.hostWireGuardSettings?.configuration = $0.build()
|
||||
}
|
||||
}
|
||||
_builder = currentProfile.builderBinding(providerManager: providerManager)
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
|
@ -146,3 +116,40 @@ private extension EndpointView.WireGuardView {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Bindings
|
||||
|
||||
private extension ObservableProfile {
|
||||
func builderBinding(providerManager: ProviderManager) -> Binding<WireGuard.ConfigurationBuilder> {
|
||||
.init {
|
||||
if self.value.isProvider {
|
||||
guard let server = self.value.providerServer(providerManager) else {
|
||||
assertionFailure("Server not found")
|
||||
return .init()
|
||||
}
|
||||
guard let preset = self.value.providerPreset(server) else {
|
||||
assertionFailure("Preset not found")
|
||||
return .init()
|
||||
}
|
||||
guard let cfg = preset.wireGuardConfiguration else {
|
||||
assertionFailure("Preset \(preset.id) (\(preset.name)) has no WireGuard configuration")
|
||||
return .init()
|
||||
}
|
||||
return cfg.builder()
|
||||
} else if let cfg = self.value.hostWireGuardSettings?.configuration {
|
||||
let builder = cfg.builder()
|
||||
// pp_log.debug("Loading WireGuard configuration: \(builder)")
|
||||
return builder
|
||||
}
|
||||
// fall back gracefully
|
||||
return .init()
|
||||
} set: {
|
||||
if self.value.isProvider {
|
||||
// readonly
|
||||
} else {
|
||||
pp_log.debug("Saving WireGuard configuration: \($0)")
|
||||
self.value.hostWireGuardSettings?.configuration = $0.build()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -43,7 +43,6 @@ struct ProviderLocationView: View, ProviderProfileAvailability {
|
|||
currentProfile.value
|
||||
}
|
||||
|
||||
// XXX: do not escape mutating 'self', use constant providerManager
|
||||
init(currentProfile: ObservableProfile, isEditable: Bool, isPresented: Binding<Bool>) {
|
||||
let providerManager: ProviderManager = .shared
|
||||
|
||||
|
@ -51,24 +50,8 @@ struct ProviderLocationView: View, ProviderProfileAvailability {
|
|||
self.currentProfile = currentProfile
|
||||
self.isEditable = isEditable
|
||||
|
||||
_selectedServer = .init {
|
||||
guard let serverId = currentProfile.value.providerServerId else {
|
||||
return nil
|
||||
}
|
||||
return providerManager.server(withId: serverId)
|
||||
} set: {
|
||||
// user never selects a nil server
|
||||
guard let server = $0 else {
|
||||
return
|
||||
}
|
||||
currentProfile.value.setProviderServer(server)
|
||||
isPresented.wrappedValue = false
|
||||
}
|
||||
_favoriteLocationIds = .init {
|
||||
currentProfile.value.providerFavoriteLocationIds
|
||||
} set: {
|
||||
currentProfile.value.providerFavoriteLocationIds = $0
|
||||
}
|
||||
_selectedServer = currentProfile.selectedServerBinding(providerManager: providerManager, isPresented: isPresented)
|
||||
_favoriteLocationIds = currentProfile.providerFavoriteLocationIdsBinding
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
|
@ -323,3 +306,31 @@ private extension ProviderLocationView.ServerListView {
|
|||
proxy.maybeScrollTo(selectedServer?.id)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Bindings
|
||||
|
||||
private extension ObservableProfile {
|
||||
func selectedServerBinding(providerManager: ProviderManager, isPresented: Binding<Bool>) -> Binding<ProviderServer?> {
|
||||
.init {
|
||||
guard let serverId = self.value.providerServerId else {
|
||||
return nil
|
||||
}
|
||||
return providerManager.server(withId: serverId)
|
||||
} set: {
|
||||
// user never selects a nil server
|
||||
guard let server = $0 else {
|
||||
return
|
||||
}
|
||||
self.value.setProviderServer(server)
|
||||
isPresented.wrappedValue = false
|
||||
}
|
||||
}
|
||||
|
||||
var providerFavoriteLocationIdsBinding: Binding<Set<String>?> {
|
||||
.init {
|
||||
self.value.providerFavoriteLocationIds
|
||||
} set: {
|
||||
self.value.providerFavoriteLocationIds = $0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -37,7 +37,6 @@ struct ProviderPresetView: View {
|
|||
|
||||
@Binding private var selectedPreset: ProviderServer.Preset?
|
||||
|
||||
// XXX: do not escape mutating 'self', use constant providerManager
|
||||
init(currentProfile: ObservableProfile) {
|
||||
let providerManager: ProviderManager = .shared
|
||||
|
||||
|
@ -45,21 +44,7 @@ struct ProviderPresetView: View {
|
|||
self.currentProfile = currentProfile
|
||||
|
||||
server = currentProfile.value.providerServer(providerManager)
|
||||
_selectedPreset = .init {
|
||||
guard let serverId = currentProfile.value.providerServerId else {
|
||||
return nil
|
||||
}
|
||||
guard let server = providerManager.server(withId: serverId) else {
|
||||
return nil
|
||||
}
|
||||
return currentProfile.value.providerPreset(server)
|
||||
} set: {
|
||||
// user never selects a nil preset
|
||||
guard let preset = $0 else {
|
||||
return
|
||||
}
|
||||
currentProfile.value.setProviderPreset(preset)
|
||||
}
|
||||
_selectedPreset = currentProfile.selectedPresetBinding(providerManager: providerManager)
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
|
@ -106,3 +91,25 @@ private extension ProviderPresetView {
|
|||
server?.presets?.sorted() ?? []
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Bindings
|
||||
|
||||
private extension ObservableProfile {
|
||||
func selectedPresetBinding(providerManager: ProviderManager) -> Binding<ProviderServer.Preset?> {
|
||||
.init {
|
||||
guard let serverId = self.value.providerServerId else {
|
||||
return nil
|
||||
}
|
||||
guard let server = providerManager.server(withId: serverId) else {
|
||||
return nil
|
||||
}
|
||||
return self.value.providerPreset(server)
|
||||
} set: {
|
||||
// user never selects a nil preset
|
||||
guard let preset = $0 else {
|
||||
return
|
||||
}
|
||||
self.value.setProviderPreset(preset)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue