From 9ae32bc56b02f7141b5f0de7dabf16cf81f54263 Mon Sep 17 00:00:00 2001 From: Michael Uray <25169478+MichaelUray@users.noreply.github.com> Date: Sat, 25 Apr 2026 22:30:37 +0000 Subject: [PATCH 1/3] Add Lazy connection toggle to Advanced 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. --- .../client/ui/advanced/AdvancedFragment.java | 18 ++++++- app/src/main/res/layout/fragment_advanced.xml | 51 ++++++++++++++++++- app/src/main/res/values/strings.xml | 2 + 3 files changed, 68 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/io/netbird/client/ui/advanced/AdvancedFragment.java b/app/src/main/java/io/netbird/client/ui/advanced/AdvancedFragment.java index 3f1e2a7c..ba968d38 100644 --- a/app/src/main/java/io/netbird/client/ui/advanced/AdvancedFragment.java +++ b/app/src/main/java/io/netbird/client/ui/advanced/AdvancedFragment.java @@ -197,6 +197,7 @@ private void initializeEngineConfigSwitches() { binding.switchDisableFirewall.setChecked(goPreferences.getDisableFirewall()); binding.switchAllowSsh.setChecked(goPreferences.getServerSSHAllowed()); binding.switchBlockInbound.setChecked(goPreferences.getBlockInbound()); + binding.switchLazyConnection.setChecked(goPreferences.getLazyConnectionEnabled()); // Set up change listeners binding.switchDisableClientRoutes.setOnCheckedChangeListener((buttonView, isChecked) -> { @@ -252,15 +253,28 @@ private void initializeEngineConfigSwitches() { Log.e(LOGTAG, "Failed to set block inbound", e); } }); - + + binding.switchLazyConnection.setOnCheckedChangeListener((buttonView, isChecked) -> { + try { + goPreferences.setLazyConnectionEnabled(isChecked); + goPreferences.commit(); + } catch (Exception e) { + Log.e(LOGTAG, "Failed to set lazy connection", e); + } + }); + // Make parent layouts clickable to toggle switches (for TV remote) binding.layoutAllowSsh.setOnClickListener(v -> { binding.switchAllowSsh.toggle(); }); - + binding.layoutBlockInbound.setOnClickListener(v -> { binding.switchBlockInbound.toggle(); }); + + binding.layoutLazyConnection.setOnClickListener(v -> { + binding.switchLazyConnection.toggle(); + }); binding.layoutDisableClientRoutes.setOnClickListener(v -> { binding.switchDisableClientRoutes.toggle(); diff --git a/app/src/main/res/layout/fragment_advanced.xml b/app/src/main/res/layout/fragment_advanced.xml index ad46aea4..082f918e 100644 --- a/app/src/main/res/layout/fragment_advanced.xml +++ b/app/src/main/res/layout/fragment_advanced.xml @@ -268,7 +268,7 @@ + + + + + + + + + + + + + + Allows SSH connections to this device Block inbound connections Blocks all inbound connections to this device and routed networks. This overrides any policies received from the management service + Lazy connection + Defer per-peer connection setup until first actual traffic. Reduces background load but adds latency to the first packet to a peer NetBird logo From 4f2c2f881669fb8967c32f5b5f5047308b0eae14 Mon Sep 17 00:00:00 2001 From: Michael Uray <25169478+MichaelUray@users.noreply.github.com> Date: Sat, 2 May 2026 14:30:59 +0000 Subject: [PATCH 2/3] ui/advanced: replace Lazy switch with Connection-Mode picker + 3 timeouts Phase 3.7h Android counterpart of the Fyne Network-tab UI: - Spinner: Follow server / relay-forced / p2p / p2p-lazy / p2p-dynamic - 3 EditTexts (Relay/P2P/P2P-RetryMax timeout) shown per-mode appropriately - Themed spinner item layout (fixes white-on-white in dark mode) - "currently: " suffix on Follow-server entry shows server-pushed value - Per-field hint shows actual server-default seconds - ServerPushed* values via ServiceAccessor -> EngineRunner -> connMgr Bumps netbird submodule to include the new server-pushed RPC fields and ConnMgr.ServerPushed* getters. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../java/io/netbird/client/MainActivity.java | 26 +++ .../io/netbird/client/ServiceAccessor.java | 27 +++ .../client/ui/advanced/AdvancedFragment.java | 219 ++++++++++++++++-- app/src/main/res/layout/fragment_advanced.xml | 107 ++++++--- .../main/res/layout/spinner_item_themed.xml | 7 + .../main/res/values/connection_mode_array.xml | 13 ++ app/src/main/res/values/strings.xml | 6 + netbird | 2 +- .../io/netbird/client/tool/EngineRunner.java | 24 ++ .../io/netbird/client/tool/VPNService.java | 16 ++ 10 files changed, 406 insertions(+), 41 deletions(-) create mode 100644 app/src/main/res/layout/spinner_item_themed.xml create mode 100644 app/src/main/res/values/connection_mode_array.xml diff --git a/app/src/main/java/io/netbird/client/MainActivity.java b/app/src/main/java/io/netbird/client/MainActivity.java index c7fb0b54..7f15bfaa 100644 --- a/app/src/main/java/io/netbird/client/MainActivity.java +++ b/app/src/main/java/io/netbird/client/MainActivity.java @@ -421,6 +421,32 @@ public String debugBundle(boolean anonymize) throws Exception { return mBinder.debugBundle(anonymize); } + @Override + public String getServerPushedConnectionMode() { + if (mBinder == null) { + return ""; + } + return mBinder.getServerPushedConnectionMode(); + } + + @Override + public long getServerPushedRelayTimeoutSecs() { + if (mBinder == null) return 0; + return mBinder.getServerPushedRelayTimeoutSecs(); + } + + @Override + public long getServerPushedP2pTimeoutSecs() { + if (mBinder == null) return 0; + return mBinder.getServerPushedP2pTimeoutSecs(); + } + + @Override + public long getServerPushedP2pRetryMaxSecs() { + if (mBinder == null) return 0; + return mBinder.getServerPushedP2pRetryMaxSecs(); + } + @Override public void addRouteChangeListener(RouteChangeListener listener) { if (mBinder == null) { diff --git a/app/src/main/java/io/netbird/client/ServiceAccessor.java b/app/src/main/java/io/netbird/client/ServiceAccessor.java index d37d399c..f4126884 100644 --- a/app/src/main/java/io/netbird/client/ServiceAccessor.java +++ b/app/src/main/java/io/netbird/client/ServiceAccessor.java @@ -19,4 +19,31 @@ public interface ServiceAccessor { void removeRouteChangeListener(RouteChangeListener listener); String debugBundle(boolean anonymize) throws Exception; + + /** + * Returns the canonical name (e.g. "p2p-dynamic") of the connection + * mode the management server most recently pushed. Empty string when + * the engine has not connected yet or no value has been pushed -- + * the UI should then hide the "(currently: ...)" suffix on the + * Follow-server entry of the override dropdown. + */ + String getServerPushedConnectionMode(); + + /** + * Returns the relay timeout (seconds) the management server most + * recently pushed. 0 when not yet known. Used as a hint in the + * override field so the user can see the value they are about to + * override. + */ + long getServerPushedRelayTimeoutSecs(); + + /** + * Returns the p2p (ICE-only) timeout in seconds most recently pushed. + */ + long getServerPushedP2pTimeoutSecs(); + + /** + * Returns the p2p retry-max cap in seconds most recently pushed. + */ + long getServerPushedP2pRetryMaxSecs(); } \ No newline at end of file diff --git a/app/src/main/java/io/netbird/client/ui/advanced/AdvancedFragment.java b/app/src/main/java/io/netbird/client/ui/advanced/AdvancedFragment.java index ba968d38..9233ab9d 100644 --- a/app/src/main/java/io/netbird/client/ui/advanced/AdvancedFragment.java +++ b/app/src/main/java/io/netbird/client/ui/advanced/AdvancedFragment.java @@ -3,10 +3,15 @@ import android.content.Context; import android.content.SharedPreferences; import android.os.Bundle; +import android.text.Editable; +import android.text.TextWatcher; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; +import android.widget.AdapterView; +import android.widget.ArrayAdapter; +import android.widget.EditText; import android.widget.RadioGroup; import android.widget.TextView; import android.widget.Toast; @@ -197,7 +202,12 @@ private void initializeEngineConfigSwitches() { binding.switchDisableFirewall.setChecked(goPreferences.getDisableFirewall()); binding.switchAllowSsh.setChecked(goPreferences.getServerSSHAllowed()); binding.switchBlockInbound.setChecked(goPreferences.getBlockInbound()); - binding.switchLazyConnection.setChecked(goPreferences.getLazyConnectionEnabled()); + + // Connection mode + timeouts (Phase 3.7h Android UI). Default + // selection is "Follow server" (index 0 in connection_mode_entries), + // which clears any local override. Selecting an explicit mode + // unhides the timeout fields below. + initializeConnectionModeUI(); // Set up change listeners binding.switchDisableClientRoutes.setOnCheckedChangeListener((buttonView, isChecked) -> { @@ -254,15 +264,6 @@ private void initializeEngineConfigSwitches() { } }); - binding.switchLazyConnection.setOnCheckedChangeListener((buttonView, isChecked) -> { - try { - goPreferences.setLazyConnectionEnabled(isChecked); - goPreferences.commit(); - } catch (Exception e) { - Log.e(LOGTAG, "Failed to set lazy connection", e); - } - }); - // Make parent layouts clickable to toggle switches (for TV remote) binding.layoutAllowSsh.setOnClickListener(v -> { binding.switchAllowSsh.toggle(); @@ -271,10 +272,6 @@ private void initializeEngineConfigSwitches() { binding.layoutBlockInbound.setOnClickListener(v -> { binding.switchBlockInbound.toggle(); }); - - binding.layoutLazyConnection.setOnClickListener(v -> { - binding.switchLazyConnection.toggle(); - }); binding.layoutDisableClientRoutes.setOnClickListener(v -> { binding.switchDisableClientRoutes.toggle(); @@ -297,6 +294,200 @@ private void initializeEngineConfigSwitches() { } } + /** + * Mapping from spinner position to canonical connection-mode string. + * Index 0 = "Follow server" -> empty string clears the local override + * so the daemon uses the server-pushed value. Other entries set an + * explicit local override that wins over the server value. + * + * Order matches connection_mode_entries (res/values/connection_mode_array.xml): + * Follow server, relay-forced, p2p, p2p-lazy, p2p-dynamic. + */ + private static final String[] CONNECTION_MODE_VALUES = new String[] { + "", // 0: Follow server + "relay-forced", // 1 + "p2p", // 2 + "p2p-lazy", // 3 + "p2p-dynamic" // 4 + }; + + private void initializeConnectionModeUI() { + try { + // Build a theme-aware adapter so the dropdown uses our nb_txt color + // and the popup picks up nb_bg in dark mode. + // The "Follow server" entry gets a "(currently: )" suffix + // that surfaces the value the management server most recently + // pushed -- refreshed on every spinner-touch in case the engine + // was not connected yet when the fragment first opened. + refreshConnectionModeAdapter(); + + // Hydrate spinner from current persisted local override. + String currentMode = goPreferences.getConnectionMode(); + int selectedIdx = 0; + for (int i = 0; i < CONNECTION_MODE_VALUES.length; i++) { + if (CONNECTION_MODE_VALUES[i].equals(currentMode)) { + selectedIdx = i; + break; + } + } + binding.spinnerConnectionMode.setSelection(selectedIdx); + updateTimeoutsVisibility(selectedIdx); + + // Hydrate timeout fields with the locally-stored override (if any). + // Empty when no override is set so the user sees the field is + // currently inactive; the hint text shows the server-pushed + // default for that field as guidance. + long relay = goPreferences.getRelayTimeoutSeconds(); + long p2p = goPreferences.getP2pTimeoutSeconds(); + long retry = goPreferences.getP2pRetryMaxSeconds(); + binding.editRelayTimeout.setText(relay == 0 ? "" : String.valueOf(relay)); + binding.editP2pTimeout.setText(p2p == 0 ? "" : String.valueOf(p2p)); + binding.editP2pRetryMax.setText(retry == 0 ? "" : String.valueOf(retry)); + + // Refresh the "(currently: ...)" suffix every time the spinner is + // touched. Cheap (just a getter call to the engine), and covers + // the case where the user opens this fragment before the daemon + // received its first PeerConfig. + binding.spinnerConnectionMode.setOnTouchListener((v, event) -> { + if (event.getActionMasked() == android.view.MotionEvent.ACTION_DOWN) { + refreshConnectionModeAdapter(); + } + return false; + }); + + binding.spinnerConnectionMode.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { + @Override + public void onItemSelected(AdapterView parent, View view, int position, long id) { + try { + goPreferences.setConnectionMode(CONNECTION_MODE_VALUES[position]); + goPreferences.commit(); + } catch (Exception e) { + Log.e(LOGTAG, "Failed to set connection mode", e); + } + updateTimeoutsVisibility(position); + } + + @Override + public void onNothingSelected(AdapterView parent) { } + }); + + wireTimeoutEditOnBlur(binding.editRelayTimeout, "relay", v -> { + try { goPreferences.setRelayTimeoutSeconds(v); goPreferences.commit(); } + catch (Exception e) { Log.e(LOGTAG, "Failed to set relay timeout", e); } + }); + wireTimeoutEditOnBlur(binding.editP2pTimeout, "p2p", v -> { + try { goPreferences.setP2pTimeoutSeconds(v); goPreferences.commit(); } + catch (Exception e) { Log.e(LOGTAG, "Failed to set p2p timeout", e); } + }); + wireTimeoutEditOnBlur(binding.editP2pRetryMax, "p2pRetryMax", v -> { + try { goPreferences.setP2pRetryMaxSeconds(v); goPreferences.commit(); } + catch (Exception e) { Log.e(LOGTAG, "Failed to set p2p retry max", e); } + }); + } catch (Exception e) { + Log.e(LOGTAG, "Failed to initialize connection mode UI", e); + } + } + + 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 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(); + } + + private void updateTimeoutsVisibility(int spinnerPosition) { + // Inactivity timeouts only apply when the lazy/dynamic connection + // manager is active. Mapping (CONNECTION_MODE_VALUES indices): + // 0 follow-server : hide all (server may push any mode; default off) + // 1 relay-forced : hide all (relay tunnel always up, no teardown) + // 2 p2p : hide all (no inactivity manager runs) + // 3 p2p-lazy : show relay_timeout (whole-peer teardown) + // 4 p2p-dynamic : show all three (ICE-only + relay + retry-cap) + boolean lazyActive = (spinnerPosition == 3 || spinnerPosition == 4); + boolean dynamicActive = (spinnerPosition == 4); + + binding.layoutTimeoutsContainer.setVisibility(lazyActive ? View.VISIBLE : View.GONE); + if (!lazyActive) return; + + // relay timeout shown for both p2p-lazy and p2p-dynamic. + binding.labelP2pTimeout.setVisibility(dynamicActive ? View.VISIBLE : View.GONE); + binding.editP2pTimeout.setVisibility(dynamicActive ? View.VISIBLE : View.GONE); + binding.labelP2pRetryMax.setVisibility(dynamicActive ? View.VISIBLE : View.GONE); + binding.editP2pRetryMax.setVisibility(dynamicActive ? View.VISIBLE : View.GONE); + + // Refresh hint text from the latest server-pushed values so users + // see what they would inherit if they leave a field blank. + refreshTimeoutHints(); + } + + private void refreshTimeoutHints() { + long relayServer = 0, p2pServer = 0, retryServer = 0; + try { + if (requireActivity() instanceof io.netbird.client.ServiceAccessor) { + io.netbird.client.ServiceAccessor sa = + (io.netbird.client.ServiceAccessor) requireActivity(); + relayServer = sa.getServerPushedRelayTimeoutSecs(); + p2pServer = sa.getServerPushedP2pTimeoutSecs(); + retryServer = sa.getServerPushedP2pRetryMaxSecs(); + } + } catch (Throwable t) { + Log.d(LOGTAG, "server-pushed timeouts unavailable: " + t.getMessage()); + } + binding.editRelayTimeout.setHint(formatHint(relayServer)); + binding.editP2pTimeout.setHint(formatHint(p2pServer)); + binding.editP2pRetryMax.setHint(formatHint(retryServer)); + } + + private static String formatHint(long secs) { + if (secs <= 0) { + return "use server default"; + } + return "use server default (" + secs + "s)"; + } + + private interface LongConsumer { void accept(long v); } + + 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; + } + if (val < 0) val = 0; + } + onCommit.accept(val); + }); + } + @Override public void onDestroyView() { super.onDestroyView(); diff --git a/app/src/main/res/layout/fragment_advanced.xml b/app/src/main/res/layout/fragment_advanced.xml index 082f918e..4d552907 100644 --- a/app/src/main/res/layout/fragment_advanced.xml +++ b/app/src/main/res/layout/fragment_advanced.xml @@ -268,52 +268,107 @@ - - - + android:text="@string/advanced_connection_mode" + android:textColor="@color/nb_txt_light" /> - - - + + + + + + + + + + + + + + + + + + app:layout_constraintTop_toBottomOf="@id/layout_connection_mode"> + diff --git a/app/src/main/res/values/connection_mode_array.xml b/app/src/main/res/values/connection_mode_array.xml new file mode 100644 index 00000000..abb7fafd --- /dev/null +++ b/app/src/main/res/values/connection_mode_array.xml @@ -0,0 +1,13 @@ + + + + + Follow server + relay-forced + p2p + p2p-lazy + p2p-dynamic + + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 9db4f747..a5781028 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -98,6 +98,12 @@ Blocks all inbound connections to this device and routed networks. This overrides any policies received from the management service Lazy connection Defer per-peer connection setup until first actual traffic. Reduces background load but adds latency to the first packet to a peer + Connection mode + Override the connection mode pushed by the server. Leave on \"Follow server\" to use the server-configured value. Other modes activate the timeout fields below. + Relay timeout (seconds; leave empty to use server default) + P2P (ICE) timeout (seconds; leave empty to use server default) + P2P retry-max cap (seconds; leave empty to use server default) + use server default NetBird logo diff --git a/netbird b/netbird index 5a89e662..83f8f01a 160000 --- a/netbird +++ b/netbird @@ -1 +1 @@ -Subproject commit 5a89e6621bf41cb6cb0da3040ffe68ae790e3c02 +Subproject commit 83f8f01ad8841441ef86f0cbb27eb11319bb928a diff --git a/tool/src/main/java/io/netbird/client/tool/EngineRunner.java b/tool/src/main/java/io/netbird/client/tool/EngineRunner.java index dfdbf846..68940849 100644 --- a/tool/src/main/java/io/netbird/client/tool/EngineRunner.java +++ b/tool/src/main/java/io/netbird/client/tool/EngineRunner.java @@ -214,6 +214,30 @@ public void renewTUN(int fd) { } } + public String getServerPushedConnectionMode() { + try { + return goClient.getServerPushedConnectionMode(); + } catch (Throwable t) { + android.util.Log.d(LOGTAG, "getServerPushedConnectionMode unavailable: " + t.getMessage()); + return ""; + } + } + + public long getServerPushedRelayTimeoutSecs() { + try { return goClient.getServerPushedRelayTimeoutSecs(); } + catch (Throwable t) { return 0; } + } + + public long getServerPushedP2pTimeoutSecs() { + try { return goClient.getServerPushedP2pTimeoutSecs(); } + catch (Throwable t) { return 0; } + } + + public long getServerPushedP2pRetryMaxSecs() { + try { return goClient.getServerPushedP2pRetryMaxSecs(); } + catch (Throwable t) { return 0; } + } + public String debugBundle(boolean anonymize) throws Exception { String configPath = profileManager.getActiveConfigPath(); String statePath = profileManager.getActiveStateFilePath(); diff --git a/tool/src/main/java/io/netbird/client/tool/VPNService.java b/tool/src/main/java/io/netbird/client/tool/VPNService.java index 8494d48d..af9077db 100644 --- a/tool/src/main/java/io/netbird/client/tool/VPNService.java +++ b/tool/src/main/java/io/netbird/client/tool/VPNService.java @@ -243,6 +243,22 @@ public String debugBundle(boolean anonymize) throws Exception { return engineRunner.debugBundle(anonymize); } + public String getServerPushedConnectionMode() { + return engineRunner.getServerPushedConnectionMode(); + } + + public long getServerPushedRelayTimeoutSecs() { + return engineRunner.getServerPushedRelayTimeoutSecs(); + } + + public long getServerPushedP2pTimeoutSecs() { + return engineRunner.getServerPushedP2pTimeoutSecs(); + } + + public long getServerPushedP2pRetryMaxSecs() { + return engineRunner.getServerPushedP2pRetryMaxSecs(); + } + public void selectRoute(String route) throws Exception { engineRunner.selectRoute(route); } From 77bc67fd73d334d25636972456c104cd10390f0f Mon Sep 17 00:00:00 2001 From: Michael Uray <25169478+MichaelUray@users.noreply.github.com> Date: Sun, 3 May 2026 10:09:48 +0000 Subject: [PATCH 3/3] android: remove Force-Relay switch (replaced by Connection-Mode picker) Phase 3.7h finalisation. The standalone "Force relay connection" toggle in Advanced Settings is removed because the new Connection-Mode picker (landed earlier on this branch) supersedes it. Preferences key and EnvVarPackager NB_FORCE_RELAY plumbing are removed too so the setting no longer leaks into NetBird via env vars. Bumps netbird submodule to include the matching ServerPushed-getter commits from the netbird repo. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../client/ui/advanced/AdvancedFragment.java | 36 ------------------- app/src/main/res/layout/fragment_advanced.xml | 13 +------ app/src/main/res/values/strings.xml | 2 -- netbird | 2 +- .../netbird/client/tool/EnvVarPackager.java | 7 +--- .../io/netbird/client/tool/Preferences.java | 14 -------- 6 files changed, 3 insertions(+), 71 deletions(-) diff --git a/app/src/main/java/io/netbird/client/ui/advanced/AdvancedFragment.java b/app/src/main/java/io/netbird/client/ui/advanced/AdvancedFragment.java index 9233ab9d..6593899e 100644 --- a/app/src/main/java/io/netbird/client/ui/advanced/AdvancedFragment.java +++ b/app/src/main/java/io/netbird/client/ui/advanced/AdvancedFragment.java @@ -17,12 +17,10 @@ import android.widget.Toast; import androidx.annotation.NonNull; -import androidx.appcompat.app.AlertDialog; import androidx.appcompat.app.AppCompatDelegate; import androidx.fragment.app.Fragment; import io.netbird.client.R; -import io.netbird.client.databinding.ComponentSwitchBinding; import io.netbird.client.databinding.FragmentAdvancedBinding; import io.netbird.client.tool.Preferences; import io.netbird.client.tool.ProfileManagerWrapper; @@ -36,38 +34,6 @@ public class AdvancedFragment extends Fragment { private FragmentAdvancedBinding binding; private io.netbird.gomobile.android.Preferences goPreferences; - private void showReconnectionNeededWarningDialog() { - final View dialogView = getLayoutInflater().inflate(R.layout.dialog_simple_alert_message, null); - final AlertDialog alertDialog = new AlertDialog.Builder(requireContext(), R.style.AlertDialogTheme) - .setView(dialogView) - .create(); - - ((TextView)dialogView.findViewById(R.id.txt_dialog)).setText(R.string.reconnectionNeededWarningMessage); - dialogView.findViewById(R.id.btn_ok_dialog).setOnClickListener(v -> alertDialog.dismiss()); - alertDialog.show(); - } - - private void configureForceRelayConnectionSwitch(@NonNull ComponentSwitchBinding binding, @NonNull Preferences preferences) { - binding.switchTitle.setText(R.string.advanced_force_relay_conn); - binding.switchDescription.setText(R.string.advanced_force_relay_conn_desc); - - binding.switchControl.setChecked(preferences.isConnectionForceRelayed()); - binding.switchControl.setOnCheckedChangeListener((buttonView, isChecked) -> { - if (isChecked) { - preferences.enableForcedRelayConnection(); - } else { - preferences.disableForcedRelayConnection(); - } - - showReconnectionNeededWarningDialog(); - }); - - // Make parent layout clickable to toggle switch (for TV remote) - binding.getRoot().setOnClickListener(v -> { - binding.switchControl.toggle(); - }); - } - public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { @@ -163,8 +129,6 @@ public View onCreateView(@NonNull LayoutInflater inflater, binding.switchRosenpassPermissive.toggle(); }); - configureForceRelayConnectionSwitch(binding.layoutForceRelayConnection, preferences); - // Initialize engine config switches (your settings) initializeEngineConfigSwitches(); diff --git a/app/src/main/res/layout/fragment_advanced.xml b/app/src/main/res/layout/fragment_advanced.xml index 4d552907..7d3b507a 100644 --- a/app/src/main/res/layout/fragment_advanced.xml +++ b/app/src/main/res/layout/fragment_advanced.xml @@ -567,17 +567,6 @@ - - + app:layout_constraintTop_toBottomOf="@id/layout_disable_firewall"> Dark Light Choose the app appearance mode. - Force relay connection - Forces usage of relay when connecting to peers exclamation mark To apply the setting, you will need to reconnect. Using setup keys for user devices is not recommended. SSO with MFA provides stronger security, proper user-device association, and periodic re-authentication. diff --git a/netbird b/netbird index 83f8f01a..c90d008b 160000 --- a/netbird +++ b/netbird @@ -1 +1 @@ -Subproject commit 83f8f01ad8841441ef86f0cbb27eb11319bb928a +Subproject commit c90d008ba7514f1cfe9cd769fcaf8065e025ea73 diff --git a/tool/src/main/java/io/netbird/client/tool/EnvVarPackager.java b/tool/src/main/java/io/netbird/client/tool/EnvVarPackager.java index f6413e99..3ba7cb2a 100644 --- a/tool/src/main/java/io/netbird/client/tool/EnvVarPackager.java +++ b/tool/src/main/java/io/netbird/client/tool/EnvVarPackager.java @@ -1,14 +1,9 @@ package io.netbird.client.tool; -import io.netbird.gomobile.android.Android; import io.netbird.gomobile.android.EnvList; public class EnvVarPackager { public static EnvList getEnvironmentVariables(Preferences preferences) { - var envList = new EnvList(); - - envList.put(Android.getEnvKeyNBForceRelay(), String.valueOf(preferences.isConnectionForceRelayed())); - - return envList; + return new EnvList(); } } diff --git a/tool/src/main/java/io/netbird/client/tool/Preferences.java b/tool/src/main/java/io/netbird/client/tool/Preferences.java index ddf57ca5..5de30663 100644 --- a/tool/src/main/java/io/netbird/client/tool/Preferences.java +++ b/tool/src/main/java/io/netbird/client/tool/Preferences.java @@ -7,8 +7,6 @@ public class Preferences { private final String keyTraceLog = "tracelog"; - private final String keyForceRelayConnection = "isConnectionForceRelayed"; - private final SharedPreferences sharedPref; public Preferences(Context context) { @@ -26,18 +24,6 @@ public void disableTraceLog() { sharedPref.edit().putBoolean(keyTraceLog, false).apply(); } - public boolean isConnectionForceRelayed() { - return sharedPref.getBoolean(keyForceRelayConnection, true); - } - - public void enableForcedRelayConnection() { - sharedPref.edit().putBoolean(keyForceRelayConnection, true).apply(); - } - - public void disableForcedRelayConnection() { - sharedPref.edit().putBoolean(keyForceRelayConnection, false).apply(); - } - public static String defaultServer() { return "https://api.netbird.io"; }