Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: gracefully shutdown app #25

Merged
merged 2 commits into from
Jan 22, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions Coder Desktop/Coder Desktop/Coder_DesktopApp.swift
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,14 @@ class AppDelegate: NSObject, NSApplicationDelegate {
}
}

func applicationShouldTerminate(_: NSApplication) -> NSApplication.TerminateReply {
Task {
await vpn.stop()
NSApp.reply(toApplicationShouldTerminate: true)
}
return .terminateLater
}

func applicationShouldTerminateAfterLastWindowClosed(_: NSApplication) -> Bool {
false
}
Expand Down
43 changes: 31 additions & 12 deletions Coder Desktop/Coder Desktop/Preview Content/PreviewVPN.swift
Original file line number Diff line number Diff line change
Expand Up @@ -24,27 +24,46 @@ final class PreviewVPN: Coder_Desktop.VPNService {
self.shouldFail = shouldFail
}

var startTask: Task<Void, Never>?
func start() async {
state = .connecting
do {
try await Task.sleep(for: .seconds(10))
} catch {
state = .failed(.longTestError)
if await startTask?.value != nil {
return
}
state = shouldFail ? .failed(.longTestError) : .connected

startTask = Task {
state = .connecting
do {
try await Task.sleep(for: .seconds(5))
} catch {
state = .failed(.longTestError)
return
}
state = shouldFail ? .failed(.longTestError) : .connected
}
defer { startTask = nil }
await startTask?.value
}

var stopTask: Task<Void, Never>?
func stop() async {
await startTask?.value
guard state == .connected else { return }
state = .disconnecting
do {
try await Task.sleep(for: .seconds(10))
} catch {
state = .failed(.longTestError)
if await stopTask?.value != nil {
return
}
state = .disabled

stopTask = Task {
state = .disconnecting
do {
try await Task.sleep(for: .seconds(5))
} catch {
state = .failed(.longTestError)
return
}
state = .disabled
}
defer { stopTask = nil }
await stopTask?.value
}

func configureTunnelProviderProtocol(proto _: NETunnelProviderProtocol?) {
Expand Down
38 changes: 29 additions & 9 deletions Coder Desktop/Coder Desktop/VPNService.swift
Original file line number Diff line number Diff line change
Expand Up @@ -63,20 +63,40 @@ final class CoderVPNService: NSObject, VPNService {
installSystemExtension()
}

var startTask: Task<Void, Never>?
func start() async {
tunnelState = .connecting
await enableNetworkExtension()
if await startTask?.value != nil {
return
}
startTask = Task {
tunnelState = .connecting
await enableNetworkExtension()

// TODO: enable communication with the NetworkExtension to track state and agents. For
// now, just pretend it worked...
tunnelState = .connected
// TODO: enable communication with the NetworkExtension to track state and agents. For
// now, just pretend it worked...
tunnelState = .connected
}
defer { startTask = nil }
await startTask?.value
}

var stopTask: Task<Void, Never>?
func stop() async {
tunnelState = .disconnecting
await disableNetworkExtension()
// TODO: determine when the NetworkExtension is completely disconnected
tunnelState = .disabled
// Wait for a start operation to finish first
await startTask?.value
guard state == .connected else { return }
if await stopTask?.value != nil {
return
}
stopTask = Task {
tunnelState = .disconnecting
await disableNetworkExtension()

// TODO: determine when the NetworkExtension is completely disconnected
tunnelState = .disabled
}
defer { stopTask = nil }
await stopTask?.value
}

func configureTunnelProviderProtocol(proto: NETunnelProviderProtocol?) {
Expand Down
5 changes: 1 addition & 4 deletions Coder Desktop/Coder Desktop/Views/VPNMenu.swift
Original file line number Diff line number Diff line change
Expand Up @@ -59,10 +59,7 @@ struct VPNMenu<VPN: VPNService, S: Session>: View {
}.buttonStyle(.plain)
TrayDivider()
Button {
Task {
await vpn.stop()
NSApp.terminate(nil)
}
NSApp.terminate(nil)
} label: {
ButtonRowView {
Text("Quit")
Expand Down