Files
ios-client/NetBirdWidgetExtension/ToggleVPNIntent.swift
evgeniyChepelev ca8cf59d55 Feature/widget toggle switch UI (#138)
* feat(widget): replace action button with toggle switch control

All connection states now render as a unified toggle-style control:
green (connected), red (disconnected), orange with spinner (transitioning).

* fix(widget+auth): toggle UI, VPN state sync, and login flow fixes

* fix(widget+sdk): update Go SDK to fix/ios-debug-bundle, fix Control Center transitioning state and app disconnect flash

* fix(widget): remove transitioning states, update toggle colors and UI

* Change color indicator

* fix(widget+auth): toggle UI, VPN state sync, and login flow fixes

* fix framework version
2026-06-15 13:32:57 +02:00

51 lines
1.9 KiB
Swift

import AppIntents
import NetworkExtension
import WidgetKit
/// Used by the widget buttons. For Siri/Shortcuts use ConnectVPNIntent or DisconnectVPNIntent.
@available(iOS 16.0, *)
struct ToggleVPNIntent: AppIntent {
static var title: LocalizedStringResource = "Toggle NetBird VPN"
static var description: IntentDescription = "Connect or disconnect the NetBird VPN."
static var openAppWhenRun: Bool = false
@Parameter(title: "Action")
var action: String
init() { self.action = "connect" }
init(action: String) { self.action = action }
func perform() async throws -> some IntentResult {
guard let manager = try await VPNIntentHelpers.loadManager() else {
WidgetCenter.shared.reloadAllTimelines()
return .result()
}
let defaults = VPNIntentHelpers.defaults
if action == "connect" {
guard !VPNIntentHelpers.isLoginRequired else {
WidgetCenter.shared.reloadAllTimelines()
return .result()
}
let status = manager.connection.status
if status == .disconnected || status == .invalid,
let session = manager.connection as? NETunnelProviderSession {
try VPNIntentHelpers.startTunnel(session: session)
}
} else {
let neStatus = manager.connection.status
let persistedRaw = defaults?.string(forKey: WidgetConstants.keyVPNStatus) ?? "disconnected"
let persisted = WidgetVPNStatus(rawValue: persistedRaw) ?? .disconnected
let shouldDisconnect = neStatus == .connected || neStatus == .connecting
|| persisted == .connected || persisted == .connecting
if shouldDisconnect {
manager.connection.stopVPNTunnel()
}
}
await VPNIntentHelpers.waitForStableState(manager: manager)
return .result()
}
}