diff --git a/app/src/main/java/com/wireguard/android/fragment/TunnelController.java b/app/src/main/java/com/wireguard/android/fragment/TunnelController.java new file mode 100644 index 00000000..668e74c0 --- /dev/null +++ b/app/src/main/java/com/wireguard/android/fragment/TunnelController.java @@ -0,0 +1,71 @@ +package com.wireguard.android.fragment; + +import android.app.AlertDialog; +import android.content.Context; +import android.databinding.DataBindingUtil; +import android.databinding.ViewDataBinding; +import android.system.ErrnoException; +import android.system.OsConstants; +import android.text.Html; +import android.text.method.LinkMovementMethod; +import android.util.Log; +import android.view.View; +import android.widget.TextView; + +import com.commonsware.cwac.crossport.design.widget.Snackbar; +import com.wireguard.android.R; +import com.wireguard.android.databinding.TunnelDetailFragmentBinding; +import com.wireguard.android.databinding.TunnelListItemBinding; +import com.wireguard.android.model.Tunnel; +import com.wireguard.android.model.Tunnel.State; +import com.wireguard.android.util.ExceptionLoggers; + +/** + * Helper method shared by TunnelListFragment and TunnelDetailFragment. + */ + +public final class TunnelController { + private static final String TAG = TunnelController.class.getSimpleName(); + + private TunnelController() { + // Prevent instantiation. + } + + public static void setTunnelState(final View view, final boolean checked) { + final ViewDataBinding binding = DataBindingUtil.findBinding(view); + final Tunnel tunnel; + if (binding instanceof TunnelDetailFragmentBinding) + tunnel = ((TunnelDetailFragmentBinding) binding).getTunnel(); + else if (binding instanceof TunnelListItemBinding) + tunnel = ((TunnelListItemBinding) binding).getItem(); + else + tunnel = null; + if (tunnel == null) { + Log.e(TAG, "setChecked() from a null tunnel", new IllegalStateException()); + return; + } + tunnel.setState(State.of(checked)).whenComplete((state, throwable) -> { + if (throwable == null) + return; + Log.e(TAG, "Cannot set state of tunnel " + tunnel.getName(), throwable); + final Context context = view.getContext(); + if (throwable instanceof ErrnoException + && ((ErrnoException) throwable).errno == OsConstants.ENODEV) { + final String message = context.getString(R.string.not_supported_message); + final AlertDialog dialog = new AlertDialog.Builder(context) + .setMessage(Html.fromHtml(message)) + .setPositiveButton(R.string.ok, null) + .setTitle(R.string.not_supported_title) + .show(); + // Make links work. + ((TextView) dialog.findViewById(android.R.id.message)) + .setMovementMethod(LinkMovementMethod.getInstance()); + } else { + final String message = + context.getString(checked ? R.string.error_up : R.string.error_down) + ": " + + ExceptionLoggers.unwrap(throwable).getMessage(); + Snackbar.make(view, message, Snackbar.LENGTH_LONG).show(); + } + }); + } +} diff --git a/app/src/main/res/layout/tunnel_detail_fragment.xml b/app/src/main/res/layout/tunnel_detail_fragment.xml index e10bc4e1..900d08ed 100644 --- a/app/src/main/res/layout/tunnel_detail_fragment.xml +++ b/app/src/main/res/layout/tunnel_detail_fragment.xml @@ -5,6 +5,8 @@ + + @@ -52,7 +54,7 @@ android:layout_alignBaseline="@+id/interface_title" android:layout_alignParentEnd="true" app:checked="@{tunnel.state == State.UP}" - app:onBeforeCheckedChanged="@{() -> tunnel.setState(State.TOGGLE)}" /> + app:onBeforeCheckedChanged="@{TunnelController::setTunnelState}" /> + + @@ -47,6 +49,6 @@ android:layout_alignBaseline="@+id/tunnel_name" android:layout_alignParentEnd="true" app:checked="@{item.state == State.UP}" - app:onBeforeCheckedChanged="@{() -> item.setState(State.TOGGLE)}" /> + app:onBeforeCheckedChanged="@{TunnelController::setTunnelState}" /> diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index f32a9925..f7b4c548 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -16,7 +16,6 @@ Edit Endpoint Error bringing down WireGuard tunnel - WireGuard currently requires root access Error bringing up WireGuard tunnel Generate (auto)