Files
ios-client/NetBirdWidgetExtension/Controls/NetBirdVPNControl.swift
evgeniyChepelevandZoltán Papp cd9863eeff Add VPN toggle to Control Center (iOS 18 Controls widget) (#120)
* Expose VPN connect/disconnect through the iOS 18 Controls interface using ControlWidget in the existing widget extension bundle. Reload the control whenever the app updates VPN state so the displayed status stays in sync with changes made outside the control.

* Fix controll state

* fix: enable VPN control from Control Center widget

Add packet-tunnel-provider entitlement to the widget extension so
NETunnelProviderManager can load and control the VPN tunnel from the
extension process. Without it, loadAllFromPreferences returned an
empty list, causing the control to always appear unconfigured and
ignore button presses.

Switch ControlValueProvider to read state from shared UserDefaults as
the primary source (matching VPNStatusProvider), falling back to live
NE status via the callback API. Replace SetValueIntent with AppIntent
to eliminate iOS value caching that broke the control after pre-login
presses. Use the callback-based NE API in the intent to avoid the
async throws variant hanging in the extension process.

* Update ToggleVPNControlIntent.swift

* Fix build error

* fix(iOS): read domain ResolvedIPs via collection getter

The merge of main bumped netbird-core to the structured ResolvedIPs
collection API (PR netbirdio/netbird#6090), but PacketTunnelProvider
still parsed domain.resolvedIPs as a comma-joined String, breaking the
build:

  value of type 'NetBirdSDKDomainInfo' has no member 'resolvedIPs'

Restore the getResolvedIPs()/size()/get() collection access (matching
PR #117 and the tvOS extension) so it matches the bumped core API.

* feat(iOS): add NetBird branding to Control Center VPN toggle

---------

Co-authored-by: Zoltán Papp <zoltan.pmail@gmail.com>
2026-06-03 15:12:30 +02:00

26 lines
737 B
Swift

import SwiftUI
import WidgetKit
@available(iOS 18.0, *)
struct NetBirdVPNControl: ControlWidget {
static let kind = "io.netbird.vpn.control"
var body: some ControlWidgetConfiguration {
StaticControlConfiguration(
kind: Self.kind,
provider: VPNControlProvider()
) { state in
ControlWidgetToggle(
isOn: state.isActive,
action: SetVPNStateIntent()
) {
Label("NetBird VPN", image: "netbird-logo")
}
.tint(Color(red: 0xF6/255, green: 0x83/255, blue: 0x30/255))
}
.displayName("NetBird VPN")
.description("Connect or disconnect NetBird VPN from Control Center.")
}
}