summaryrefslogtreecommitdiffhomepage
path: root/app/src/main/java/com/wireguard/android/activity/MainActivity.java
diff options
context:
space:
mode:
Diffstat (limited to 'app/src/main/java/com/wireguard/android/activity/MainActivity.java')
-rw-r--r--app/src/main/java/com/wireguard/android/activity/MainActivity.java146
1 files changed, 146 insertions, 0 deletions
diff --git a/app/src/main/java/com/wireguard/android/activity/MainActivity.java b/app/src/main/java/com/wireguard/android/activity/MainActivity.java
new file mode 100644
index 00000000..2d06a9a9
--- /dev/null
+++ b/app/src/main/java/com/wireguard/android/activity/MainActivity.java
@@ -0,0 +1,146 @@
+package com.wireguard.android.activity;
+
+import android.app.Fragment;
+import android.app.FragmentTransaction;
+import android.content.Intent;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.Menu;
+import android.view.MenuItem;
+
+import com.wireguard.android.R;
+import com.wireguard.android.fragment.ConfigEditorFragment;
+import com.wireguard.android.fragment.TunnelDetailFragment;
+import com.wireguard.android.fragment.TunnelListFragment;
+import com.wireguard.android.model.Tunnel;
+
+import java9.util.stream.Stream;
+
+/**
+ * CRUD interface for WireGuard tunnels. This activity serves as the main entry point to the
+ * WireGuard application, and contains several fragments for listing, viewing details of, and
+ * editing the configuration and interface state of WireGuard tunnels.
+ */
+
+public class MainActivity extends BaseActivity {
+ private static final String KEY_STATE = "fragment_state";
+ private static final String TAG = MainActivity.class.getSimpleName();
+ private State state = State.EMPTY;
+
+ private boolean moveToState(final State nextState) {
+ Log.i(TAG, "Moving from " + state.name() + " to " + nextState.name());
+ if (nextState == state) {
+ return false;
+ } else if (nextState.layer > state.layer + 1) {
+ moveToState(State.ofLayer(state.layer + 1));
+ moveToState(nextState);
+ return true;
+ } else if (nextState.layer == state.layer + 1) {
+ final Fragment fragment = Fragment.instantiate(this, nextState.fragment);
+ final FragmentTransaction transaction = getFragmentManager().beginTransaction()
+ .replace(R.id.master_fragment, fragment)
+ .setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
+ if (state.layer > 0)
+ transaction.addToBackStack(null);
+ transaction.commit();
+ } else if (nextState.layer == state.layer - 1) {
+ if (getFragmentManager().getBackStackEntryCount() == 0)
+ return false;
+ getFragmentManager().popBackStack();
+ } else if (nextState.layer < state.layer - 1) {
+ moveToState(State.ofLayer(state.layer - 1));
+ moveToState(nextState);
+ return true;
+ }
+ state = nextState;
+ if (state.layer > 1) {
+ if (getActionBar() != null)
+ getActionBar().setDisplayHomeAsUpEnabled(true);
+ } else {
+ if (getActionBar() != null)
+ getActionBar().setDisplayHomeAsUpEnabled(false);
+ setSelectedTunnel(null);
+ }
+ return true;
+ }
+
+ @Override
+ public void onBackPressed() {
+ if (!moveToState(State.ofLayer(state.layer - 1)))
+ super.onBackPressed();
+ }
+
+ @Override
+ protected void onCreate(final Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.main_activity);
+ if (savedInstanceState != null && savedInstanceState.getString(KEY_STATE) != null)
+ state = State.valueOf(savedInstanceState.getString(KEY_STATE));
+ if (state == State.EMPTY) {
+ State initialState = getSelectedTunnel() != null ? State.DETAIL : State.LIST;
+ if (getIntent() != null && getIntent().getStringExtra(KEY_STATE) != null)
+ initialState = State.valueOf(getIntent().getStringExtra(KEY_STATE));
+ moveToState(initialState);
+ }
+ }
+
+ @Override
+ public boolean onCreateOptionsMenu(final Menu menu) {
+ getMenuInflater().inflate(R.menu.main_activity, menu);
+ return true;
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(final MenuItem item) {
+ switch (item.getItemId()) {
+ case android.R.id.home:
+ // The back arrow in the action bar should act the same as the back button.
+ moveToState(State.ofLayer(state.layer - 1));
+ return true;
+ case R.id.menu_action_edit:
+ if (getSelectedTunnel() != null)
+ moveToState(State.EDITOR);
+ return true;
+ case R.id.menu_action_save:
+ // This menu item is handled by the editor fragment.
+ return false;
+ case R.id.menu_settings:
+ startActivity(new Intent(this, SettingsActivity.class));
+ return true;
+ default:
+ return super.onOptionsItemSelected(item);
+ }
+ }
+
+ @Override
+ protected void onSaveInstanceState(final Bundle outState) {
+ outState.putString(KEY_STATE, state.name());
+ super.onSaveInstanceState(outState);
+ }
+
+
+ @Override
+ protected Tunnel onSelectedTunnelChanged(final Tunnel oldTunnel, final Tunnel newTunnel) {
+ moveToState(newTunnel != null ? State.DETAIL : State.LIST);
+ return newTunnel;
+ }
+
+ private enum State {
+ EMPTY(null, 0),
+ LIST(TunnelListFragment.class, 1),
+ DETAIL(TunnelDetailFragment.class, 2),
+ EDITOR(ConfigEditorFragment.class, 3);
+
+ private final String fragment;
+ private final int layer;
+
+ State(final Class<? extends Fragment> fragment, final int layer) {
+ this.fragment = fragment != null ? fragment.getName() : null;
+ this.layer = layer;
+ }
+
+ private static State ofLayer(final int layer) {
+ return Stream.of(State.values()).filter(s -> s.layer == layer).findFirst().get();
+ }
+ }
+}