From febf414d68164542df202328eb944d05a3866672 Mon Sep 17 00:00:00 2001 From: Ethan Dickson Date: Thu, 13 Feb 2025 01:38:29 +1100 Subject: [PATCH 1/3] fix: temporarily disable vpn toggle after toggling off --- .../Coder Desktop/Views/VPNMenu.swift | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/Coder Desktop/Coder Desktop/Views/VPNMenu.swift b/Coder Desktop/Coder Desktop/Views/VPNMenu.swift index 0c70c1a..97ea6d2 100644 --- a/Coder Desktop/Coder Desktop/Views/VPNMenu.swift +++ b/Coder Desktop/Coder Desktop/Views/VPNMenu.swift @@ -5,6 +5,13 @@ struct VPNMenu: View { @EnvironmentObject var session: S @Environment(\.openSettings) private var openSettings + // There appears to be a race between the VPN service reporting itself as disconnected, + // and the system extension process exiting. When the VPN is toggled off and on quickly, + // an error is shown: "The VPN session failed because an internal error occurred". + // This forces the user to wait a few seconds before they can toggle the VPN back on. + @State private var waitCleanup = false + private var waitCleanupDuration: Duration = .seconds(4) + let inspection = Inspection() var body: some View { @@ -16,7 +23,7 @@ struct VPNMenu: View { Toggle(isOn: Binding( get: { vpn.state == .connected || vpn.state == .connecting }, set: { isOn in Task { - if isOn { await vpn.start() } else { await vpn.stop() } + if isOn { await vpn.start() } else { await stop() } } } )) { @@ -86,11 +93,21 @@ struct VPNMenu: View { } private var vpnDisabled: Bool { + waitCleanup || !session.hasSession || vpn.state == .connecting || vpn.state == .disconnecting || vpn.state == .failed(.systemExtensionError(.needsUserApproval)) } + + private func stop() async { + await vpn.stop() + waitCleanup = true + Task { + try await Task.sleep(for: waitCleanupDuration) + waitCleanup = false + } + } } func openSystemExtensionSettings() { From cfb3dd59315d61cacce6961df28825fe5fe46837 Mon Sep 17 00:00:00 2001 From: Ethan Dickson Date: Thu, 13 Feb 2025 01:44:08 +1100 Subject: [PATCH 2/3] fixup --- Coder Desktop/Coder Desktop/Views/VPNMenu.swift | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Coder Desktop/Coder Desktop/Views/VPNMenu.swift b/Coder Desktop/Coder Desktop/Views/VPNMenu.swift index 97ea6d2..c748916 100644 --- a/Coder Desktop/Coder Desktop/Views/VPNMenu.swift +++ b/Coder Desktop/Coder Desktop/Views/VPNMenu.swift @@ -10,7 +10,7 @@ struct VPNMenu: View { // an error is shown: "The VPN session failed because an internal error occurred". // This forces the user to wait a few seconds before they can toggle the VPN back on. @State private var waitCleanup = false - private var waitCleanupDuration: Duration = .seconds(4) + private var waitCleanupDuration: Duration = .seconds(4) let inspection = Inspection() @@ -94,7 +94,7 @@ struct VPNMenu: View { private var vpnDisabled: Bool { waitCleanup || - !session.hasSession || + !session.hasSession || vpn.state == .connecting || vpn.state == .disconnecting || vpn.state == .failed(.systemExtensionError(.needsUserApproval)) @@ -104,7 +104,7 @@ struct VPNMenu: View { await vpn.stop() waitCleanup = true Task { - try await Task.sleep(for: waitCleanupDuration) + try? await Task.sleep(for: waitCleanupDuration) waitCleanup = false } } From e42502bfe02fbb7184826b1548fea872283ecd11 Mon Sep 17 00:00:00 2001 From: Ethan Dickson Date: Thu, 13 Feb 2025 02:09:53 +1100 Subject: [PATCH 3/3] longer --- Coder Desktop/Coder Desktop/Views/VPNMenu.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Coder Desktop/Coder Desktop/Views/VPNMenu.swift b/Coder Desktop/Coder Desktop/Views/VPNMenu.swift index c748916..b41cdbb 100644 --- a/Coder Desktop/Coder Desktop/Views/VPNMenu.swift +++ b/Coder Desktop/Coder Desktop/Views/VPNMenu.swift @@ -10,7 +10,7 @@ struct VPNMenu: View { // an error is shown: "The VPN session failed because an internal error occurred". // This forces the user to wait a few seconds before they can toggle the VPN back on. @State private var waitCleanup = false - private var waitCleanupDuration: Duration = .seconds(4) + private var waitCleanupDuration: Duration = .seconds(6) let inspection = Inspection()