You've already forked ios-client
mirror of
https://github.com/netbirdio/ios-client.git
synced 2026-05-22 17:10:12 -07:00
315283822c
* Add Home Screen widget with VPN toggle and refactor app activation logic - Add NetBirdWidgetExtension target with small/medium widget sizes - Support direct connect/disconnect from widget via interactive buttons (iOS 17+) - Detect missing VPN config or login-required state and open app via deep link - Poll for stable VPN state after toggle to prevent loader getting stuck - Add widget shared state keys to GlobalConstants and sync status from MainViewModel - Fix false "authentication required" alert on app resume after widget disconnect - Deduplicate app activation logic into shared startActivation/stopActivation - Extract polling helpers: updateDetailsIfChanged, updatePeersIfChanged, applyExtensionStatus
51 lines
1.9 KiB
Swift
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 {
|
|
defaults?.set(WidgetVPNStatus.connecting.rawValue, forKey: WidgetConstants.keyVPNStatus)
|
|
WidgetCenter.shared.reloadAllTimelines()
|
|
let session = manager.connection as? NETunnelProviderSession
|
|
try session?.startVPNTunnel()
|
|
}
|
|
} else {
|
|
let status = manager.connection.status
|
|
if status == .connected || status == .connecting {
|
|
defaults?.set(WidgetVPNStatus.disconnecting.rawValue, forKey: WidgetConstants.keyVPNStatus)
|
|
WidgetCenter.shared.reloadAllTimelines()
|
|
manager.connection.stopVPNTunnel()
|
|
}
|
|
}
|
|
|
|
await VPNIntentHelpers.waitForStableState(manager: manager)
|
|
return .result()
|
|
}
|
|
}
|