ImportKeys: Add basic key importing

This commit is contained in:
Andrea Torlaschi
2016-08-16 23:32:48 +02:00
parent 1cdd91cc85
commit 28af02c6c7
7 changed files with 159 additions and 33 deletions

View File

@@ -268,6 +268,7 @@ public class ImportKeysActivity extends BaseActivity implements ImportKeysListen
*/ */
private void startListFragment(byte[] bytes, Uri dataUri, String serverQuery, private void startListFragment(byte[] bytes, Uri dataUri, String serverQuery,
Preferences.CloudSearchPrefs cloudSearchPrefs) { Preferences.CloudSearchPrefs cloudSearchPrefs) {
Fragment listFragment = Fragment listFragment =
ImportKeysListFragment.newInstance(bytes, dataUri, serverQuery, false, ImportKeysListFragment.newInstance(bytes, dataUri, serverQuery, false,
cloudSearchPrefs); cloudSearchPrefs);

View File

@@ -32,8 +32,12 @@ import android.support.v4.util.LongSparseArray;
import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView; import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.TextView;
import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.R;
@@ -55,6 +59,7 @@ import org.sufficientlysecure.keychain.util.IteratorWithSize;
import org.sufficientlysecure.keychain.util.Log; import org.sufficientlysecure.keychain.util.Log;
import org.sufficientlysecure.keychain.util.ParcelableProxy; import org.sufficientlysecure.keychain.util.ParcelableProxy;
import org.sufficientlysecure.keychain.util.Preferences; import org.sufficientlysecure.keychain.util.Preferences;
import org.sufficientlysecure.keychain.util.Preferences.CloudSearchPrefs;
import org.sufficientlysecure.keychain.util.orbot.OrbotHelper; import org.sufficientlysecure.keychain.util.orbot.OrbotHelper;
import java.util.ArrayList; import java.util.ArrayList;
@@ -78,6 +83,7 @@ public class ImportKeysListFragment extends Fragment implements
private RecyclerView mRecyclerView; private RecyclerView mRecyclerView;
private ImportKeysAdapter mAdapter; private ImportKeysAdapter mAdapter;
private boolean mAdvanced;
private LoaderState mLoaderState; private LoaderState mLoaderState;
@@ -148,7 +154,8 @@ public class ImportKeysListFragment extends Fragment implements
* @return fragment with arguments set based on passed parameters * @return fragment with arguments set based on passed parameters
*/ */
public static ImportKeysListFragment newInstance(byte[] bytes, Uri dataUri, String serverQuery, public static ImportKeysListFragment newInstance(byte[] bytes, Uri dataUri, String serverQuery,
Preferences.CloudSearchPrefs cloudSearchPrefs) { CloudSearchPrefs cloudSearchPrefs) {
return newInstance(bytes, dataUri, serverQuery, false, cloudSearchPrefs); return newInstance(bytes, dataUri, serverQuery, false, cloudSearchPrefs);
} }
@@ -168,8 +175,7 @@ public class ImportKeysListFragment extends Fragment implements
Uri dataUri, Uri dataUri,
String serverQuery, String serverQuery,
boolean nonInteractive, boolean nonInteractive,
Preferences.CloudSearchPrefs cloudSearchPrefs) { CloudSearchPrefs cloudSearchPrefs) {
ImportKeysListFragment frag = new ImportKeysListFragment();
Bundle args = new Bundle(); Bundle args = new Bundle();
args.putByteArray(ARG_BYTES, bytes); args.putByteArray(ARG_BYTES, bytes);
@@ -178,13 +184,13 @@ public class ImportKeysListFragment extends Fragment implements
args.putBoolean(ARG_NON_INTERACTIVE, nonInteractive); args.putBoolean(ARG_NON_INTERACTIVE, nonInteractive);
args.putParcelable(ARG_CLOUD_SEARCH_PREFS, cloudSearchPrefs); args.putParcelable(ARG_CLOUD_SEARCH_PREFS, cloudSearchPrefs);
ImportKeysListFragment frag = new ImportKeysListFragment();
frag.setArguments(args); frag.setArguments(args);
return frag; return frag;
} }
@Override @Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle bundle) {
binding = DataBindingUtil.inflate(inflater, R.layout.import_keys_list_fragment, container, false); binding = DataBindingUtil.inflate(inflater, R.layout.import_keys_list_fragment, container, false);
binding.setStatus(STATUS_FIRST); binding.setStatus(STATUS_FIRST);
View view = binding.getRoot(); View view = binding.getRoot();
@@ -208,7 +214,7 @@ public class ImportKeysListFragment extends Fragment implements
if (dataUri != null || bytes != null) { if (dataUri != null || bytes != null) {
mLoaderState = new BytesLoaderState(bytes, dataUri); mLoaderState = new BytesLoaderState(bytes, dataUri);
} else if (query != null) { } else if (query != null) {
Preferences.CloudSearchPrefs cloudSearchPrefs CloudSearchPrefs cloudSearchPrefs
= args.getParcelable(ARG_CLOUD_SEARCH_PREFS); = args.getParcelable(ARG_CLOUD_SEARCH_PREFS);
if (cloudSearchPrefs == null) { if (cloudSearchPrefs == null) {
cloudSearchPrefs = Preferences.getPreferences(mActivity).getCloudSearchPrefs(); cloudSearchPrefs = Preferences.getPreferences(mActivity).getCloudSearchPrefs();
@@ -221,6 +227,16 @@ public class ImportKeysListFragment extends Fragment implements
restartLoaders(); restartLoaders();
} }
setHasOptionsMenu(true);
TextView importAllKeys = (TextView) view.findViewById(R.id.import_keys);
importAllKeys.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
mCallback.importKeys();
}
});
return view; return view;
} }
@@ -236,6 +252,38 @@ public class ImportKeysListFragment extends Fragment implements
} }
} }
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.import_keys_list_fragment, menu);
menu.findItem(R.id.basic).setVisible(mAdvanced);
menu.findItem(R.id.advanced).setVisible(!mAdvanced);
super.onCreateOptionsMenu(menu, inflater);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.basic:
mAdvanced = false;
mAdapter.setAdvanced(false);
mActivity.invalidateOptionsMenu();
binding.setAdvanced(mAdvanced);
return true;
case R.id.advanced:
mAdvanced = true;
mAdapter.setAdvanced(true);
mActivity.invalidateOptionsMenu();
binding.setAdvanced(mAdvanced);
return true;
}
return false;
}
@Override @Override
public void onRequestPermissionsResult(int requestCode, public void onRequestPermissionsResult(int requestCode,
@NonNull String[] permissions, @NonNull String[] permissions,
@@ -263,6 +311,8 @@ public class ImportKeysListFragment extends Fragment implements
!PermissionsUtil.checkAndRequestReadPermission(mActivity, ls.mDataUri)) { !PermissionsUtil.checkAndRequestReadPermission(mActivity, ls.mDataUri)) {
return; return;
} }
} else if (mLoaderState instanceof CloudLoaderState) {
} }
restartLoaders(); restartLoaders();

