Skip to content

Add Lazy connection toggle to Advanced settings#171

Open
MichaelUray wants to merge 1 commit intonetbirdio:mainfrom
MichaelUray:feat/lazy-connection-toggle-upstream
Open

Add Lazy connection toggle to Advanced settings#171
MichaelUray wants to merge 1 commit intonetbirdio:mainfrom
MichaelUray:feat/lazy-connection-toggle-upstream

Conversation

@MichaelUray
Copy link
Copy Markdown

@MichaelUray MichaelUray commented Apr 25, 2026

Describe your changes

Adds a "Lazy connection" switch to the Advanced settings fragment (sits between Block inbound connections and Disable client routes). The toggle controls the engine's LazyConnectionEnabled setting via the gomobile Preferences bridge.

  • New layout_lazy_connection block in fragment_advanced.xml; the constraint chain is updated so layout_disable_client_routes is anchored below the new block.
  • New string resources advanced_lazy_connection / advanced_lazy_connection_desc.
  • AdvancedFragment.initializeEngineConfigSwitches() reads the current value via goPreferences.getLazyConnectionEnabled() and writes back via setLazyConnectionEnabled() + commit() on toggle, with a TV-remote layout click handler wired through layout_lazy_connection.toggle().

Default is off, so behavior on existing installs does not change until a user enables it explicitly.

Issue ticket number and link

N/A.

Checklist

  • Is it a bug fix
  • Is a typo/documentation fix
  • Is a feature enhancement
  • It is a refactor
  • Created tests that fail without the change (if possible) — N/A, UI passthrough.
  • Extended the README / documentation, if necessary

Dependency

This PR consumes two new bridge methods on the gomobile Preferences type:

  • GetLazyConnectionEnabled() (bool, error)
  • SetLazyConnectionEnabled(enabled bool)

Those are added in netbirdio/netbird#5994. This PR's submodule pointer is intentionally not bumped — it should land after #5994 merges, at which point a routine submodule update will pick up the new bridge symbols and this PR will compile.

Testing

Verified end-to-end on a Galaxy S21 (SM-G991B, Android 15) with a local build that includes the bridge change:

  • aapt2 dump resources confirms id/layout_lazy_connection, id/switch_lazy_connection, string/advanced_lazy_connection are baked into the APK.
  • dexdump confirms AdvancedFragment calls Preferences.{get,set}LazyConnectionEnabled.
  • After toggling the switch on and reconnecting, GoLog logcat confirms the engine activates the lazy-connection subsystem:
    • client/internal/lazyconn/manager/manager.go: setup lazy connection service
    • client/internal/lazyconn/inactivity/manager.go: inactivity threshold configured: 15m0s
    • client/internal/conn_mgr.go: peer added to lazy conn manager (per peer)
    • client/internal/lazyconn/activity/listener_udp.go: created activity listener: 127.0.0.1:NNNNN
    • On peer activity: removing activity listeneradding peer to inactivity manager
  • With the toggle off, the same logcat shows: client/internal/conn_mgr.go: lazy connection manager is disabled.

Summary by CodeRabbit

  • New Features
    • Introduced lazy connection setting in advanced settings, which defers per-peer connection establishment until first actual traffic occurs. The setting automatically persists and provides a user-friendly toggle control accessible through both touch and remote controls, optimizing network resource usage.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 25, 2026

Review Change Stack
No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 5f01c0bc-c311-4255-94e9-fa2045a6fdc6

📥 Commits

Reviewing files that changed from the base of the PR and between 77bc67f and 113c2b4.

📒 Files selected for processing (4)
  • app/src/main/java/io/netbird/client/ui/advanced/AdvancedFragment.java
  • app/src/main/res/layout/fragment_advanced.xml
  • app/src/main/res/values/strings.xml
  • netbird
✅ Files skipped from review due to trivial changes (1)
  • netbird
🚧 Files skipped from review as they are similar to previous changes (1)
  • app/src/main/res/layout/fragment_advanced.xml

📝 Walkthrough

Walkthrough

This PR adds a "lazy connection" toggle to the Advanced settings screen, enabling deferred per-peer connection setup until first traffic. It updates the layout, adds preference persistence wiring in the fragment, includes TV-remote interaction support, and bumps the netbird submodule.

