Skip to content
Open
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
19 changes: 17 additions & 2 deletions NetBird/Source/App/ViewModels/MainViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,8 @@ class ViewModel: ObservableObject {
}
}
@Published var forceRelayConnection = true
@Published var showForceRelayAlert = false
@Published var enableLazyConnection = true
@Published var showConfigChangeAlert = false
@Published var showRosenpassChangedAlert = false
@Published var networkUnavailable = false

Expand Down Expand Up @@ -130,6 +131,7 @@ class ViewModel: ObservableObject {

// forceRelayConnection uses UserDefaults (not SDK), so it's safe to load during init
self.forceRelayConnection = self.getForcedRelayConnectionEnabled()
self.enableLazyConnection = self.getLazyConnectionEnabled()

$setupKey
.removeDuplicates()
Expand Down Expand Up @@ -371,7 +373,7 @@ class ViewModel: ObservableObject {
let userDefaults = UserDefaults(suiteName: GlobalConstants.userPreferencesSuiteName)
userDefaults?.set(isEnabled, forKey: GlobalConstants.keyForceRelayConnection)
self.forceRelayConnection = isEnabled
self.showForceRelayAlert = true
self.showConfigChangeAlert = true
}

func getForcedRelayConnectionEnabled() -> Bool {
Expand All @@ -386,6 +388,19 @@ class ViewModel: ObservableObject {
#endif
}

func setEnableLazyConnection(isEnabled: Bool) {
let userDefaults = UserDefaults(suiteName: GlobalConstants.userPreferencesSuiteName)
userDefaults?.set(isEnabled, forKey: GlobalConstants.keyEnableLazyConnection)
self.enableLazyConnection = isEnabled
self.showConfigChangeAlert = true
}

func getLazyConnectionEnabled() -> Bool {
let userDefaults = UserDefaults(suiteName: GlobalConstants.userPreferencesSuiteName)
userDefaults?.register(defaults: [GlobalConstants.keyEnableLazyConnection: true])
return userDefaults?.bool(forKey: GlobalConstants.keyEnableLazyConnection) ?? true
Comment on lines +399 to +401
Copy link

Copilot AI Feb 16, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The getLazyConnectionEnabled function should follow the same pattern as getForcedRelayConnectionEnabled by including platform-specific defaults using #if os(iOS) guards. According to the PR description, lazy connection is for the iOS peer, suggesting it may need different defaults on tvOS similar to how forceRelayConnection has platform-specific handling.

Suggested change
let userDefaults = UserDefaults(suiteName: GlobalConstants.userPreferencesSuiteName)
userDefaults?.register(defaults: [GlobalConstants.keyEnableLazyConnection: true])
return userDefaults?.bool(forKey: GlobalConstants.keyEnableLazyConnection) ?? true
let userDefaults = UserDefaults(suiteName: GlobalConstants.userPreferencesSuiteName)
#if os(iOS)
userDefaults?.register(defaults: [GlobalConstants.keyEnableLazyConnection: true])
return userDefaults?.bool(forKey: GlobalConstants.keyEnableLazyConnection) ?? true
#else
// lazy connection is for the iOS peer; disable by default on Apple TV
userDefaults?.register(defaults: [GlobalConstants.keyEnableLazyConnection: false])
return userDefaults?.bool(forKey: GlobalConstants.keyEnableLazyConnection) ?? false
#endif

Copilot uses AI. Check for mistakes.
}

func getDefaultStatus() -> StatusDetails {
return StatusDetails(ip: "", fqdn: "", managementStatus: .disconnected, peerInfo: [])
}
Expand Down
24 changes: 19 additions & 5 deletions NetBird/Source/App/Views/AdvancedView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,20 @@ struct AdvancedView: View {
viewModel.setForcedRelayConnection(isEnabled: value)
}

Toggle(isOn: $viewModel.enableLazyConnection) {
Text("Enable lazy connection")
.multilineTextAlignment(.leading)
.font(.system(size: 18, weight: .regular))
.foregroundColor(Color("TextSecondary"))
.padding(.top, 3)
.fixedSize(horizontal: false, vertical: true)
}
.toggleStyle(SwitchToggleStyle(tint: .orange))
.padding(.top, 10)
.onChange(of: viewModel.enableLazyConnection) { value in
viewModel.setEnableLazyConnection(isEnabled: value)
}

Spacer()
}
.padding([.leading, .trailing], UIScreen.main.bounds.width * 0.10)
Expand All @@ -144,10 +158,10 @@ struct AdvancedView: View {
LogLevelAlert()
}

alertOverlay(isPresented: viewModel.showForceRelayAlert, onDismiss: {
viewModel.showForceRelayAlert = false
alertOverlay(isPresented: viewModel.showConfigChangeAlert, onDismiss: {
viewModel.showConfigChangeAlert = false
}) {
ForceRelayAlert()
ConfigChangeAlert()
}
}
.onAppear {
Expand Down Expand Up @@ -293,7 +307,7 @@ struct AdvancedView: View {
}
}

struct ForceRelayAlert: View {
struct ConfigChangeAlert: View {
@EnvironmentObject var viewModel: ViewModel

var body: some View {
Expand All @@ -308,7 +322,7 @@ struct ForceRelayAlert: View {
HStack {
Spacer()
Button(action: {
viewModel.showForceRelayAlert = false
viewModel.showConfigChangeAlert = false
}) {
Text("OK")
.padding()
Expand Down
4 changes: 4 additions & 0 deletions NetBirdTests/GlobalConstantsTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ final class GlobalConstantsTests: XCTestCase {
XCTAssertEqual(GlobalConstants.keyForceRelayConnection, "isConnectionForceRelayed")
}

func testEnableLazyConnectionKey() {
XCTAssertEqual(GlobalConstants.keyEnableLazyConnection, "isLazyConnectionEnabled")
}

func testLoginRequiredKey() {
XCTAssertEqual(GlobalConstants.keyLoginRequired, "netbird.loginRequired")
}
Expand Down
9 changes: 9 additions & 0 deletions NetBirdTests/SharedUserDefaultsTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ final class SharedUserDefaultsTests: XCTestCase {
override func tearDown() {
userDefaults?.removeObject(forKey: GlobalConstants.keyLoginRequired)
userDefaults?.removeObject(forKey: GlobalConstants.keyForceRelayConnection)
userDefaults?.removeObject(forKey: GlobalConstants.keyEnableLazyConnection)
super.tearDown()
}

Expand Down Expand Up @@ -58,4 +59,12 @@ final class SharedUserDefaultsTests: XCTestCase {
let value = defaults.bool(forKey: GlobalConstants.keyForceRelayConnection)
XCTAssertTrue(value, "Force relay connection should default to true")
}

func testEnableLazyConnectionDefaultsToTrue() throws {
let defaults = try XCTUnwrap(userDefaults)
defaults.removeObject(forKey: GlobalConstants.keyEnableLazyConnection)
defaults.register(defaults: [GlobalConstants.keyEnableLazyConnection: true])
let value = defaults.bool(forKey: GlobalConstants.keyEnableLazyConnection)
XCTAssertTrue(value, "Enable lazy connection should default to true")
}
}
8 changes: 7 additions & 1 deletion NetbirdKit/EnvVarPackager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,14 @@ class EnvVarPackager {
defaults.register(defaults: [GlobalConstants.keyForceRelayConnection: defaultForceRelay])
let forceRelayConnection = defaults.bool(forKey: GlobalConstants.keyForceRelayConnection)

let defaultLazyConnection = true
defaults.register(defaults: [GlobalConstants.keyEnableLazyConnection: defaultLazyConnection])
let isLazyConnectionEnabled = defaults.bool(forKey: GlobalConstants.keyEnableLazyConnection)

envList.put(NetBirdSDKGetEnvKeyNBForceRelay(), value: String(forceRelayConnection))

envList.put(NetBirdSDKGetEnvKeyNBLazyConn(), value: String(isLazyConnectionEnabled))
envList.put(NetBirdSDKGetEnvKeyNBInactivityThreshold(), value: String(5))
Copy link

Copilot AI Feb 16, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The hardcoded inactivity threshold value of 5 should be extracted to a named constant in GlobalConstants.swift for better maintainability. This would follow the established pattern seen with other configuration values in the codebase and make it easier to adjust this value in the future without searching through the code.

Copilot uses AI. Check for mistakes.

return envList
}
}
2 changes: 2 additions & 0 deletions NetbirdKit/GlobalConstants.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ struct GlobalConstants {
#endif

static let keyForceRelayConnection = "isConnectionForceRelayed"
static let keyEnableLazyConnection = "isLazyConnectionEnabled"

static let keyLoginRequired = "netbird.loginRequired"
static let keyNetworkUnavailable = "netbird.networkUnavailable"

Expand Down
Loading