From 9469d6d6b246a2234a245e4dd21f863bc7b044e7 Mon Sep 17 00:00:00 2001 From: Andrea Torlaschi Date: Sat, 20 Aug 2016 00:31:06 +0200 Subject: [PATCH] ImportKeys: Use single card for importing all keys --- .../processing/ImportKeysListLoader.java | 18 +- .../keychain/ui/ImportKeysListFragment.java | 168 ++++++------------ .../ui/adapter/ImportKeysAdapter.java | 9 +- .../res/layout/import_keys_list_fragment.xml | 68 +++---- .../main/res/layout/import_keys_list_item.xml | 13 +- .../layout/import_keys_list_item_basic.xml | 62 +++++++ .../res/menu/import_keys_list_fragment.xml | 12 -- OpenKeychain/src/main/res/values/strings.xml | 7 +- 8 files changed, 157 insertions(+), 200 deletions(-) create mode 100644 OpenKeychain/src/main/res/layout/import_keys_list_item_basic.xml delete mode 100644 OpenKeychain/src/main/res/menu/import_keys_list_fragment.xml diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/processing/ImportKeysListLoader.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/processing/ImportKeysListLoader.java index 33e9c935a..717dbe511 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/processing/ImportKeysListLoader.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/keyimport/processing/ImportKeysListLoader.java @@ -21,7 +21,6 @@ package org.sufficientlysecure.keychain.keyimport.processing; import android.content.Context; import android.support.annotation.NonNull; import android.support.v4.content.AsyncTaskLoader; -import android.support.v4.util.LongSparseArray; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.keyimport.ImportKeysListEntry; @@ -43,16 +42,17 @@ import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; +import java.util.List; public class ImportKeysListLoader extends AsyncTaskLoader>> { - final Context mContext; - final BytesLoaderState mLoaderState; + private final Context mContext; + private final BytesLoaderState mLoaderState; - ArrayList mData = new ArrayList<>(); - LongSparseArray mParcelableRings = new LongSparseArray<>(); - AsyncTaskResultWrapper> mEntryListWrapper; + private ArrayList mData = new ArrayList<>(); + private ArrayList mParcelableRings = new ArrayList<>(); + private AsyncTaskResultWrapper> mEntryListWrapper; public ImportKeysListLoader(Context context, BytesLoaderState inputData) { super(context); @@ -113,7 +113,7 @@ public class ImportKeysListLoader super.deliverResult(data); } - public LongSparseArray getParcelableRings() { + public List getParcelableRings() { return mParcelableRings; } @@ -133,11 +133,9 @@ public class ImportKeysListLoader IteratorWithIOThrow it = UncachedKeyRing.fromStream(bufferedInput); while (it.hasNext()) { UncachedKeyRing ring = it.next(); - ImportKeysListEntry item = new ImportKeysListEntry(mContext, ring); mData.add(item); - - mParcelableRings.put(item.hashCode(), new ParcelableKeyRing(ring.getEncoded())); + mParcelableRings.add(item.getParcelableKeyRing()); } } catch (IOException e) { Log.e(Constants.TAG, "IOException on parsing key file! Return NoValidKeysException!", e); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysListFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysListFragment.java index 0429cf82c..ac9489e53 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysListFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ImportKeysListFragment.java @@ -28,20 +28,14 @@ import android.support.v4.app.Fragment; import android.support.v4.app.FragmentActivity; import android.support.v4.app.LoaderManager; import android.support.v4.content.Loader; -import android.support.v4.util.LongSparseArray; import android.support.v7.widget.LinearLayoutManager; -import android.support.v7.widget.RecyclerView; import android.view.LayoutInflater; -import android.view.Menu; -import android.view.MenuInflater; -import android.view.MenuItem; import android.view.View; -import android.view.View.OnClickListener; import android.view.ViewGroup; -import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.databinding.ImportKeysListFragmentBinding; +import org.sufficientlysecure.keychain.databinding.ImportKeysListItemBasicBinding; import org.sufficientlysecure.keychain.keyimport.ImportKeysListEntry; import org.sufficientlysecure.keychain.keyimport.ParcelableKeyRing; import org.sufficientlysecure.keychain.keyimport.processing.AsyncTaskResultWrapper; @@ -56,7 +50,6 @@ import org.sufficientlysecure.keychain.service.input.RequiredInputParcel; import org.sufficientlysecure.keychain.ui.adapter.ImportKeysAdapter; import org.sufficientlysecure.keychain.ui.util.PermissionsUtil; import org.sufficientlysecure.keychain.util.IteratorWithSize; -import org.sufficientlysecure.keychain.util.Log; import org.sufficientlysecure.keychain.util.ParcelableProxy; import org.sufficientlysecure.keychain.util.Preferences; import org.sufficientlysecure.keychain.util.Preferences.CloudSearchPrefs; @@ -78,13 +71,12 @@ public class ImportKeysListFragment extends Fragment implements private FragmentActivity mActivity; private ImportKeysListener mCallback; - private ImportKeysListFragmentBinding binding; + private ImportKeysListFragmentBinding mBinding; + private ImportKeysListItemBasicBinding mBindingBasic; private ParcelableProxy mParcelableProxy; - private RecyclerView mRecyclerView; + private List mKeyData; private ImportKeysAdapter mAdapter; - private boolean mAdvanced; - private LoaderState mLoaderState; public static final int STATUS_FIRST = 0; @@ -94,53 +86,9 @@ public class ImportKeysListFragment extends Fragment implements private static final int LOADER_ID_BYTES = 0; private static final int LOADER_ID_CLOUD = 1; - private LongSparseArray mCachedKeyData; private boolean mShowingOrbotDialog; - /** - * Returns an Iterator (with size) of the selected data items. - * This iterator is sort of a tradeoff, it's slightly more complex than an - * ArrayList would have been, but we save some memory by just returning - * relevant elements on demand. - */ - public IteratorWithSize getData() { - final List entries = getEntries(); - final Iterator it = entries.iterator(); - return new IteratorWithSize() { - - @Override - public int getSize() { - return entries.size(); - } - - @Override - public boolean hasNext() { - return it.hasNext(); - } - - @Override - public ParcelableKeyRing next() { - // throws NoSuchElementException if it doesn't exist, but that's not our problem - return mCachedKeyData.get(it.next().hashCode()); - } - - @Override - public void remove() { - it.remove(); - } - }; - } - - private List getEntries() { - if (mAdapter != null) { - return mAdapter.getEntries(); - } else { - Log.e(Constants.TAG, "Adapter not initialized, returning empty list"); - return new ArrayList<>(); - } - } - /** * Creates an interactive ImportKeyListFragment which reads keyrings from bytes, or file specified * by dataUri, or searches a keyserver for serverQuery, if parameter is not null, in that order @@ -191,23 +139,24 @@ public class ImportKeysListFragment extends Fragment implements @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle bundle) { - binding = DataBindingUtil.inflate(inflater, R.layout.import_keys_list_fragment, container, false); - binding.setStatus(STATUS_FIRST); - View view = binding.getRoot(); + mBinding = DataBindingUtil.inflate(inflater, R.layout.import_keys_list_fragment, container, false); + mBinding.setStatus(STATUS_FIRST); + mBindingBasic = mBinding.basic; + View view = mBinding.getRoot(); mActivity = getActivity(); - setHasOptionsMenu(true); Bundle args = getArguments(); Uri dataUri = args.getParcelable(ARG_DATA_URI); byte[] bytes = args.getByteArray(ARG_BYTES); String query = args.getString(ARG_SERVER_QUERY); boolean nonInteractive = args.getBoolean(ARG_NON_INTERACTIVE, false); + mBindingBasic.setNonInteractive(nonInteractive); // Create an empty adapter we will use to display the loaded data. mAdapter = new ImportKeysAdapter(mActivity, mCallback, nonInteractive); - binding.recyclerView.setAdapter(mAdapter); - binding.recyclerView.setLayoutManager(new LinearLayoutManager(mActivity)); + mBinding.recyclerView.setAdapter(mAdapter); + mBinding.recyclerView.setLayoutManager(new LinearLayoutManager(mActivity)); if (dataUri != null || bytes != null) { loadState(new BytesLoaderState(bytes, dataUri)); @@ -224,12 +173,18 @@ public class ImportKeysListFragment extends Fragment implements restartLoaders(); } - binding.importKeys.setOnClickListener(new OnClickListener() { + mBinding.basic.importKeys.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { mCallback.importKeys(); } }); + mBinding.basic.listKeys.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + mBinding.setAdvanced(true); + } + }); return view; } @@ -246,42 +201,6 @@ public class ImportKeysListFragment extends Fragment implements } } - @Override - public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { - if (mLoaderState != null) { - inflater.inflate(R.menu.import_keys_list_fragment, menu); - - MenuItem basicMenuItem = menu.findItem(R.id.basic); - basicMenuItem.setVisible(mAdvanced && mLoaderState.isBasicModeSupported()); - MenuItem advancedMenuItem = menu.findItem(R.id.advanced); - advancedMenuItem.setVisible(!mAdvanced); - } - - super.onCreateOptionsMenu(menu, inflater); - } - - @Override - public boolean onOptionsItemSelected(MenuItem item) { - int itemId = item.getItemId(); - switch (itemId) { - case R.id.basic: - setAdvanced(false); - return true; - case R.id.advanced: - setAdvanced(true); - return true; - } - return false; - } - - public void setAdvanced(boolean advanced) { - this.mAdvanced = advanced; - - mAdapter.setAdvanced(advanced); - mActivity.invalidateOptionsMenu(); - binding.setAdvanced(advanced); - } - @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @@ -310,11 +229,7 @@ public class ImportKeysListFragment extends Fragment implements return; } } - - if (!mLoaderState.isBasicModeSupported()) { - mAdvanced = true; - } - setAdvanced(mAdvanced); + mBinding.setAdvanced(!mLoaderState.isBasicModeSupported()); restartLoaders(); } @@ -348,7 +263,7 @@ public class ImportKeysListFragment extends Fragment implements } if (loader != null) { - binding.setStatus(STATUS_LOADING); + mBinding.setStatus(STATUS_LOADING); } return loader; @@ -360,19 +275,20 @@ public class ImportKeysListFragment extends Fragment implements AsyncTaskResultWrapper> data ) { ArrayList result = data.getResult(); - binding.setStatus(result.size() > 0 ? STATUS_LOADED : STATUS_EMPTY); - - // free old cached key data - mCachedKeyData = null; + mKeyData = null; mAdapter.setData(result); + int size = result.size(); + mBindingBasic.setNumber(size); + mBinding.setStatus(size > 0 ? STATUS_LOADED : STATUS_EMPTY); + GetKeyResult getKeyResult = (GetKeyResult) data.getOperationResult(); switch (loader.getId()) { case LOADER_ID_BYTES: if (getKeyResult.success()) { // No error - mCachedKeyData = ((ImportKeysListLoader) loader).getParcelableRings(); + mKeyData = ((ImportKeysListLoader) loader).getParcelableRings(); } else { getKeyResult.createNotify(mActivity).show(); } @@ -443,4 +359,36 @@ public class ImportKeysListFragment extends Fragment implements mAdapter.clearData(); } + /** + * Returns an Iterator (with size) of the selected data items. + * This iterator is sort of a tradeoff, it's slightly more complex than an + * ArrayList would have been, but we save some memory by just returning + * relevant elements on demand. + */ + public IteratorWithSize getData() { + final Iterator it = mKeyData.iterator(); + return new IteratorWithSize() { + + @Override + public int getSize() { + return mKeyData.size(); + } + + @Override + public boolean hasNext() { + return it.hasNext(); + } + + @Override + public ParcelableKeyRing next() { + return it.next(); + } + + @Override + public void remove() { + it.remove(); + } + }; + } + } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysAdapter.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysAdapter.java index 1d6af1f21..3ed25fd55 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysAdapter.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysAdapter.java @@ -49,7 +49,7 @@ public class ImportKeysAdapter extends RecyclerView.Adapter mData; @@ -64,11 +64,6 @@ public class ImportKeysAdapter extends RecyclerView.Adapter data) { this.mData = data; this.mKeyStates = new KeyState[data.size()]; @@ -127,8 +122,6 @@ public class ImportKeysAdapter extends RecyclerView.Adapter + xmlns:app="http://schemas.android.com/apk/res-auto"> - - - - + + @@ -24,59 +19,42 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true" - android:visibility="@{status == i.STATUS_LOADING ? View.VISIBLE : View.GONE}" /> + android:visibility="@{status == i.STATUS_LOADING ? V.VISIBLE : V.GONE}" /> + android:visibility="@{status == i.STATUS_EMPTY ? V.VISIBLE : V.GONE}" /> - + android:visibility="@{status == i.STATUS_LOADED ? V.VISIBLE : V.GONE}"> - - - + android:layout_height="match_parent" + android:visibility="@{advanced ? V.GONE : V.VISIBLE}"> - + - + - + + + diff --git a/OpenKeychain/src/main/res/layout/import_keys_list_item.xml b/OpenKeychain/src/main/res/layout/import_keys_list_item.xml index e017ae2e6..1e0666b22 100644 --- a/OpenKeychain/src/main/res/layout/import_keys_list_item.xml +++ b/OpenKeychain/src/main/res/layout/import_keys_list_item.xml @@ -5,7 +5,6 @@ - @@ -77,18 +76,11 @@ - - - + android:visibility="@{nonInteractive ? V.GONE : V.VISIBLE}">