Changes

Lazy Connection Advanced Setting

Layer / File(s) Summary
UI Strings
app/src/main/res/values/strings.xml
Adds advanced_lazy_connection and advanced_lazy_connection_desc string resources defining the label and description for the lazy connection feature.
Layout Definition
app/src/main/res/layout/fragment_advanced.xml
Introduces layout_lazy_connection container with switch_lazy_connection positioned after layout_block_inbound; reanchors layout_disable_client_routes below the new lazy connection layout.
Fragment Integration
app/src/main/java/io/netbird/client/ui/advanced/AdvancedFragment.java
Initializes switch from goPreferences.getLazyConnectionEnabled(); adds checked-change listener that persists updates via setLazyConnectionEnabled() and commit(); adds parent layout click handler for TV remote toggle support.
Dependencies
netbird
Updates netbird submodule commit reference.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

Possibly related PRs

Suggested reviewers

  • pappz
  • lixmal
  • mlsmaycon

Poem

🐰 A lazy hare hops in the Spring,
Deferring work 'til traffic's zing—
With switches flipped and preferences stored,
Remote control now fully poured!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 10.81% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely summarizes the main change: adding a lazy connection toggle to the Advanced settings UI.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Tip

💬 Introducing Slack Agent: The best way for teams to turn conversations into code.

Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.

  • Generate code and open pull requests
  • Plan features and break down work
  • Investigate incidents and troubleshoot customer tickets together
  • Automate recurring tasks and respond to alerts with triggers
  • Summarize progress and report instantly

Built for teams:

  • Shared memory across your entire org—no repeating context
  • Per-thread sandboxes to safely plan and execute work
  • Governance built-in—scoped access, auditability, and budget controls

One agent for your entire SDLC. Right inside Slack.

