diff options
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.java | 146 |
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(); + } + } +} |