Redesign Import, still some todos and regression bugs

This commit is contained in:
Dominik Schürmann
2014-06-18 00:03:06 +02:00
parent 21e9d0b7b4
commit 8c7a360d6e
34 changed files with 1204 additions and 460 deletions

View File

@@ -17,6 +17,7 @@
package org.sufficientlysecure.keychain.helper;
import android.content.Context;
import android.os.Bundle;
import android.text.SpannableStringBuilder;
import android.text.Spanned;
@@ -67,4 +68,12 @@ public class OtherHelper {
return sb;
}
public static int dpToPx(Context context, int dp) {
return (int) ((dp * context.getResources().getDisplayMetrics().density) + 0.5);
}
public static int pxToDp(Context context, int px) {
return (int) ((px / context.getResources().getDisplayMetrics().density) + 0.5);
}
}

View File

@@ -32,10 +32,14 @@ import android.os.Messenger;
import android.os.Parcelable;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentTransaction;
import android.support.v4.view.ViewPager;
import android.support.v7.app.ActionBar;
import android.support.v7.app.ActionBarActivity;
import android.util.DisplayMetrics;
import android.util.TypedValue;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import com.github.johnpersano.supertoasts.SuperCardToast;
@@ -45,18 +49,22 @@ import com.github.johnpersano.supertoasts.util.Style;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.helper.OtherHelper;
import org.sufficientlysecure.keychain.keyimport.ImportKeysListEntry;
import org.sufficientlysecure.keychain.keyimport.KeybaseKeyserver;
import org.sufficientlysecure.keychain.keyimport.ParcelableKeyRing;
import org.sufficientlysecure.keychain.pgp.PgpKeyHelper;
import org.sufficientlysecure.keychain.service.KeychainIntentService;
import org.sufficientlysecure.keychain.service.KeychainIntentServiceHandler;
import org.sufficientlysecure.keychain.service.OperationResults.ImportResult;
import org.sufficientlysecure.keychain.ui.adapter.PagerTabStripAdapter;
import org.sufficientlysecure.keychain.ui.widget.SlidingTabLayout;
import org.sufficientlysecure.keychain.util.Log;
import java.util.ArrayList;
import java.util.Locale;
public class ImportKeysActivity extends ActionBarActivity implements ActionBar.OnNavigationListener {
public class ImportKeysActivity extends ActionBarActivity {
public static final String ACTION_IMPORT_KEY = Constants.INTENT_PREFIX + "IMPORT_KEY";
public static final String ACTION_IMPORT_KEY_FROM_QR_CODE = Constants.INTENT_PREFIX
+ "IMPORT_KEY_FROM_QR_CODE";
@@ -90,23 +98,18 @@ public class ImportKeysActivity extends ActionBarActivity implements ActionBar.O
private String[] mNavigationStrings;
private Fragment mCurrentFragment;
private View mImportButton;
private ViewPager mViewPager;
private SlidingTabLayout mSlidingTabLayout;
private PagerTabStripAdapter mTabsAdapter;
public static final int VIEW_PAGER_HEIGHT = 64; // dp
private static final Class[] NAVIGATION_CLASSES = new Class[]{
ImportKeysServerFragment.class,
ImportKeysFileFragment.class,
ImportKeysQrCodeFragment.class,
ImportKeysClipboardFragment.class,
ImportKeysNFCFragment.class,
ImportKeysKeybaseFragment.class
};
private static final int NAV_SERVER = 0;
private static final int NAV_FILE = 1;
private static final int NAV_QR_CODE = 2;
private static final int NAV_CLIPBOARD = 3;
private static final int NAV_NFC = 4;
private static final int NAV_KEYBASE = 5;
private static final int NAV_QR_CODE = 1;
private static final int NAV_FILE = 2;
private static final int NAV_KEYBASE = 3;
private int mCurrentNavPosition = -1;
private int mSwitchToTab = NAV_SERVER;
@Override
protected void onCreate(Bundle savedInstanceState) {
@@ -114,6 +117,9 @@ public class ImportKeysActivity extends ActionBarActivity implements ActionBar.O
setContentView(R.layout.import_keys_activity);
mViewPager = (ViewPager) findViewById(R.id.import_pager);
mSlidingTabLayout = (SlidingTabLayout) findViewById(R.id.import_sliding_tab_layout);
mImportButton = findViewById(R.id.import_import);
mImportButton.setOnClickListener(new OnClickListener() {
@Override
@@ -127,18 +133,55 @@ public class ImportKeysActivity extends ActionBarActivity implements ActionBar.O
if (ACTION_IMPORT_KEY_FROM_KEYSERVER_AND_RETURN.equals(getIntent().getAction())) {
setTitle(R.string.nav_import);
} else {
getSupportActionBar().setDisplayShowTitleEnabled(false);
// set drop down navigation
Context context = getSupportActionBar().getThemedContext();
ArrayAdapter<CharSequence> navigationAdapter = ArrayAdapter.createFromResource(context,
R.array.import_action_list, android.R.layout.simple_spinner_dropdown_item);
getSupportActionBar().setNavigationMode(ActionBar.NAVIGATION_MODE_LIST);
getSupportActionBar().setListNavigationCallbacks(navigationAdapter, this);
initTabs();
}
handleActions(savedInstanceState, getIntent());
}
private void initTabs() {
mTabsAdapter = new PagerTabStripAdapter(this);
mViewPager.setAdapter(mTabsAdapter);
mSlidingTabLayout.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
// resize view pager back to 64 if keyserver settings have been collapsed
if (getViewPagerHeight() > VIEW_PAGER_HEIGHT) {
resizeViewPager(VIEW_PAGER_HEIGHT);
}
}
@Override
public void onPageSelected(int position) {
}
@Override
public void onPageScrollStateChanged(int state) {
}
});
Bundle serverBundle = new Bundle();
// serverBundle.putParcelable(ViewKeyMainFragment.ARG_DATA_URI, dataUri);
mTabsAdapter.addTab(ImportKeysServerFragment.class,
serverBundle, getString(R.string.import_tab_keyserver));
Bundle qrCodeBundle = new Bundle();
// importBundle.putParcelable(ViewKeyMainFragment.ARG_DATA_URI, dataUri);
mTabsAdapter.addTab(ImportKeysQrCodeFragment.class,
qrCodeBundle, getString(R.string.import_tab_qr_code));
Bundle fileBundle = new Bundle();
// importBundle.putParcelable(ViewKeyMainFragment.ARG_DATA_URI, dataUri);
mTabsAdapter.addTab(ImportKeysFileFragment.class,
fileBundle, getString(R.string.import_tab_direct));
Bundle keybaseBundle = new Bundle();
// keybaseBundle.putParcelable(ViewKeyMainFragment.ARG_DATA_URI, dataUri);
mTabsAdapter.addTab(ImportKeysKeybaseFragment.class,
keybaseBundle, getString(R.string.import_tab_keybase));
// update layout after operations
mSlidingTabLayout.setViewPager(mViewPager);
}
protected void handleActions(Bundle savedInstanceState, Intent intent) {
@@ -164,7 +207,7 @@ public class ImportKeysActivity extends ActionBarActivity implements ActionBar.O
/* Keychain's own Actions */
// display file fragment
loadNavFragment(NAV_FILE, null);
mViewPager.setCurrentItem(NAV_FILE);
if (dataUri != null) {
// action: directly load data
@@ -199,7 +242,9 @@ public class ImportKeysActivity extends ActionBarActivity implements ActionBar.O
// display keyserver fragment with query
Bundle args = new Bundle();
args.putString(ImportKeysServerFragment.ARG_QUERY, query);
loadNavFragment(NAV_SERVER, args);
// loadNavFragment(NAV_SERVER, args);
//TODO: load afterwards!
mSwitchToTab = NAV_SERVER;
// action: search immediately
startListFragment(savedInstanceState, null, null, query);
@@ -223,9 +268,8 @@ public class ImportKeysActivity extends ActionBarActivity implements ActionBar.O
return;
}
} else if (ACTION_IMPORT_KEY_FROM_FILE.equals(action)) {
// NOTE: this only displays the appropriate fragment, no actions are taken
loadNavFragment(NAV_FILE, null);
mSwitchToTab = NAV_FILE;
// no immediate actions!
startListFragment(savedInstanceState, null, null, null);
@@ -233,26 +277,28 @@ public class ImportKeysActivity extends ActionBarActivity implements ActionBar.O
// also exposed in AndroidManifest
// NOTE: this only displays the appropriate fragment, no actions are taken
loadNavFragment(NAV_QR_CODE, null);
mSwitchToTab = NAV_QR_CODE;
// no immediate actions!
startListFragment(savedInstanceState, null, null, null);
} else if (ACTION_IMPORT_KEY_FROM_NFC.equals(action)) {
// NOTE: this only displays the appropriate fragment, no actions are taken
loadNavFragment(NAV_NFC, null);
mSwitchToTab = NAV_QR_CODE;
// no immediate actions!
startListFragment(savedInstanceState, null, null, null);
} else if (ACTION_IMPORT_KEY_FROM_KEYBASE.equals(action)) {
// NOTE: this only displays the appropriate fragment, no actions are taken
loadNavFragment(NAV_KEYBASE, null);
mSwitchToTab = NAV_KEYBASE;
// no immediate actions!
startListFragment(savedInstanceState, null, null, null);
} else {
startListFragment(savedInstanceState, null, null, null);
}
mViewPager.setCurrentItem(mSwitchToTab);
}
private void startListFragment(Bundle savedInstanceState, byte[] bytes, Uri dataUri, String serverQuery) {
@@ -275,54 +321,16 @@ public class ImportKeysActivity extends ActionBarActivity implements ActionBar.O
getSupportFragmentManager().executePendingTransactions();
}
/**
* "Basically, when using a list navigation, onNavigationItemSelected() is automatically
* called when your activity is created/re-created, whether you like it or not. To prevent
* your Fragment's onCreateView() from being called twice, this initial automatic call to
* onNavigationItemSelected() should check whether the Fragment is already in existence
* inside your Activity."
* <p/>
* from http://stackoverflow.com/a/14295474
* <p/>
* In our case, if we start ImportKeysActivity with parameters to directly search using a fingerprint,
* the fragment would be loaded twice resulting in the query being empty after the second load.
* <p/>
* Our solution:
* To prevent that a fragment will be loaded again even if it was already loaded loadNavFragment
* checks against mCurrentNavPosition.
*
* @param itemPosition
* @param itemId
* @return
*/
@Override
public boolean onNavigationItemSelected(int itemPosition, long itemId) {
Log.d(Constants.TAG, "onNavigationItemSelected");
loadNavFragment(itemPosition, null);
return true;
public void resizeViewPager(int dp) {
ViewGroup.LayoutParams params = mViewPager.getLayoutParams();
params.height = OtherHelper.dpToPx(this, dp);
// update layout after operations
mSlidingTabLayout.setViewPager(mViewPager);
}
private void loadNavFragment(int itemPosition, Bundle args) {
if (mCurrentNavPosition != itemPosition) {
if (ActionBar.NAVIGATION_MODE_LIST == getSupportActionBar().getNavigationMode()) {
getSupportActionBar().setSelectedNavigationItem(itemPosition);
}
loadFragment(NAVIGATION_CLASSES[itemPosition], args, mNavigationStrings[itemPosition]);
mCurrentNavPosition = itemPosition;
}
}
private void loadFragment(Class<?> clss, Bundle args, String tag) {
mCurrentFragment = Fragment.instantiate(this, clss.getName(), args);
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
// Replace whatever is in the fragment container with this fragment
// and give the fragment a tag name equal to the string at the position selected
ft.replace(R.id.import_navigation_fragment, mCurrentFragment, tag);
// Apply changes
ft.commit();
public int getViewPagerHeight() {
ViewGroup.LayoutParams params = mViewPager.getLayoutParams();
return OtherHelper.pxToDp(this, params.height);
}
public void loadFromFingerprintUri(Bundle savedInstanceState, Uri dataUri) {
@@ -349,7 +357,9 @@ public class ImportKeysActivity extends ActionBarActivity implements ActionBar.O
Bundle args = new Bundle();
args.putString(ImportKeysServerFragment.ARG_QUERY, query);
args.putBoolean(ImportKeysServerFragment.ARG_DISABLE_QUERY_EDIT, true);
loadNavFragment(NAV_SERVER, args);
// loadNavFragment(NAV_SERVER, args);
//TODO
// action: search directly
startListFragment(savedInstanceState, null, null, query);
@@ -437,15 +447,16 @@ public class ImportKeysActivity extends ActionBarActivity implements ActionBar.O
toast.setButtonTextColor(getResources().getColor(R.color.black));
toast.setTextColor(getResources().getColor(R.color.black));
toast.setOnClickWrapper(new OnClickWrapper("supercardtoast",
new SuperToast.OnClickListener() {
@Override
public void onClick(View view, Parcelable token) {
Intent intent = new Intent(
ImportKeysActivity.this, LogDisplayActivity.class);
intent.putExtra(LogDisplayFragment.EXTRA_RESULT, result);
startActivity(intent);
new SuperToast.OnClickListener() {
@Override
public void onClick(View view, Parcelable token) {
Intent intent = new Intent(
ImportKeysActivity.this, LogDisplayActivity.class);
intent.putExtra(LogDisplayFragment.EXTRA_RESULT, result);
startActivity(intent);
}
}
}));
));
toast.show();
/*
@@ -560,9 +571,12 @@ public class ImportKeysActivity extends ActionBarActivity implements ActionBar.O
super.onResume();
// Check to see if the Activity started due to an Android Beam
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN
&& NfcAdapter.ACTION_NDEF_DISCOVERED.equals(getIntent().getAction())) {
handleActionNdefDiscovered(getIntent());
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(getIntent().getAction())) {
handleActionNdefDiscovered(getIntent());
} else {
Log.d(Constants.TAG, "NFC: No NDEF discovered!");
}
} else {
Log.e(Constants.TAG, "Android Beam not supported by Android < 4.1");
}

View File

@@ -1,88 +0,0 @@
/*
* Copyright (C) 2013-2014 Dominik Schürmann <dominik@dominikschuermann.de>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.sufficientlysecure.keychain.ui;
import android.net.Uri;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import com.beardedhen.androidbootstrap.BootstrapButton;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.compatibility.ClipboardReflection;
import java.util.Locale;
public class ImportKeysClipboardFragment extends Fragment {
private ImportKeysActivity mImportActivity;
private BootstrapButton mButton;
/**
* Creates new instance of this fragment
*/
public static ImportKeysClipboardFragment newInstance() {
ImportKeysClipboardFragment frag = new ImportKeysClipboardFragment();
Bundle args = new Bundle();
frag.setArguments(args);
return frag;
}
/**
* Inflate the layout for this fragment
*/
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.import_keys_clipboard_fragment, container, false);
mButton = (BootstrapButton) view.findViewById(R.id.import_clipboard_button);
mButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
CharSequence clipboardText = ClipboardReflection.getClipboardText(getActivity());
String sendText = "";
if (clipboardText != null) {
sendText = clipboardText.toString();
if (sendText.toLowerCase(Locale.ENGLISH).startsWith(Constants.FINGERPRINT_SCHEME)) {
mImportActivity.loadFromFingerprintUri(null, Uri.parse(sendText));
return;
}
}
mImportActivity.loadCallback(sendText.getBytes(), null, null, null, null);
}
});
return view;
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
mImportActivity = (ImportKeysActivity) getActivity();
}
}