👉 Get started


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@app/src/main/java/io/netbird/client/ui/advanced/AdvancedFragment.java`:
- Around line 355-383: refreshConnectionModeAdapter contains hardcoded
user-visible strings ("currently", "engine not yet connected") and the
formatHint() text which must be localized; replace these inline literals with
string resources and use getString(...) with placeholders (e.g., a resource like
connection_mode_currently="%1$s (currently: %2$s)" and
connection_mode_engine_not_connected="%1$s (engine not yet connected)") when
building entries, and move the formatHint() literal into its own string resource
and call getString(R.string.<name>, ...) from the same methods
(refreshConnectionModeAdapter and the related block at lines ~428-433) so all UI
copy is loaded from resources and supports localization.
- Around line 437-448: The EditText blur handler in wireTimeoutEditOnBlur
currently clears the visible field but does not clear the persisted override;
when NumberFormatException occurs, call the provided LongConsumer onCommit with
a sentinel to clear the stored override (e.g. onCommit.accept(-1L)) before
returning so the engine stops using the old timeout override; update the catch
block in wireTimeoutEditOnBlur to invoke onCommit.accept(-1L) (or your project's
defined "clear" sentinel) after edit.setText("").

In `@app/src/main/res/layout/fragment_advanced.xml`:
- Around line 319-368: Remove the misleading autofillHints="postalCode" from the
timeout EditText fields (edit_relay_timeout, edit_p2p_timeout,
edit_p2p_retry_max) and disable autofill for these inputs by adding
android:importantForAutofill="no" (or clearing the autofillHints) so system
autofill services stop suggesting postal data for numeric timeout/retry
settings.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: a829a070-0cbe-475e-949c-646d9c072e2e

📥 Commits

Reviewing files that changed from the base of the PR and between 9ae32bc and 77bc67f.

📒 Files selected for processing (12)
  • app/src/main/java/io/netbird/client/MainActivity.java
  • app/src/main/java/io/netbird/client/ServiceAccessor.java
  • app/src/main/java/io/netbird/client/ui/advanced/AdvancedFragment.java
  • app/src/main/res/layout/fragment_advanced.xml
  • app/src/main/res/layout/spinner_item_themed.xml
  • app/src/main/res/values/connection_mode_array.xml
  • app/src/main/res/values/strings.xml
  • netbird
  • tool/src/main/java/io/netbird/client/tool/EngineRunner.java
  • tool/src/main/java/io/netbird/client/tool/EnvVarPackager.java
  • tool/src/main/java/io/netbird/client/tool/Preferences.java
  • tool/src/main/java/io/netbird/client/tool/VPNService.java
💤 Files with no reviewable changes (1)
  • tool/src/main/java/io/netbird/client/tool/Preferences.java
✅ Files skipped from review due to trivial changes (2)
  • app/src/main/res/layout/spinner_item_themed.xml
  • app/src/main/res/values/connection_mode_array.xml

Comment on lines +355 to +383
private void refreshConnectionModeAdapter() {
if (binding == null) return;
String[] base = getResources().getStringArray(R.array.connection_mode_entries);
String[] entries = base.clone();
String pushed = "";
try {
if (requireActivity() instanceof io.netbird.client.ServiceAccessor) {
pushed = ((io.netbird.client.ServiceAccessor) requireActivity())
.getServerPushedConnectionMode();
}
} catch (Throwable t) {
Log.d(LOGTAG, "no server-pushed mode available yet: " + t.getMessage());
}
if (pushed != null && !pushed.isEmpty()) {
entries[0] = base[0] + " (currently: " + pushed + ")";
} else {
entries[0] = base[0] + " (engine not yet connected)";
}
int currentSelection = binding.spinnerConnectionMode.getSelectedItemPosition();
ArrayAdapter<String> adapter = new ArrayAdapter<>(
requireContext(), R.layout.spinner_item_themed, entries);
adapter.setDropDownViewResource(R.layout.spinner_item_themed);
binding.spinnerConnectionMode.setAdapter(adapter);
if (currentSelection >= 0 && currentSelection < entries.length) {
binding.spinnerConnectionMode.setSelection(currentSelection);
}
// Server-pushed timeout values may have changed too; refresh hints.
refreshTimeoutHints();
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Move the new status/hint copy into string resources.

"currently", "engine not yet connected", and the formatHint() text are all hardcoded here, so the new connection-mode UI will not localize with the rest of the screen.

Also applies to: 428-433

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/src/main/java/io/netbird/client/ui/advanced/AdvancedFragment.java` around
lines 355 - 383, refreshConnectionModeAdapter contains hardcoded user-visible
strings ("currently", "engine not yet connected") and the formatHint() text
which must be localized; replace these inline literals with string resources and
use getString(...) with placeholders (e.g., a resource like
connection_mode_currently="%1$s (currently: %2$s)" and
connection_mode_engine_not_connected="%1$s (engine not yet connected)") when
building entries, and move the formatHint() literal into its own string resource
and call getString(R.string.<name>, ...) from the same methods
(refreshConnectionModeAdapter and the related block at lines ~428-433) so all UI
copy is loaded from resources and supports localization.