View File

@@ -52,7 +52,7 @@ public class ImportKeysAdapter extends RecyclerView.Adapter<ImportKeysAdapter.Vi
private FragmentActivity mActivity; private FragmentActivity mActivity;
private ImportKeysResultListener mListener; private ImportKeysResultListener mListener;
private boolean mNonInteractive; private boolean mAdvanced, mNonInteractive;
private LoaderState mLoaderState; private LoaderState mLoaderState;
private List<ImportKeysListEntry> mData; private List<ImportKeysListEntry> mData;
@@ -60,14 +60,22 @@ public class ImportKeysAdapter extends RecyclerView.Adapter<ImportKeysAdapter.Vi
private KeyState[] mKeyStates; private KeyState[] mKeyStates;
private int mCurrent; private int mCurrent;
public ImportKeysAdapter(FragmentActivity activity, ImportKeysListener listener, boolean mNonInteractive) { public ImportKeysAdapter(FragmentActivity activity, ImportKeysListener listener,
boolean nonInteractive) {
this.mActivity = activity; this.mActivity = activity;
this.mListener = listener; this.mListener = listener;
this.mNonInteractive = mNonInteractive; this.mNonInteractive = nonInteractive;
}
public void setAdvanced(boolean advanced) {
this.mAdvanced = advanced;
notifyDataSetChanged();
} }
public void setLoaderState(LoaderState loaderState) { public void setLoaderState(LoaderState loaderState) {
this.mLoaderState = loaderState; this.mLoaderState = loaderState;
notifyDataSetChanged();
} }
public void setData(List<ImportKeysListEntry> data) { public void setData(List<ImportKeysListEntry> data) {
@@ -128,6 +136,8 @@ public class ImportKeysAdapter extends RecyclerView.Adapter<ImportKeysAdapter.Vi
final ImportKeysListEntry entry = mData.get(position); final ImportKeysListEntry entry = mData.get(position);
b.setEntry(entry); b.setEntry(entry);
b.setAdvanced(mAdvanced);
final KeyState keyState = mKeyStates[position]; final KeyState keyState = mKeyStates[position];
final boolean downloaded = keyState.mDownloaded; final boolean downloaded = keyState.mDownloaded;
final boolean showed = keyState.mShowed; final boolean showed = keyState.mShowed;

View File

@@ -1,5 +1,7 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"> <layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<data> <data>
@@ -9,12 +11,11 @@
alias="i" alias="i"
type="org.sufficientlysecure.keychain.ui.ImportKeysListFragment" /> type="org.sufficientlysecure.keychain.ui.ImportKeysListFragment" />
<variable <variable name="status" type="int" />
name="status" <variable name="advanced" type="boolean" />
type="int" />
</data> </data>
<FrameLayout <RelativeLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:background="@color/md_grey_100"> android:background="@color/md_grey_100">
@@ -22,23 +23,60 @@
<ProgressBar <ProgressBar
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center" android:layout_centerInParent="true"
android:visibility="@{status == i.STATUS_LOADING ? View.VISIBLE : View.GONE}" /> android:visibility="@{status == i.STATUS_LOADING ? View.VISIBLE : View.GONE}" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text="@string/error_nothing_import"
android:visibility="@{status == i.STATUS_EMPTY ? View.VISIBLE : View.GONE}" />
<android.support.v7.widget.RecyclerView <android.support.v7.widget.RecyclerView
android:id="@+id/recycler_view" android:id="@+id/recycler_view"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:layout_above="@+id/toolbar_bottom"
android:paddingLeft="8dp" android:paddingLeft="8dp"
android:paddingRight="8dp" android:paddingRight="8dp"
android:scrollbars="vertical" android:scrollbars="vertical"
android:visibility="@{status == i.STATUS_LOADED ? View.VISIBLE : View.GONE}" /> android:visibility="@{status == i.STATUS_LOADED ? View.VISIBLE : View.GONE}" />
<TextView <android.support.v7.widget.Toolbar
android:layout_width="wrap_content" android:id="@+id/toolbar_bottom"
android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center" android:layout_alignParentBottom="true"
android:text="@string/error_nothing_import" android:background="?attr/colorPrimary"
android:visibility="@{status == i.STATUS_EMPTY ? View.VISIBLE : View.GONE}" /> android:elevation="4dp"
</FrameLayout> android:minHeight="?attr/actionBarSize"
android:paddingLeft="8dp"
android:paddingRight="8dp"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
android:visibility="@{!advanced &amp;&amp; (status == i.STATUS_LOADED) ? View.VISIBLE : View.GONE}"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
tools:ignore="UnusedAttribute">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/import_keys"
style="@style/TextAppearance.Widget.AppCompat.Toolbar.Subtitle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:drawablePadding="8dp"
android:drawableRight="@drawable/ic_file_download_white_24dp"
android:gravity="center_vertical"
android:text="@string/menu_import_all_keys"
android:textColor="#ffffffff" />
</RelativeLayout>
</android.support.v7.widget.Toolbar>
</RelativeLayout>
</layout> </layout>

View File

@@ -5,6 +5,7 @@
<import type="android.view.View" /> <import type="android.view.View" />
<import type="org.sufficientlysecure.keychain.keyimport.ImportKeysListEntry" /> <import type="org.sufficientlysecure.keychain.keyimport.ImportKeysListEntry" />
<variable name="advanced" type="boolean" />
<variable name="nonInteractive" type="boolean" /> <variable name="nonInteractive" type="boolean" />
<variable name="entry" type="ImportKeysListEntry" /> <variable name="entry" type="ImportKeysListEntry" />
</data> </data>
@@ -76,11 +77,17 @@
</LinearLayout> </LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingBottom="8dp"
android:visibility="@{(!advanced || nonInteractive) ? View.VISIBLE : View.GONE}" />
<RelativeLayout <RelativeLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:padding="8dp" android:padding="8dp"
android:visibility="@{nonInteractive ? View.GONE : View.VISIBLE}"> android:visibility="@{(!advanced || nonInteractive) ? View.GONE : View.VISIBLE}">
<Button <Button
android:id="@+id/import_key" android:id="@+id/import_key"
@@ -109,20 +116,27 @@
</RelativeLayout> </RelativeLayout>
<LinearLayout <LinearLayout
android:id="@+id/extra_container"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:animateLayoutChanges="true" android:visibility="@{advanced ? View.VISIBLE : View.GONE}">
android:orientation="vertical"
android:paddingBottom="24dp"
android:paddingLeft="16dp"
android:paddingRight="16dp"
android:paddingTop="16dp"
android:visibility="gone">
<include <LinearLayout
layout="@layout/import_keys_list_item_extra" android:id="@+id/extra_container"
app:entry="@{entry}" /> android:layout_width="match_parent"
android:layout_height="wrap_content"
android:animateLayoutChanges="true"
android:orientation="vertical"
android:paddingBottom="24dp"
android:paddingLeft="16dp"
android:paddingRight="16dp"
android:paddingTop="16dp"
android:visibility="gone">
<include
layout="@layout/import_keys_list_item_extra"
app:entry="@{entry}" />
</LinearLayout>
</LinearLayout> </LinearLayout>

View File

@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/basic"
android:title="@string/menu_basic" />
<item
android:id="@+id/advanced"
android:title="@string/menu_advanced" />
</menu>

View File

@@ -128,6 +128,7 @@
<string name="menu_select_all">"Select all"</string> <string name="menu_select_all">"Select all"</string>
<string name="menu_export_all_keys">"Export all keys"</string> <string name="menu_export_all_keys">"Export all keys"</string>
<string name="menu_update_all_keys">"Update all keys"</string> <string name="menu_update_all_keys">"Update all keys"</string>
<string name="menu_basic">"Basic"</string>
<string name="menu_advanced">"Advanced"</string> <string name="menu_advanced">"Advanced"</string>
<string name="menu_certify_fingerprint">"Confirm with fingerprint"</string> <string name="menu_certify_fingerprint">"Confirm with fingerprint"</string>
<string name="menu_certify_fingerprint_phrases">"Confirm with phrases"</string> <string name="menu_certify_fingerprint_phrases">"Confirm with phrases"</string>