View File

@@ -19,21 +19,24 @@ package org.sufficientlysecure.keychain.ui;
import android.app.Activity;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.beardedhen.androidbootstrap.BootstrapButton;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.compatibility.ClipboardReflection;
import org.sufficientlysecure.keychain.helper.FileHelper;
import java.util.Locale;
public class ImportKeysFileFragment extends Fragment {
private ImportKeysActivity mImportActivity;
private BootstrapButton mBrowse;
private View mBrowse;
private View mClipboardButton;
public static final int REQUEST_CODE_FILE = 0x00007003;
@@ -56,26 +59,45 @@ public class ImportKeysFileFragment extends Fragment {
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.import_keys_file_fragment, container, false);
mBrowse = (BootstrapButton) view.findViewById(R.id.import_keys_file_browse);
mBrowse = view.findViewById(R.id.import_keys_file_browse);
mBrowse.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
// open .asc or .gpg files
// setting it to text/plain prevents Cynaogenmod's file manager from selecting asc
// setting it to text/plain prevents Cyanogenmod's file manager from selecting asc
// or gpg types!
FileHelper.openFile(ImportKeysFileFragment.this, Constants.Path.APP_DIR + "/",
"*/*", REQUEST_CODE_FILE);
}
});
mClipboardButton = view.findViewById(R.id.import_clipboard_button);
mClipboardButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
CharSequence clipboardText = ClipboardReflection.getClipboardText(getActivity());
String sendText = "";
if (clipboardText != null) {
sendText = clipboardText.toString();
if (sendText.toLowerCase(Locale.ENGLISH).startsWith(Constants.FINGERPRINT_SCHEME)) {
mImportActivity.loadFromFingerprintUri(null, Uri.parse(sendText));
return;
}
}
mImportActivity.loadCallback(sendText.getBytes(), null, null, null, null);
}
});
return view;
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
public void onAttach(Activity activity) {
super.onAttach(activity);
mImportActivity = (ImportKeysActivity) getActivity();
mImportActivity = (ImportKeysActivity) activity;
}
@Override

View File

@@ -17,6 +17,7 @@
package org.sufficientlysecure.keychain.ui;
import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.support.v4.app.Fragment;
@@ -29,8 +30,6 @@ import android.view.inputmethod.InputMethodManager;
import android.widget.EditText;
import android.widget.TextView;
import com.beardedhen.androidbootstrap.BootstrapButton;
import org.sufficientlysecure.keychain.R;
/**
@@ -40,7 +39,7 @@ import org.sufficientlysecure.keychain.R;
public class ImportKeysKeybaseFragment extends Fragment {
private ImportKeysActivity mImportActivity;
private BootstrapButton mSearchButton;
private View mSearchButton;
private EditText mQueryEditText;
public static final String ARG_QUERY = "query";
@@ -66,7 +65,7 @@ public class ImportKeysKeybaseFragment extends Fragment {
mQueryEditText = (EditText) view.findViewById(R.id.import_keybase_query);
mSearchButton = (BootstrapButton) view.findViewById(R.id.import_keybase_search);
mSearchButton = view.findViewById(R.id.import_keybase_search);
mSearchButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
@@ -101,8 +100,6 @@ public class ImportKeysKeybaseFragment extends Fragment {
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
mImportActivity = (ImportKeysActivity) getActivity();
// set displayed values
if (getArguments() != null) {
if (getArguments().containsKey(ARG_QUERY)) {
@@ -112,6 +109,13 @@ public class ImportKeysKeybaseFragment extends Fragment {
}
}
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
mImportActivity = (ImportKeysActivity) activity;
}
private void search(String query) {
mImportActivity.loadCallback(null, null, null, null, query);
}

View File

@@ -42,6 +42,7 @@ import org.sufficientlysecure.keychain.ui.adapter.ImportKeysListLoader;
import org.sufficientlysecure.keychain.ui.adapter.ImportKeysListServerLoader;
import org.sufficientlysecure.keychain.util.InputData;
import org.sufficientlysecure.keychain.util.Log;
import org.sufficientlysecure.keychain.util.Notify;
import java.io.ByteArrayInputStream;
import java.io.FileNotFoundException;
@@ -97,7 +98,7 @@ public class ImportKeysListFragment extends ListFragment implements
public ArrayList<ParcelableKeyRing> getSelectedData() {
ArrayList<ParcelableKeyRing> result = new ArrayList<ParcelableKeyRing>();
for(ImportKeysListEntry entry : getSelectedEntries()) {
for (ImportKeysListEntry entry : getSelectedEntries()) {
result.add(mCachedKeyData.get(entry.getKeyId()));
}
return result;
@@ -273,17 +274,15 @@ public class ImportKeysListFragment extends ListFragment implements
// No error
mCachedKeyData = ((ImportKeysListLoader) loader).getParcelableRings();
} else if (error instanceof ImportKeysListLoader.FileHasNoContent) {
AppMsg.makeText(getActivity(), R.string.error_import_file_no_content,
AppMsg.STYLE_ALERT).show();
Notify.showNotify(getActivity(), R.string.error_import_file_no_content, Notify.Style.ERROR);
} else if (error instanceof ImportKeysListLoader.NonPgpPart) {
AppMsg.makeText(getActivity(),
Notify.showNotify(getActivity(),
((ImportKeysListLoader.NonPgpPart) error).getCount() + " " + getResources().
getQuantityString(R.plurals.error_import_non_pgp_part,
((ImportKeysListLoader.NonPgpPart) error).getCount()),
new AppMsg.Style(AppMsg.LENGTH_LONG, R.color.confirm)).show();
Notify.Style.OK);
} else {
AppMsg.makeText(getActivity(), R.string.error_generic_report_bug,
new AppMsg.Style(AppMsg.LENGTH_LONG, R.color.alert)).show();
Notify.showNotify(getActivity(), R.string.error_generic_report_bug, Notify.Style.ERROR);
}
break;
@@ -292,23 +291,17 @@ public class ImportKeysListFragment extends ListFragment implements
// TODO: possibly fine-tune message building for these two cases
if (error == null) {
AppMsg.makeText(
getActivity(), getResources().getQuantityString(R.plurals.keys_found,
mAdapter.getCount(), mAdapter.getCount()),
AppMsg.STYLE_INFO
).show();
// No error
} else if (error instanceof Keyserver.QueryTooShortException) {
AppMsg.makeText(getActivity(), R.string.error_keyserver_insufficient_query,
AppMsg.STYLE_ALERT).show();
Notify.showNotify(getActivity(), R.string.error_keyserver_insufficient_query, Notify.Style.ERROR);
} else if (error instanceof Keyserver.TooManyResponsesException) {
AppMsg.makeText(getActivity(), R.string.error_keyserver_too_many_responses,
AppMsg.STYLE_ALERT).show();
Notify.showNotify(getActivity(), R.string.error_keyserver_too_many_responses, Notify.Style.ERROR);
} else if (error instanceof Keyserver.QueryFailedException) {
Log.d(Constants.TAG,
"Unrecoverable keyserver query error: " + error.getLocalizedMessage());
String alert = getActivity().getString(R.string.error_searching_keys);
alert = alert + " (" + error.getLocalizedMessage() + ")";
AppMsg.makeText(getActivity(), alert, AppMsg.STYLE_ALERT).show();
Notify.showNotify(getActivity(), alert, Notify.Style.ERROR);
}
break;

View File

@@ -1,70 +0,0 @@
/*
* Copyright (C) 2013-2014 Dominik Schürmann <dominik@dominikschuermann.de>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.sufficientlysecure.keychain.ui;
import android.content.Intent;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import com.beardedhen.androidbootstrap.BootstrapButton;
import org.sufficientlysecure.keychain.R;
public class ImportKeysNFCFragment extends Fragment {
private BootstrapButton mButton;
/**
* Creates new instance of this fragment
*/
public static ImportKeysNFCFragment newInstance() {
ImportKeysNFCFragment frag = new ImportKeysNFCFragment();
Bundle args = new Bundle();
frag.setArguments(args);
return frag;
}
/**
* Inflate the layout for this fragment
*/
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.import_keys_nfc_fragment, container, false);
mButton = (BootstrapButton) view.findViewById(R.id.import_nfc_button);
mButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// show nfc help
Intent intent = new Intent(getActivity(), HelpActivity.class);
intent.putExtra(HelpActivity.EXTRA_SELECTED_TAB, HelpActivity.TAB_NFC);
startActivityForResult(intent, 0);
}
});
return view;
}
}

View File

@@ -17,47 +17,47 @@
package org.sufficientlysecure.keychain.ui;
import android.app.Activity;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.ProgressBar;
import android.widget.TextView;
import com.beardedhen.androidbootstrap.BootstrapButton;
import com.devspark.appmsg.AppMsg;
import com.google.zxing.integration.android.IntentResult;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.util.IntentIntegratorSupportV4;
import org.sufficientlysecure.keychain.util.Log;
import org.sufficientlysecure.keychain.util.Notify;
import java.util.ArrayList;
import java.util.Locale;
public class ImportKeysQrCodeFragment extends Fragment {
private ImportKeysActivity mImportActivity;
private BootstrapButton mButton;
private TextView mText;
private ProgressBar mProgress;
private View mNfcButton;
private String[] mScannedContent;
private View mQrCodeButton;
private TextView mQrCodeText;
private ProgressBar mQrCodeProgress;
private String[] mQrCodeContent;
/**
* Creates new instance of this fragment
*/
public static ImportKeysQrCodeFragment newInstance() {
ImportKeysQrCodeFragment frag = new ImportKeysQrCodeFragment();
public static ImportKeysFileFragment newInstance() {
ImportKeysFileFragment frag = new ImportKeysFileFragment();
Bundle args = new Bundle();
frag.setArguments(args);
frag.setArguments(args);
return frag;
}
@@ -68,11 +68,23 @@ public class ImportKeysQrCodeFragment extends Fragment {
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.import_keys_qr_code_fragment, container, false);
mButton = (BootstrapButton) view.findViewById(R.id.import_qrcode_button);
mText = (TextView) view.findViewById(R.id.import_qrcode_text);
mProgress = (ProgressBar) view.findViewById(R.id.import_qrcode_progress);
mNfcButton = view.findViewById(R.id.import_nfc_button);
mNfcButton.setOnClickListener(new View.OnClickListener() {
mButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// show nfc help
Intent intent = new Intent(getActivity(), HelpActivity.class);
intent.putExtra(HelpActivity.EXTRA_SELECTED_TAB, HelpActivity.TAB_NFC);
startActivityForResult(intent, 0);
}
});
mQrCodeButton = view.findViewById(R.id.import_qrcode_button);
mQrCodeText = (TextView) view.findViewById(R.id.import_qrcode_text);
mQrCodeProgress = (ProgressBar) view.findViewById(R.id.import_qrcode_progress);
mQrCodeButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
@@ -85,10 +97,10 @@ public class ImportKeysQrCodeFragment extends Fragment {
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
public void onAttach(Activity activity) {
super.onAttach(activity);
mImportActivity = (ImportKeysActivity) getActivity();
mImportActivity = (ImportKeysActivity) activity;
}
@Override
@@ -122,8 +134,7 @@ public class ImportKeysQrCodeFragment extends Fragment {
}
// fail...
AppMsg.makeText(getActivity(), R.string.import_qr_code_wrong, AppMsg.STYLE_ALERT)
.show();
Notify.showNotify(getActivity(), R.string.import_qr_code_wrong, Notify.Style.ERROR);
}
break;
@@ -136,6 +147,7 @@ public class ImportKeysQrCodeFragment extends Fragment {
}
}
public void importFingerprint(Uri dataUri) {
mImportActivity.loadFromFingerprintUri(null, dataUri);
}
@@ -151,32 +163,31 @@ public class ImportKeysQrCodeFragment extends Fragment {
// first qr code -> setup
if (counter == 0) {
mScannedContent = new String[size];
mProgress.setMax(size);
mProgress.setVisibility(View.VISIBLE);
mText.setVisibility(View.VISIBLE);
mQrCodeContent = new String[size];
mQrCodeProgress.setMax(size);
mQrCodeProgress.setVisibility(View.VISIBLE);
mQrCodeText.setVisibility(View.VISIBLE);
}
if (mScannedContent == null || counter > mScannedContent.length) {
AppMsg.makeText(getActivity(), R.string.import_qr_code_start_with_one, AppMsg.STYLE_ALERT)
.show();
if (mQrCodeContent == null || counter > mQrCodeContent.length) {
Notify.showNotify(getActivity(), R.string.import_qr_code_start_with_one, Notify.Style.ERROR);
return;
}
// save scanned content
mScannedContent[counter] = content;
mQrCodeContent[counter] = content;
// get missing numbers
ArrayList<Integer> missing = new ArrayList<Integer>();
for (int i = 0; i < mScannedContent.length; i++) {
if (mScannedContent[i] == null) {
for (int i = 0; i < mQrCodeContent.length; i++) {
if (mQrCodeContent[i] == null) {
missing.add(i);
}
}
// update progress and text
int alreadyScanned = mScannedContent.length - missing.size();
mProgress.setProgress(alreadyScanned);
int alreadyScanned = mQrCodeContent.length - missing.size();
mQrCodeProgress.setProgress(alreadyScanned);
String missingString = "";
for (int m : missing) {
@@ -188,17 +199,16 @@ public class ImportKeysQrCodeFragment extends Fragment {
String missingText = getResources().getQuantityString(R.plurals.import_qr_code_missing,
missing.size(), missingString);
mText.setText(missingText);
mQrCodeText.setText(missingText);
// finished!
if (missing.size() == 0) {
mText.setText(R.string.import_qr_code_finished);
mQrCodeText.setText(R.string.import_qr_code_finished);
String result = "";
for (String in : mScannedContent) {
for (String in : mQrCodeContent) {
result += in;
}
mImportActivity.loadCallback(result.getBytes(), null, null, null, null);
}
}
}

View File

@@ -17,6 +17,7 @@
package org.sufficientlysecure.keychain.ui;
import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.support.v4.app.Fragment;
@@ -32,8 +33,6 @@ import android.widget.EditText;
import android.widget.Spinner;
import android.widget.TextView;
import com.beardedhen.androidbootstrap.BootstrapButton;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.helper.Preferences;
@@ -46,8 +45,10 @@ public class ImportKeysServerFragment extends Fragment {
private ImportKeysActivity mImportActivity;
private BootstrapButton mSearchButton;
private View mSearchButton;
private EditText mQueryEditText;
private View mConfigButton;
private View mConfigLayout;
private Spinner mServerSpinner;
private ArrayAdapter<String> mServerAdapter;
@@ -73,14 +74,17 @@ public class ImportKeysServerFragment extends Fragment {
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.import_keys_server_fragment, container, false);
mSearchButton = (BootstrapButton) view.findViewById(R.id.import_server_search);
mSearchButton = view.findViewById(R.id.import_server_search);
mQueryEditText = (EditText) view.findViewById(R.id.import_server_query);
mConfigButton = view.findViewById(R.id.import_server_config_button);
mConfigLayout = view.findViewById(R.id.import_server_config);
mServerSpinner = (Spinner) view.findViewById(R.id.import_server_spinner);
// add keyservers to spinner
mServerAdapter = new ArrayAdapter<String>(getActivity(),
android.R.layout.simple_spinner_item, Preferences.getPreferences(getActivity())
.getKeyServers());
.getKeyServers()
);
mServerAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
mServerSpinner.setAdapter(mServerAdapter);
if (mServerAdapter.getCount() > 0) {
@@ -118,6 +122,17 @@ public class ImportKeysServerFragment extends Fragment {
}
});
mConfigButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
if (mImportActivity.getViewPagerHeight() > ImportKeysActivity.VIEW_PAGER_HEIGHT) {
mImportActivity.resizeViewPager(ImportKeysActivity.VIEW_PAGER_HEIGHT);
} else {
mImportActivity.resizeViewPager(ImportKeysActivity.VIEW_PAGER_HEIGHT + 41);
}
}
});
return view;
}
@@ -125,8 +140,6 @@ public class ImportKeysServerFragment extends Fragment {
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
mImportActivity = (ImportKeysActivity) getActivity();
// set displayed values
if (getArguments() != null) {
if (getArguments().containsKey(ARG_QUERY)) {
@@ -150,6 +163,13 @@ public class ImportKeysServerFragment extends Fragment {
}
}
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
mImportActivity = (ImportKeysActivity) activity;
}
private void search(String query, String keyServer) {
mImportActivity.loadCallback(null, null, query, keyServer, null);
}

View File

@@ -158,7 +158,7 @@ public class ViewKeyActivity extends ActionBarActivity implements
Bundle shareBundle = new Bundle();
shareBundle.putParcelable(ViewKeyMainFragment.ARG_DATA_URI, dataUri);
mTabsAdapter.addTab(ViewKeyShareFragment.class,
mainBundle, getString(R.string.key_view_tab_share));
shareBundle, getString(R.string.key_view_tab_share));
// update layout after operations
mSlidingTabLayout.setViewPager(mViewPager);

View File

@@ -133,7 +133,7 @@ public class ImportKeysListLoader
// read all available blocks... (asc files can contain many blocks with BEGIN END)
while (bufferedInput.available() > 0) {
// todo deal with non-keyring objects?
// TODO: deal with non-keyring objects?
List<UncachedKeyRing> rings = UncachedKeyRing.fromStream(bufferedInput);
for(UncachedKeyRing key : rings) {
ImportKeysListEntry item = new ImportKeysListEntry(getContext(), key);