Comment on lines +437 to +448
private void wireTimeoutEditOnBlur(EditText edit, String label, LongConsumer onCommit) {
edit.setOnFocusChangeListener((view, hasFocus) -> {
if (hasFocus) return;
String s = edit.getText().toString().trim();
long val = 0;
if (!s.isEmpty()) {
try { val = Long.parseLong(s); }
catch (NumberFormatException nfe) {
Log.w(LOGTAG, "Invalid " + label + " timeout: " + s);
edit.setText("");
return;
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Clear the stored timeout override on invalid input.

Clearing the EditText and returning here leaves the previous persisted value intact. The field looks empty, but the engine still uses the old override until the user enters another valid value.

Suggested fix
             if (!s.isEmpty()) {
                 try { val = Long.parseLong(s); }
                 catch (NumberFormatException nfe) {
                     Log.w(LOGTAG, "Invalid " + label + " timeout: " + s);
                     edit.setText("");
+                    onCommit.accept(0);
                     return;
                 }
                 if (val < 0) val = 0;
             }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
private void wireTimeoutEditOnBlur(EditText edit, String label, LongConsumer onCommit) {
edit.setOnFocusChangeListener((view, hasFocus) -> {
if (hasFocus) return;
String s = edit.getText().toString().trim();
long val = 0;
if (!s.isEmpty()) {
try { val = Long.parseLong(s); }
catch (NumberFormatException nfe) {
Log.w(LOGTAG, "Invalid " + label + " timeout: " + s);
edit.setText("");
return;
}
private void wireTimeoutEditOnBlur(EditText edit, String label, LongConsumer onCommit) {
edit.setOnFocusChangeListener((view, hasFocus) -> {
if (hasFocus) return;
String s = edit.getText().toString().trim();
long val = 0;
if (!s.isEmpty()) {
try { val = Long.parseLong(s); }
catch (NumberFormatException nfe) {
Log.w(LOGTAG, "Invalid " + label + " timeout: " + s);
edit.setText("");
onCommit.accept(0);
return;
}
if (val < 0) val = 0;
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/src/main/java/io/netbird/client/ui/advanced/AdvancedFragment.java` around
lines 437 - 448, The EditText blur handler in wireTimeoutEditOnBlur currently
clears the visible field but does not clear the persisted override; when
NumberFormatException occurs, call the provided LongConsumer onCommit with a
sentinel to clear the stored override (e.g. onCommit.accept(-1L)) before
returning so the engine stops using the old timeout override; update the catch
block in wireTimeoutEditOnBlur to invoke onCommit.accept(-1L) (or your project's
defined "clear" sentinel) after edit.setText("").

Comment on lines +319 to +368
<EditText
android:id="@+id/edit_relay_timeout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:autofillHints="postalCode"
android:hint="@string/advanced_timeout_hint"
android:inputType="number"
android:maxLength="9"
android:textColor="@color/nb_txt_light"
android:textColorHint="@color/nb_txt_light" />

<TextView
android:id="@+id/label_p2p_timeout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:text="@string/advanced_p2p_timeout"
android:textColor="@color/nb_txt_light"
android:textSize="12sp" />

<EditText
android:id="@+id/edit_p2p_timeout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:autofillHints="postalCode"
android:hint="@string/advanced_timeout_hint"
android:inputType="number"
android:maxLength="9"
android:textColor="@color/nb_txt_light"
android:textColorHint="@color/nb_txt_light" />

<TextView
android:id="@+id/label_p2p_retry_max"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:text="@string/advanced_p2p_retry_max"
android:textColor="@color/nb_txt_light"
android:textSize="12sp" />

<EditText
android:id="@+id/edit_p2p_retry_max"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:autofillHints="postalCode"
android:hint="@string/advanced_timeout_hint"
android:inputType="number"
android:maxLength="9"
android:textColor="@color/nb_txt_light"
android:textColorHint="@color/nb_txt_light" />
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Disable autofill on these timeout fields instead of labeling them as postal codes.

Using postalCode here will make autofill services suggest ZIP/postal data for numeric engine settings. These inputs should either opt out of autofill or use no hint at all.

Suggested fix
-                        android:autofillHints="postalCode"
+                        android:importantForAutofill="no"
                         android:hint="@string/advanced_timeout_hint"
                         android:inputType="number"
                         android:maxLength="9"
                         android:textColor="@color/nb_txt_light"
                         android:textColorHint="@color/nb_txt_light" />
...
-                        android:autofillHints="postalCode"
+                        android:importantForAutofill="no"
                         android:hint="@string/advanced_timeout_hint"
                         android:inputType="number"
                         android:maxLength="9"
                         android:textColor="@color/nb_txt_light"
                         android:textColorHint="@color/nb_txt_light" />
...
-                        android:autofillHints="postalCode"
+                        android:importantForAutofill="no"
                         android:hint="@string/advanced_timeout_hint"
                         android:inputType="number"
                         android:maxLength="9"
                         android:textColor="@color/nb_txt_light"
                         android:textColorHint="@color/nb_txt_light" />
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<EditText
android:id="@+id/edit_relay_timeout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:autofillHints="postalCode"
android:hint="@string/advanced_timeout_hint"
android:inputType="number"
android:maxLength="9"
android:textColor="@color/nb_txt_light"
android:textColorHint="@color/nb_txt_light" />
<TextView
android:id="@+id/label_p2p_timeout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:text="@string/advanced_p2p_timeout"
android:textColor="@color/nb_txt_light"
android:textSize="12sp" />
<EditText
android:id="@+id/edit_p2p_timeout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:autofillHints="postalCode"
android:hint="@string/advanced_timeout_hint"
android:inputType="number"
android:maxLength="9"
android:textColor="@color/nb_txt_light"
android:textColorHint="@color/nb_txt_light" />
<TextView
android:id="@+id/label_p2p_retry_max"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:text="@string/advanced_p2p_retry_max"
android:textColor="@color/nb_txt_light"
android:textSize="12sp" />
<EditText
android:id="@+id/edit_p2p_retry_max"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:autofillHints="postalCode"
android:hint="@string/advanced_timeout_hint"
android:inputType="number"
android:maxLength="9"
android:textColor="@color/nb_txt_light"
android:textColorHint="@color/nb_txt_light" />
<EditText
android:id="@+id/edit_relay_timeout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:importantForAutofill="no"
android:hint="@string/advanced_timeout_hint"
android:inputType="number"
android:maxLength="9"
android:textColor="@color/nb_txt_light"
android:textColorHint="@color/nb_txt_light" />
<TextView
android:id="@+id/label_p2p_timeout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:text="@string/advanced_p2p_timeout"
android:textColor="@color/nb_txt_light"
android:textSize="12sp" />
<EditText
android:id="@+id/edit_p2p_timeout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:importantForAutofill="no"
android:hint="@string/advanced_timeout_hint"
android:inputType="number"
android:maxLength="9"
android:textColor="@color/nb_txt_light"
android:textColorHint="@color/nb_txt_light" />
<TextView
android:id="@+id/label_p2p_retry_max"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:text="@string/advanced_p2p_retry_max"
android:textColor="@color/nb_txt_light"
android:textSize="12sp" />
<EditText
android:id="@+id/edit_p2p_retry_max"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:importantForAutofill="no"
android:hint="@string/advanced_timeout_hint"
android:inputType="number"
android:maxLength="9"
android:textColor="@color/nb_txt_light"
android:textColorHint="@color/nb_txt_light" />
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/src/main/res/layout/fragment_advanced.xml` around lines 319 - 368, Remove
the misleading autofillHints="postalCode" from the timeout EditText fields
(edit_relay_timeout, edit_p2p_timeout, edit_p2p_retry_max) and disable autofill
for these inputs by adding android:importantForAutofill="no" (or clearing the
autofillHints) so system autofill services stop suggesting postal data for
numeric timeout/retry settings.

Adds a switch in the Advanced fragment that controls the
LazyConnectionEnabled engine setting. Default is OFF so existing
behavior is preserved; users opt in to per-peer connection on first
traffic for reduced background load.

The toggle wires through the new GetLazyConnectionEnabled /
SetLazyConnectionEnabled methods on the gomobile Preferences bridge.

Tested on a Galaxy S21 (Android 15): toggling the switch persists
LazyConnectionEnabled in the config; on reconnect the engine activates
the lazy connection manager (setup lazy connection service, per-peer
activity listeners on 127.0.0.1:N, 15-minute inactivity threshold) and
peers are wired up on demand instead of eagerly.
@MichaelUray MichaelUray force-pushed the feat/lazy-connection-toggle-upstream branch from 77bc67f to 113c2b4 Compare May 7, 2026 07:24
@MichaelUray
Copy link
Copy Markdown
Author

Rebased on upstream/main (now at v0.70.5 + #167 fix) and reduced to the original single-commit scope. Submodule pin bumped to c17355dc7 so this PR depends only on netbirdio/netbird#5994 (the LazyConnectionEnabled Preferences bridge).

The connection-mode picker UI + 3 timeouts that I had prototyped on top of this branch are no longer here — they belong to the broader Phase-3.7i Android UI work, which depends on the Go-side bridges that are still in review on the netbirdio/netbird#6081-#6084 stack. I'll open that as a separate android-client PR after the backend stack lands; opening it now would just sit red against current upstream/main.

Verified locally on Galaxy S21 (Android 15):

  • Build: ./gradlew assembleDebug clean (NDK 23.1.7779620, gomobile pinned to repo version, Java 21).
  • Install + toggle interaction: switch shows up in Advanced, can be toggled both directions, value persists across am force-stop + relaunch.
  • VPN: connect-button works after the change, tunnel comes up to 100.87.223.194/16, 19 of 29 Peers connected with Lazy enabled (on-demand wake working as designed).

So this should be ready for a maintainer pass once #5994 is in.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant