aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/app/src/main/java/com/wireguard/android/ConfigActivity.java
diff options
context:
space:
mode:
authorSamuel Holland <samuel@sholland.org>2018-01-01 02:06:37 -0600
committerSamuel Holland <samuel@sholland.org>2018-01-06 04:09:29 -0600
commit609194fae2332e6f2ccd7a4464bfa492ad661a6f (patch)
tree96a7cd9846a093dfcdacfef285b0a4d77000edf0 /app/src/main/java/com/wireguard/android/ConfigActivity.java
parentRename package widgets -> widget (diff)
downloadwireguard-android-609194fae2332e6f2ccd7a4464bfa492ad661a6f.tar.xz
wireguard-android-609194fae2332e6f2ccd7a4464bfa492ad661a6f.zip
Serviceless rewrite, part 1
Signed-off-by: Samuel Holland <samuel@sholland.org>
Diffstat (limited to 'app/src/main/java/com/wireguard/android/ConfigActivity.java')
-rw-r--r--app/src/main/java/com/wireguard/android/ConfigActivity.java289
1 files changed, 0 insertions, 289 deletions
diff --git a/app/src/main/java/com/wireguard/android/ConfigActivity.java b/app/src/main/java/com/wireguard/android/ConfigActivity.java
deleted file mode 100644
index b92b34e3..00000000
--- a/app/src/main/java/com/wireguard/android/ConfigActivity.java
+++ /dev/null
@@ -1,289 +0,0 @@
-package com.wireguard.android;
-
-import android.app.Fragment;
-import android.app.FragmentManager;
-import android.app.FragmentTransaction;
-import android.content.Intent;
-import android.databinding.Observable;
-import android.os.Bundle;
-import android.view.Menu;
-import android.view.MenuItem;
-
-import com.wireguard.config.Config;
-
-/**
- * Activity that allows creating/viewing/editing/deleting WireGuard configurations.
- */
-
-public class ConfigActivity extends BaseConfigActivity {
- private static final String KEY_EDITOR_STATE = "editorState";
- private static final String TAG_DETAIL = "detail";
- private static final String TAG_EDIT = "edit";
- private static final String TAG_LIST = "list";
-
- private Fragment.SavedState editorState;
- private final FragmentManager fm = getFragmentManager();
- private final FragmentCache fragments = new FragmentCache(fm);
- private boolean isLayoutFinished;
- private boolean isServiceAvailable;
- private boolean isSingleLayout;
- private boolean isStateSaved;
- private int mainContainer;
- private Observable.OnPropertyChangedCallback nameChangeCallback;
- private String visibleFragmentTag;
-
- /**
- * Updates the fragment visible in the UI.
- * Sets visibleFragmentTag.
- *
- * @param config The config that should be visible.
- * @param tag The tag of the fragment that should be visible.
- */
- private void moveToFragment(final Config config, final String tag) {
- // Sanity check.
- if (tag == null && config != null)
- throw new IllegalArgumentException("Cannot set a config on a null fragment");
- if ((tag == null && isSingleLayout) || (TAG_LIST.equals(tag) && !isSingleLayout))
- throw new IllegalArgumentException("Requested tag " + tag + " does not match layout");
- // First tear down fragments as necessary.
- if (tag == null || TAG_LIST.equals(tag) || (TAG_DETAIL.equals(tag)
- && TAG_EDIT.equals(visibleFragmentTag))) {
- while (visibleFragmentTag != null && !visibleFragmentTag.equals(tag) &&
- fm.getBackStackEntryCount() > 0) {
- final Fragment removedFragment = fm.findFragmentById(mainContainer);
- // The fragment *must* be removed first, or it will stay attached to the layout!
- fm.beginTransaction().remove(removedFragment).commit();
- fm.popBackStackImmediate();
- // Recompute the visible fragment.
- if (TAG_EDIT.equals(visibleFragmentTag))
- visibleFragmentTag = TAG_DETAIL;
- else if (isSingleLayout && TAG_DETAIL.equals(visibleFragmentTag))
- visibleFragmentTag = TAG_LIST;
- else
- throw new IllegalStateException();
- }
- }
- // Now build up intermediate entries in the back stack as necessary.
- if (TAG_EDIT.equals(tag) && !TAG_EDIT.equals(visibleFragmentTag) &&
- !TAG_DETAIL.equals(visibleFragmentTag))
- moveToFragment(config, TAG_DETAIL);
- // Finally, set the main container's content to the new top-level fragment.
- if (tag == null) {
- if (visibleFragmentTag != null) {
- final BaseConfigFragment fragment = fragments.get(visibleFragmentTag);
- fm.beginTransaction().remove(fragment).commit();
- fm.executePendingTransactions();
- visibleFragmentTag = null;
- }
- } else if (!TAG_LIST.equals(tag)) {
- final BaseConfigFragment fragment = fragments.get(tag);
- if (!tag.equals(visibleFragmentTag)) {
- // Restore any saved editor state the first time its fragment is added.
- if (TAG_EDIT.equals(tag) && editorState != null) {
- fragment.setInitialSavedState(editorState);
- editorState = null;
- }
- final FragmentTransaction transaction = fm.beginTransaction();
- if (TAG_EDIT.equals(tag) || (isSingleLayout && TAG_DETAIL.equals(tag))) {
- transaction.addToBackStack(null);
- transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
- }
- transaction.replace(mainContainer, fragment, tag).commit();
- visibleFragmentTag = tag;
- }
- if (fragment.getCurrentConfig() != config)
- fragment.setCurrentConfig(config);
- }
- }
-
- /**
- * Transition the state machine to the desired state, if possible.
- * Sets currentConfig and isEditing.
- *
- * @param config The desired config to show in the UI.
- * @param shouldBeEditing Whether or not the config should be in the editing state.
- */
- private void moveToState(final Config config, final boolean shouldBeEditing) {
- // Update the saved state.
- setCurrentConfig(config);
- setIsEditing(shouldBeEditing);
- // Avoid performing fragment transactions when the app is not fully initialized.
- if (!isLayoutFinished || !isServiceAvailable || isStateSaved)
- return;
- // Ensure the list is present in the master pane. It will be restored on activity restarts!
- final BaseConfigFragment listFragment = fragments.get(TAG_LIST);
- if (fm.findFragmentById(R.id.master_fragment) == null)
- fm.beginTransaction().add(R.id.master_fragment, listFragment, TAG_LIST).commit();
- // In the single-pane layout, the main container starts holding the list fragment.
- if (isSingleLayout && visibleFragmentTag == null)
- visibleFragmentTag = TAG_LIST;
- // Forward any config changes to the list (they may have come from the intent or editing).
- listFragment.setCurrentConfig(config);
- // Ensure the correct main fragment is visible, adjusting the back stack as necessary.
- moveToFragment(config, shouldBeEditing ? TAG_EDIT :
- (config != null ? TAG_DETAIL : (isSingleLayout ? TAG_LIST : null)));
- // Show the current config as the title if the list of configurations is not visible.
- setTitle(isSingleLayout && config != null ? config.getName() : getString(R.string.app_name));
- // Show or hide the action bar back button if the back stack is not empty.
- if (getActionBar() != null) {
- getActionBar().setDisplayHomeAsUpEnabled(config != null &&
- (isSingleLayout || shouldBeEditing));
- }
- }
-
- @Override
- public void onBackPressed() {
- final ConfigListFragment listFragment = (ConfigListFragment) fragments.get(TAG_LIST);
- if (listFragment.isVisible() && listFragment.tryCollapseMenu())
- return;
- super.onBackPressed();
- // The visible fragment is now the one that was on top of the back stack, if there was one.
- if (isEditing())
- visibleFragmentTag = TAG_DETAIL;
- else if (isSingleLayout && TAG_DETAIL.equals(visibleFragmentTag))
- visibleFragmentTag = TAG_LIST;
- // If the user went back from the detail screen to the list, clear the current config.
- moveToState(isEditing() ? getCurrentConfig() : null, false);
- }
-
- @Override
- public void onCreate(final Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- if (savedInstanceState != null)
- editorState = savedInstanceState.getParcelable(KEY_EDITOR_STATE);
- setContentView(R.layout.config_activity);
- isSingleLayout = findViewById(R.id.detail_fragment) == null;
- mainContainer = isSingleLayout ? R.id.master_fragment : R.id.detail_fragment;
- if (isSingleLayout) {
- nameChangeCallback = new ConfigNameChangeCallback();
- if (getCurrentConfig() != null)
- getCurrentConfig().addOnPropertyChangedCallback(nameChangeCallback);
- }
- isLayoutFinished = true;
- moveToState(getCurrentConfig(), isEditing());
- }
-
- @Override
- public boolean onCreateOptionsMenu(final Menu menu) {
- getMenuInflater().inflate(R.menu.main, menu);
- return true;
- }
-
- @Override
- protected void onCurrentConfigChanged(final Config oldConfig, final Config newConfig) {
- if (nameChangeCallback != null && oldConfig != null)
- oldConfig.removeOnPropertyChangedCallback(nameChangeCallback);
- // Abandon editing a config when the current config changes.
- moveToState(newConfig, false);
- if (nameChangeCallback != null && newConfig != null)
- newConfig.addOnPropertyChangedCallback(nameChangeCallback);
- }
-
- @Override
- protected void onEditingStateChanged(final boolean isEditing) {
- moveToState(getCurrentConfig(), isEditing);
- }
-
- @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.
- onBackPressed();
- return true;
- case R.id.menu_action_edit:
- // Try to make the editing fragment visible.
- setIsEditing(true);
- return true;
- case R.id.menu_action_save:
- // This menu item is handled by the editing fragment.
- return false;
- case R.id.menu_settings:
- startActivity(new Intent(this, SettingsActivity.class));
- return true;
- default:
- return super.onOptionsItemSelected(item);
- }
- }
-
- @Override
- public void onPostResume() {
- super.onPostResume();
- // Allow changes to fragments.
- isStateSaved = false;
- moveToState(getCurrentConfig(), isEditing());
- }
-
- @Override
- public void onSaveInstanceState(final Bundle outState) {
- // We cannot save fragments that might switch between containers if the layout changes.
- if (isLayoutFinished && isServiceAvailable && !isStateSaved) {
- // Save the editor state before destroying it.
- if (TAG_EDIT.equals(visibleFragmentTag)) {
- // For the case where the activity is resumed.
- editorState = fm.saveFragmentInstanceState(fragments.get(TAG_EDIT));
- // For the case where the activity is restarted.
- outState.putParcelable(KEY_EDITOR_STATE, editorState);
- }
- moveToFragment(null, isSingleLayout ? TAG_LIST : null);
- }
- // Prevent further changes to fragments.
- isStateSaved = true;
- super.onSaveInstanceState(outState);
- }
-
- @Override
- protected void onServiceAvailable() {
- super.onServiceAvailable();
- // Allow creating fragments.
- isServiceAvailable = true;
- moveToState(getCurrentConfig(), isEditing());
- }
-
- private class ConfigNameChangeCallback extends Observable.OnPropertyChangedCallback {
- @Override
- public void onPropertyChanged(final Observable sender, final int propertyId) {
- if (sender != getCurrentConfig())
- sender.removeOnPropertyChangedCallback(this);
- if (propertyId != 0 && propertyId != BR.name)
- return;
- setTitle(getCurrentConfig().getName());
- }
- }
-
- private static class FragmentCache {
- private ConfigDetailFragment detailFragment;
- private ConfigEditFragment editFragment;
- private final FragmentManager fm;
- private ConfigListFragment listFragment;
-
- private FragmentCache(final FragmentManager fm) {
- this.fm = fm;
- }
-
- private BaseConfigFragment get(final String tag) {
- switch (tag) {
- case TAG_DETAIL:
- if (detailFragment == null)
- detailFragment = (ConfigDetailFragment) fm.findFragmentByTag(tag);
- if (detailFragment == null)
- detailFragment = new ConfigDetailFragment();
- return detailFragment;
- case TAG_EDIT:
- if (editFragment == null)
- editFragment = (ConfigEditFragment) fm.findFragmentByTag(tag);
- if (editFragment == null)
- editFragment = new ConfigEditFragment();
- return editFragment;
- case TAG_LIST:
- if (listFragment == null)
- listFragment = (ConfigListFragment) fm.findFragmentByTag(tag);
- if (listFragment == null)
- listFragment = new ConfigListFragment();
- return listFragment;
- default:
- throw new IllegalArgumentException();
- }
- }
- }
-}