diff --git a/Coder-Desktop/Coder-Desktop/Coder_DesktopApp.swift b/Coder-Desktop/Coder-Desktop/Coder_DesktopApp.swift index a8d0c946..091a1c25 100644 --- a/Coder-Desktop/Coder-Desktop/Coder_DesktopApp.swift +++ b/Coder-Desktop/Coder-Desktop/Coder_DesktopApp.swift @@ -37,6 +37,10 @@ class AppDelegate: NSObject, NSApplicationDelegate { vpn = CoderVPNService() state = AppState(onChange: vpn.configureTunnelProviderProtocol) fileSyncDaemon = MutagenDaemon() + if state.startVPNOnLaunch { + vpn.startWhenReady = true + } + vpn.installSystemExtension() } func applicationDidFinishLaunching(_: Notification) { @@ -68,9 +72,6 @@ class AppDelegate: NSObject, NSApplicationDelegate { if await !vpn.loadNetworkExtensionConfig() { state.reconfigure() } - if state.startVPNOnLaunch { - await vpn.start() - } } // TODO: Start the daemon only once a file sync is configured Task { @@ -78,6 +79,10 @@ class AppDelegate: NSObject, NSApplicationDelegate { } } + deinit { + NotificationCenter.default.removeObserver(self) + } + // This function MUST eventually call `NSApp.reply(toApplicationShouldTerminate: true)` // or return `.terminateNow` func applicationShouldTerminate(_: NSApplication) -> NSApplication.TerminateReply { diff --git a/Coder-Desktop/Coder-Desktop/VPN/VPNService.swift b/Coder-Desktop/Coder-Desktop/VPN/VPNService.swift index ca0a8ff3..22a3ad8b 100644 --- a/Coder-Desktop/Coder-Desktop/VPN/VPNService.swift +++ b/Coder-Desktop/Coder-Desktop/VPN/VPNService.swift @@ -18,6 +18,16 @@ enum VPNServiceState: Equatable { case disconnecting case connected case failed(VPNServiceError) + + var canBeStarted: Bool { + switch self { + // A tunnel failure should not prevent a reconnect attempt + case .disabled, .failed: + true + default: + false + } + } } enum VPNServiceError: Error, Equatable { @@ -54,11 +64,18 @@ final class CoderVPNService: NSObject, VPNService { guard neState == .enabled || neState == .disabled else { return .failed(.networkExtensionError(neState)) } + if startWhenReady, tunnelState.canBeStarted { + startWhenReady = false + Task { await start() } + } return tunnelState } @Published var menuState: VPNMenuState = .init() + // Whether the VPN should start as soon as possible + var startWhenReady: Bool = false + // systemExtnDelegate holds a reference to the SystemExtensionDelegate so that it doesn't get // garbage collected while the OSSystemExtensionRequest is in flight, since the OS framework // only stores a weak reference to the delegate. @@ -68,11 +85,6 @@ final class CoderVPNService: NSObject, VPNService { override init() { super.init() - installSystemExtension() - } - - deinit { - NotificationCenter.default.removeObserver(self) } func start() async { diff --git a/Coder-Desktop/Coder-DesktopTests/LoginFormTests.swift b/Coder-Desktop/Coder-DesktopTests/LoginFormTests.swift index a07ced3f..26f5883d 100644 --- a/Coder-Desktop/Coder-DesktopTests/LoginFormTests.swift +++ b/Coder-Desktop/Coder-DesktopTests/LoginFormTests.swift @@ -107,6 +107,12 @@ struct LoginTests { data: [.get: Client.encoder.encode(buildInfo)] ).register() + try Mock( + url: url.appendingPathComponent("/api/v2/users/me"), + statusCode: 200, + data: [.get: Client.encoder.encode(User(id: UUID(), username: "username"))] + ).register() + try await ViewHosting.host(view) { try await sut.inspection.inspect { view in try view.find(ViewType.TextField.self).setInput(url.absoluteString) pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy