import: simplify ImportKeysActivity, don't display search bar for fixed input

This commit is contained in:
Vincent Breitmoser 2015-09-30 03:11:54 +02:00
parent 4025acd13a
commit 43e661790d
2 changed files with 109 additions and 168 deletions

View file

@ -21,8 +21,8 @@ import android.app.Activity;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.os.Message;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
@ -33,10 +33,8 @@ import org.sufficientlysecure.keychain.intents.OpenKeychainIntents;
import org.sufficientlysecure.keychain.keyimport.ImportKeysListEntry;
import org.sufficientlysecure.keychain.keyimport.ParcelableKeyRing;
import org.sufficientlysecure.keychain.operations.results.ImportKeyResult;
import org.sufficientlysecure.keychain.operations.results.OperationResult;
import org.sufficientlysecure.keychain.service.ImportKeyringParcel;
import org.sufficientlysecure.keychain.ui.base.BaseNfcActivity;
import org.sufficientlysecure.keychain.service.ServiceProgressHandler;
import org.sufficientlysecure.keychain.ui.base.CryptoOperationHelper;
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
import org.sufficientlysecure.keychain.ui.util.Notify;
@ -78,10 +76,8 @@ public class ImportKeysActivity extends BaseNfcActivity
public static final String EXTRA_PENDING_INTENT_DATA = "data";
private Intent mPendingIntentData;
// view
private ImportKeysListFragment mListFragment;
private Fragment mTopFragment;
private View mImportButton;
public static final String TAG_FRAG_LIST = "frag_list";
public static final String TAG_FRAG_TOP = "frag_top";
// for CryptoOperationHelper.Callback
private String mKeyserver;
@ -94,15 +90,22 @@ public class ImportKeysActivity extends BaseNfcActivity
super.onCreate(savedInstanceState);
setFullScreenDialogClose(Activity.RESULT_CANCELED, true);
mImportButton = findViewById(R.id.import_import);
mImportButton.setOnClickListener(new OnClickListener() {
findViewById(R.id.import_import).setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
importKeys();
importSelectedKeys();
}
});
handleActions(savedInstanceState, getIntent());
// only used for OpenPgpService
if (getIntent().hasExtra(EXTRA_PENDING_INTENT_DATA)) {
mPendingIntentData = getIntent().getParcelableExtra(EXTRA_PENDING_INTENT_DATA);
}
// if we aren't being restored, initialize fragments
if (savedInstanceState == null) {
handleActions(getIntent());
}
}
@Override
@ -110,7 +113,7 @@ public class ImportKeysActivity extends BaseNfcActivity
setContentView(R.layout.import_keys_activity);
}
protected void handleActions(Bundle savedInstanceState, Intent intent) {
protected void handleActions(Intent intent) {
String action = intent.getAction();
Bundle extras = intent.getExtras();
Uri dataUri = intent.getData();
@ -120,14 +123,8 @@ public class ImportKeysActivity extends BaseNfcActivity
extras = new Bundle();
}
if (action == null) {
startCloudFragment(savedInstanceState, null, false, null);
startListFragment(savedInstanceState, null, null, null, null);
return;
}
if (Intent.ACTION_VIEW.equals(action)) {
if (scheme.equals("http") || scheme.equals("https")) {
if ("http".equals(scheme) || "https".equals(scheme)) {
action = ACTION_SEARCH_KEYSERVER_FROM_URL;
} else {
// Android's Action when opening file associated to Keychain (see AndroidManifest.xml)
@ -135,20 +132,24 @@ public class ImportKeysActivity extends BaseNfcActivity
action = ACTION_IMPORT_KEY;
}
}
if (action == null) {
// -> switch to default below
action = "";
}
switch (action) {
case ACTION_IMPORT_KEY: {
/* Keychain's own Actions */
startFileFragment(savedInstanceState);
if (dataUri != null) {
// action: directly load data
startListFragment(savedInstanceState, null, dataUri, null, null);
startListFragment(null, dataUri, null, null);
} else if (extras.containsKey(EXTRA_KEY_BYTES)) {
byte[] importData = extras.getByteArray(EXTRA_KEY_BYTES);
// action: directly load data
startListFragment(savedInstanceState, importData, null, null, null);
startListFragment(importData, null, null, null);
} else {
startTopFileFragment();
startListFragment(null, null, null, null);
}
break;
}
@ -156,10 +157,6 @@ public class ImportKeysActivity extends BaseNfcActivity
case ACTION_IMPORT_KEY_FROM_KEYSERVER_AND_RETURN_TO_SERVICE:
case ACTION_IMPORT_KEY_FROM_KEYSERVER_AND_RETURN_RESULT: {
// only used for OpenPgpService
if (extras.containsKey(EXTRA_PENDING_INTENT_DATA)) {
mPendingIntentData = extras.getParcelable(EXTRA_PENDING_INTENT_DATA);
}
if (extras.containsKey(EXTRA_QUERY) || extras.containsKey(EXTRA_KEY_ID)) {
/* simple search based on query or key id */
@ -175,10 +172,10 @@ public class ImportKeysActivity extends BaseNfcActivity
if (query != null && query.length() > 0) {
// display keyserver fragment with query
startCloudFragment(savedInstanceState, query, false, null);
startTopCloudFragment(query, false, null);
// action: search immediately
startListFragment(savedInstanceState, null, null, query, null);
startListFragment(null, null, query, null);
} else {
Log.e(Constants.TAG, "Query is empty!");
return;
@ -194,10 +191,10 @@ public class ImportKeysActivity extends BaseNfcActivity
String query = "0x" + fingerprint;
// display keyserver fragment with query
startCloudFragment(savedInstanceState, query, true, null);
startTopCloudFragment(query, true, null);
// action: search immediately
startListFragment(savedInstanceState, null, null, query, null);
startListFragment(null, null, query, null);
}
} else {
Log.e(Constants.TAG,
@ -208,14 +205,6 @@ public class ImportKeysActivity extends BaseNfcActivity
}
break;
}
case ACTION_IMPORT_KEY_FROM_FILE: {
// NOTE: this only displays the appropriate fragment, no actions are taken
startFileFragment(savedInstanceState);
// no immediate actions!
startListFragment(savedInstanceState, null, null, null, null);
break;
}
case ACTION_SEARCH_KEYSERVER_FROM_URL: {
// need to process URL to get search query and keyserver authority
String query = dataUri.getQueryParameter("search");
@ -223,120 +212,88 @@ public class ImportKeysActivity extends BaseNfcActivity
// if query not specified, we still allow users to search the keyserver in the link
if (query == null) {
Notify.create(this, R.string.import_url_warn_no_search_parameter, Notify.LENGTH_INDEFINITE,
Notify.Style.WARN).show(mTopFragment);
Notify.Style.WARN).show();
// we just set the keyserver
startCloudFragment(savedInstanceState, null, false, keyserver);
startTopCloudFragment(null, false, keyserver);
// we don't set the keyserver for ImportKeysListFragment since
// it'll be set in the cloudSearchPrefs of ImportKeysCloudFragment
// which is used when the user clicks on the search button
startListFragment(savedInstanceState, null, null, null, null);
startListFragment(null, null, null, null);
} else {
// we allow our users to edit the query if they wish
startCloudFragment(savedInstanceState, query, false, keyserver);
startTopCloudFragment(query, false, keyserver);
// search immediately
startListFragment(savedInstanceState, null, null, query, keyserver);
startListFragment(null, null, query, keyserver);
}
break;
}
case ACTION_IMPORT_KEY_FROM_FILE:
case ACTION_IMPORT_KEY_FROM_FILE_AND_RETURN: {
// NOTE: this only displays the appropriate fragment, no actions are taken
startFileFragment(savedInstanceState);
// no immediate actions!
startListFragment(savedInstanceState, null, null, null, null);
startTopFileFragment();
startListFragment(null, null, null, null);
break;
}
default: {
startCloudFragment(savedInstanceState, null, false, null);
startListFragment(savedInstanceState, null, null, null, null);
startTopCloudFragment(null, false, null);
startListFragment(null, null, null, null);
break;
}
}
}
@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
// the only thing we need to take care of for restoring state is
// that the top layout is shown iff it contains a fragment
Fragment topFragment = getSupportFragmentManager().findFragmentByTag(TAG_FRAG_TOP);
boolean hasTopFragment = topFragment != null;
findViewById(R.id.import_keys_top_layout).setVisibility(hasTopFragment ? View.VISIBLE : View.GONE);
}
/**
* if the fragment is started with non-null bytes/dataUri/serverQuery, it will immediately
* load content
*
* @param savedInstanceState
* @param bytes bytes containing list of keyrings to import
* @param dataUri uri to file to import keyrings from
* @param serverQuery query to search for on the keyserver
* @param keyserver keyserver authority to search on. If null will use keyserver from
* user preferences
*/
private void startListFragment(Bundle savedInstanceState, byte[] bytes, Uri dataUri,
String serverQuery, String keyserver) {
// However, if we're being restored from a previous state,
// then we don't need to do anything and should return or else
// we could end up with overlapping fragments.
if (mListFragment != null) {
return;
}
mListFragment = ImportKeysListFragment.newInstance(bytes, dataUri, serverQuery, false,
keyserver);
// Add the fragment to the 'fragment_container' FrameLayout
// NOTE: We use commitAllowingStateLoss() to prevent weird crashes!
private void startListFragment(byte[] bytes, Uri dataUri, String serverQuery, String keyserver) {
Fragment listFragment =
ImportKeysListFragment.newInstance(bytes, dataUri, serverQuery, false, keyserver);
getSupportFragmentManager().beginTransaction()
.replace(R.id.import_keys_list_container, mListFragment)
.commitAllowingStateLoss();
// do it immediately!
getSupportFragmentManager().executePendingTransactions();
.replace(R.id.import_keys_list_container, listFragment, TAG_FRAG_LIST)
.commit();
}
private void startFileFragment(Bundle savedInstanceState) {
// However, if we're being restored from a previous state,
// then we don't need to do anything and should return or else
// we could end up with overlapping fragments.
if (mTopFragment != null) {
return;
}
// Create an instance of the fragment
mTopFragment = ImportKeysFileFragment.newInstance();
// Add the fragment to the 'fragment_container' FrameLayout
// NOTE: We use commitAllowingStateLoss() to prevent weird crashes!
private void startTopFileFragment() {
findViewById(R.id.import_keys_top_layout).setVisibility(View.VISIBLE);
Fragment importFileFragment = ImportKeysFileFragment.newInstance();
getSupportFragmentManager().beginTransaction()
.replace(R.id.import_keys_top_container, mTopFragment)
.commitAllowingStateLoss();
// do it immediately!
getSupportFragmentManager().executePendingTransactions();
.replace(R.id.import_keys_top_container, importFileFragment, TAG_FRAG_TOP)
.commit();
}
/**
* loads the CloudFragment, which consists of the search bar, search button and settings icon
* visually.
*
* @param savedInstanceState
* @param query search query
* @param disableQueryEdit if true, user will not be able to edit the search query
* @param keyserver keyserver authority to use for search, if null will use keyserver
* specified in user preferences
*/
private void startCloudFragment(Bundle savedInstanceState, String query, boolean disableQueryEdit, String
keyserver) {
// However, if we're being restored from a previous state,
// then we don't need to do anything and should return or else
// we could end up with overlapping fragments.
if (mTopFragment != null) {
return;
}
// Create an instance of the fragment
mTopFragment = ImportKeysCloudFragment.newInstance(query, disableQueryEdit, keyserver);
// Add the fragment to the 'fragment_container' FrameLayout
// NOTE: We use commitAllowingStateLoss() to prevent weird crashes!
private void startTopCloudFragment(String query, boolean disableQueryEdit, String keyserver) {
findViewById(R.id.import_keys_top_layout).setVisibility(View.VISIBLE);
Fragment importCloudFragment = ImportKeysCloudFragment.newInstance(query, disableQueryEdit, keyserver);
getSupportFragmentManager().beginTransaction()
.replace(R.id.import_keys_top_container, mTopFragment)
.commitAllowingStateLoss();
// do it immediately!
getSupportFragmentManager().executePendingTransactions();
.replace(R.id.import_keys_top_container, importCloudFragment, TAG_FRAG_TOP)
.commit();
}
private boolean isFingerprintValid(String fingerprint) {
@ -350,63 +307,32 @@ public class ImportKeysActivity extends BaseNfcActivity
}
public void loadCallback(final ImportKeysListFragment.LoaderState loaderState) {
mListFragment.loadNew(loaderState);
FragmentManager fragMan = getSupportFragmentManager();
ImportKeysListFragment keyListFragment = (ImportKeysListFragment) fragMan.findFragmentByTag(TAG_FRAG_LIST);
keyListFragment.loadNew(loaderState);
}
private void handleMessage(Message message) {
if (message.arg1 == ServiceProgressHandler.MessageStatus.OKAY.ordinal()) {
// get returned data bundle
Bundle returnData = message.getData();
if (returnData == null) {
return;
}
final ImportKeyResult result =
returnData.getParcelable(OperationResult.EXTRA_RESULT);
if (result == null) {
Log.e(Constants.TAG, "result == null");
return;
}
private void importSelectedKeys() {
if (ACTION_IMPORT_KEY_FROM_KEYSERVER_AND_RETURN_RESULT.equals(getIntent().getAction())
|| ACTION_IMPORT_KEY_FROM_FILE_AND_RETURN.equals(getIntent().getAction())) {
Intent intent = new Intent();
intent.putExtra(ImportKeyResult.EXTRA_RESULT, result);
ImportKeysActivity.this.setResult(RESULT_OK, intent);
ImportKeysActivity.this.finish();
return;
}
if (ACTION_IMPORT_KEY_FROM_KEYSERVER_AND_RETURN_TO_SERVICE.equals(getIntent().getAction())) {
ImportKeysActivity.this.setResult(RESULT_OK, mPendingIntentData);
ImportKeysActivity.this.finish();
return;
}
FragmentManager fragMan = getSupportFragmentManager();
ImportKeysListFragment keyListFragment = (ImportKeysListFragment) fragMan.findFragmentByTag(TAG_FRAG_LIST);
result.createNotify(ImportKeysActivity.this)
.show((ViewGroup) findViewById(R.id.import_snackbar));
}
}
/**
* Import keys with mImportData
*/
public void importKeys() {
if (mListFragment.getSelectedEntries().size() == 0) {
if (keyListFragment.getSelectedEntries().size() == 0) {
Notify.create(this, R.string.error_nothing_import_selected, Notify.Style.ERROR)
.show((ViewGroup) findViewById(R.id.import_snackbar));
return;
}
mOperationHelper = new CryptoOperationHelper<ImportKeyringParcel, ImportKeyResult>(
mOperationHelper = new CryptoOperationHelper<>(
1, this, this, R.string.progress_importing
);
ImportKeysListFragment.LoaderState ls = mListFragment.getLoaderState();
ImportKeysListFragment.LoaderState ls = keyListFragment.getLoaderState();
if (ls instanceof ImportKeysListFragment.BytesLoaderState) {
Log.d(Constants.TAG, "importKeys started");
// get DATA from selected key entries
IteratorWithSize<ParcelableKeyRing> selectedEntries = mListFragment.getSelectedData();
IteratorWithSize<ParcelableKeyRing> selectedEntries = keyListFragment.getSelectedData();
// instead of giving the entries by Intent extra, cache them into a
// file to prevent Java Binder problems on heavy imports
@ -435,7 +361,7 @@ public class ImportKeysActivity extends BaseNfcActivity
ArrayList<ParcelableKeyRing> keys = new ArrayList<>();
{
// change the format into ParcelableKeyRing
ArrayList<ImportKeysListEntry> entries = mListFragment.getSelectedEntries();
ArrayList<ImportKeysListEntry> entries = keyListFragment.getSelectedEntries();
for (ImportKeysListEntry entry : entries) {
keys.add(new ParcelableKeyRing(
entry.getFingerprintHex(), entry.getKeyIdHex(), entry.getExtraData())
@ -458,24 +384,28 @@ public class ImportKeysActivity extends BaseNfcActivity
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (mOperationHelper == null ||
!mOperationHelper.handleActivityResult(requestCode, resultCode, data)) {
super.onActivityResult(requestCode, resultCode, data);
if (mOperationHelper != null &&
mOperationHelper.handleActivityResult(requestCode, resultCode, data)) {
return;
}
super.onActivityResult(requestCode, resultCode, data);
}
public void handleResult(ImportKeyResult result) {
if (ACTION_IMPORT_KEY_FROM_KEYSERVER_AND_RETURN_RESULT.equals(getIntent().getAction())
|| ACTION_IMPORT_KEY_FROM_FILE_AND_RETURN.equals(getIntent().getAction())) {
String intentAction = getIntent().getAction();
if (ACTION_IMPORT_KEY_FROM_KEYSERVER_AND_RETURN_RESULT.equals(intentAction)
|| ACTION_IMPORT_KEY_FROM_FILE_AND_RETURN.equals(intentAction)) {
Intent intent = new Intent();
intent.putExtra(ImportKeyResult.EXTRA_RESULT, result);
ImportKeysActivity.this.setResult(RESULT_OK, intent);
ImportKeysActivity.this.finish();
setResult(RESULT_OK, intent);
finish();
return;
}
if (ACTION_IMPORT_KEY_FROM_KEYSERVER_AND_RETURN_TO_SERVICE.equals(getIntent().getAction())) {
ImportKeysActivity.this.setResult(RESULT_OK, mPendingIntentData);
ImportKeysActivity.this.finish();
if (ACTION_IMPORT_KEY_FROM_KEYSERVER_AND_RETURN_TO_SERVICE.equals(intentAction)) {
setResult(RESULT_OK, mPendingIntentData);
finish();
return;
}

View file

@ -1,7 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
android:layout_height="match_parent"
xmlns:tools="http://schemas.android.com/tools">
<include
android:id="@+id/toolbar_include"
@ -21,16 +22,26 @@
<include layout="@layout/notify_area" />
<FrameLayout
android:id="@+id/import_keys_top_container"
<LinearLayout
android:layout_width="match_parent"
android:layout_height="64dp"
android:orientation="vertical" />
android:layout_height="wrap_content"
android:orientation="vertical"
android:id="@+id/import_keys_top_layout"
android:visibility="gone"
tools:visibility="visible">
<View
android:layout_width="match_parent"
android:layout_height="1dip"
android:background="?android:attr/listDivider" />
<FrameLayout
android:id="@+id/import_keys_top_container"
android:layout_width="match_parent"
android:layout_height="64dp"
android:orientation="vertical" />
<View
android:layout_width="match_parent"
android:layout_height="1dip"
android:background="?android:attr/listDivider" />
</LinearLayout>
<FrameLayout
android:id="@+id/import_keys_list_container"