Late dismissal after changing active provider server (#804)
The dismissal action waited until the current connection was disconnected. Consider that AppContext makes the explicit .connect() redundant, reconnection is already happening after saving a profile while connected.
This commit is contained in:
parent
3f7ad5bf57
commit
fff21c3250
|
@ -23,12 +23,14 @@
|
|||
// along with Passepartout. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
|
||||
import CommonUtils
|
||||
import PassepartoutKit
|
||||
import SwiftUI
|
||||
|
||||
extension ProviderEntityViewProviding where Self: ProviderCompatibleModule, EntityType.Configuration: ProviderConfigurationIdentifiable & Codable {
|
||||
func vpnProviderEntityView(
|
||||
with provider: ModuleMetadata.Provider,
|
||||
errorHandler: ErrorHandler,
|
||||
onSelect: @escaping (any ProviderEntity & Encodable) async throws -> Void
|
||||
) -> some View {
|
||||
let selectedEntity = try? provider
|
||||
|
@ -40,6 +42,7 @@ extension ProviderEntityViewProviding where Self: ProviderCompatibleModule, Enti
|
|||
return VPNProviderServerCoordinator(
|
||||
moduleId: id,
|
||||
providerId: provider.id,
|
||||
errorHandler: errorHandler,
|
||||
selectedEntity: selectedEntity,
|
||||
onSelect: onSelect
|
||||
)
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
// along with Passepartout. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
|
||||
import CommonUtils
|
||||
import PassepartoutKit
|
||||
import SwiftUI
|
||||
|
||||
|
@ -32,6 +33,7 @@ protocol ProviderEntityViewProviding {
|
|||
@MainActor
|
||||
func providerEntityView(
|
||||
with provider: ModuleMetadata.Provider,
|
||||
errorHandler: ErrorHandler,
|
||||
onSelect: @escaping (any ProviderEntity & Encodable) async throws -> Void
|
||||
) -> EntityContent
|
||||
}
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
|
||||
import AppLibrary
|
||||
import CommonLibrary
|
||||
import CommonUtils
|
||||
import PassepartoutKit
|
||||
import SwiftUI
|
||||
|
||||
|
@ -51,6 +52,9 @@ public struct AppCoordinator: View, AppCoordinatorConforming {
|
|||
@State
|
||||
private var profilePath = NavigationPath()
|
||||
|
||||
@StateObject
|
||||
private var errorHandler: ErrorHandler = .default()
|
||||
|
||||
public init(
|
||||
profileManager: ProfileManager,
|
||||
tunnel: ExtendedTunnel,
|
||||
|
@ -114,6 +118,7 @@ extension AppCoordinator {
|
|||
tunnel: tunnel,
|
||||
registry: registry,
|
||||
isImporting: $isImporting,
|
||||
errorHandler: errorHandler,
|
||||
flow: .init(
|
||||
onEditProfile: {
|
||||
guard let profile = profileManager.profile(withId: $0.id) else {
|
||||
|
@ -167,7 +172,8 @@ extension AppCoordinator {
|
|||
tunnel: tunnel,
|
||||
profile: profile,
|
||||
module: module,
|
||||
provider: provider
|
||||
provider: provider,
|
||||
errorHandler: errorHandler
|
||||
)
|
||||
|
||||
case .settings:
|
||||
|
|
|
@ -40,14 +40,14 @@ struct ProfileContainerView: View, Routable {
|
|||
@Binding
|
||||
var isImporting: Bool
|
||||
|
||||
@ObservedObject
|
||||
var errorHandler: ErrorHandler
|
||||
|
||||
var flow: ProfileFlow?
|
||||
|
||||
@StateObject
|
||||
private var interactiveManager = InteractiveManager()
|
||||
|
||||
@StateObject
|
||||
private var errorHandler: ErrorHandler = .default()
|
||||
|
||||
var body: some View {
|
||||
debugChanges()
|
||||
return innerView
|
||||
|
@ -150,7 +150,8 @@ private struct PreviewView: View {
|
|||
profileManager: .mock,
|
||||
tunnel: .mock,
|
||||
registry: Registry(),
|
||||
isImporting: .constant(false)
|
||||
isImporting: .constant(false),
|
||||
errorHandler: .default()
|
||||
)
|
||||
}
|
||||
.withMockEnvironment()
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
//
|
||||
|
||||
import AppLibrary
|
||||
import CommonUtils
|
||||
import PassepartoutKit
|
||||
import SwiftUI
|
||||
|
||||
|
@ -44,9 +45,15 @@ struct ProviderEntitySelector: View {
|
|||
|
||||
let provider: ModuleMetadata.Provider
|
||||
|
||||
let errorHandler: ErrorHandler
|
||||
|
||||
var body: some View {
|
||||
if let viewProvider = module as? any ProviderEntityViewProviding {
|
||||
AnyView(viewProvider.providerEntityView(with: provider, onSelect: onSelect))
|
||||
AnyView(viewProvider.providerEntityView(
|
||||
with: provider,
|
||||
errorHandler: errorHandler,
|
||||
onSelect: onSelect
|
||||
))
|
||||
} else {
|
||||
fatalError("Module got too far without being ProviderEntityViewProviding: \(module)")
|
||||
}
|
||||
|
@ -58,16 +65,15 @@ private extension ProviderEntitySelector {
|
|||
pp_log(.app, .info, "Select new provider entity: \(entity)")
|
||||
|
||||
var builder = profile.builder()
|
||||
try builder.setProviderEntity(entity, forModuleWithId: module.id)
|
||||
let newProfile = try builder.tryBuild()
|
||||
try await profileManager.save(newProfile)
|
||||
do {
|
||||
try builder.setProviderEntity(entity, forModuleWithId: module.id)
|
||||
let newProfile = try builder.tryBuild()
|
||||
try await profileManager.save(newProfile)
|
||||
|
||||
Task {
|
||||
do {
|
||||
try await tunnel.connect(with: newProfile, processor: profileProcessor)
|
||||
} catch {
|
||||
pp_log(.app, .error, "Unable to connect with new provider entity: \(error)")
|
||||
}
|
||||
// will reconnect via AppContext observation
|
||||
} catch {
|
||||
pp_log(.app, .error, "Unable to save new provider entity: \(error)")
|
||||
throw error
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
// along with Passepartout. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
|
||||
import CommonUtils
|
||||
import PassepartoutKit
|
||||
import SwiftUI
|
||||
|
||||
|
@ -35,8 +36,9 @@ extension OpenVPNModule.Builder: ModuleViewProviding {
|
|||
extension OpenVPNModule: ProviderEntityViewProviding {
|
||||
func providerEntityView(
|
||||
with provider: ModuleMetadata.Provider,
|
||||
errorHandler: ErrorHandler,
|
||||
onSelect: @escaping (any ProviderEntity & Encodable) async throws -> Void
|
||||
) -> some View {
|
||||
vpnProviderEntityView(with: provider, onSelect: onSelect)
|
||||
vpnProviderEntityView(with: provider, errorHandler: errorHandler, onSelect: onSelect)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -36,13 +36,13 @@ struct VPNProviderServerCoordinator<Configuration>: View where Configuration: Pr
|
|||
|
||||
let providerId: ProviderID
|
||||
|
||||
@ObservedObject
|
||||
var errorHandler: ErrorHandler
|
||||
|
||||
let selectedEntity: VPNEntity<Configuration>?
|
||||
|
||||
let onSelect: (VPNEntity<Configuration>) async throws -> Void
|
||||
|
||||
@StateObject
|
||||
private var errorHandler: ErrorHandler = .default()
|
||||
|
||||
var body: some View {
|
||||
NavigationStack {
|
||||
VPNProviderServerView(
|
||||
|
@ -67,7 +67,6 @@ struct VPNProviderServerCoordinator<Configuration>: View where Configuration: Pr
|
|||
}
|
||||
}
|
||||
}
|
||||
.withErrorHandler(errorHandler)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -77,8 +76,8 @@ private extension VPNProviderServerCoordinator {
|
|||
Task {
|
||||
do {
|
||||
let entity = VPNEntity(server: server, preset: preset)
|
||||
try await onSelect(entity)
|
||||
dismiss()
|
||||
try await onSelect(entity)
|
||||
} catch {
|
||||
pp_log(.app, .fault, "Unable to select server \(server.serverId) for provider \(server.provider.id): \(error)")
|
||||
errorHandler.handle(error, title: Strings.Global.servers)
|
||||
|
|
Loading…
Reference in New Issue