Dont show verification icons in my key view, hide edit button for non-secret keys

This commit is contained in:
Dominik Schürmann 2015-02-25 21:53:46 +01:00
parent b521162ef0
commit a38f84a401
7 changed files with 153 additions and 52 deletions

View File

@ -34,6 +34,7 @@ import android.os.Bundle;
import android.os.Handler; import android.os.Handler;
import android.os.Message; import android.os.Message;
import android.provider.ContactsContract; import android.provider.ContactsContract;
import android.provider.Settings;
import android.support.v4.app.ActivityCompat; import android.support.v4.app.ActivityCompat;
import android.support.v4.app.LoaderManager; import android.support.v4.app.LoaderManager;
import android.support.v4.content.CursorLoader; import android.support.v4.content.CursorLoader;
@ -87,7 +88,6 @@ public class ViewKeyActivity extends BaseActivity implements
private ImageButton mActionEncryptFile; private ImageButton mActionEncryptFile;
private ImageButton mActionEncryptText; private ImageButton mActionEncryptText;
private ImageButton mActionVerify; private ImageButton mActionVerify;
private ImageButton mActionEdit;
private ImageButton mActionNfc; private ImageButton mActionNfc;
private FloatingActionButton mFab; private FloatingActionButton mFab;
private AspectRatioImageView mPhoto; private AspectRatioImageView mPhoto;
@ -103,8 +103,8 @@ public class ViewKeyActivity extends BaseActivity implements
private static final int LOADER_ID_UNIFIED = 0; private static final int LOADER_ID_UNIFIED = 0;
private boolean mIsSecret; private boolean mIsSecret = false;
private boolean mHasEncrypt; private boolean mHasEncrypt = false;
@Override @Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
@ -123,7 +123,6 @@ public class ViewKeyActivity extends BaseActivity implements
mActionEncryptFile = (ImageButton) findViewById(R.id.view_key_action_encrypt_files); mActionEncryptFile = (ImageButton) findViewById(R.id.view_key_action_encrypt_files);
mActionEncryptText = (ImageButton) findViewById(R.id.view_key_action_encrypt_text); mActionEncryptText = (ImageButton) findViewById(R.id.view_key_action_encrypt_text);
mActionVerify = (ImageButton) findViewById(R.id.view_key_action_verify); mActionVerify = (ImageButton) findViewById(R.id.view_key_action_verify);
mActionEdit = (ImageButton) findViewById(R.id.view_key_action_edit);
mActionNfc = (ImageButton) findViewById(R.id.view_key_action_nfc); mActionNfc = (ImageButton) findViewById(R.id.view_key_action_nfc);
mFab = (FloatingActionButton) findViewById(R.id.fab); mFab = (FloatingActionButton) findViewById(R.id.fab);
mPhoto = (AspectRatioImageView) findViewById(R.id.view_key_photo); mPhoto = (AspectRatioImageView) findViewById(R.id.view_key_photo);
@ -165,11 +164,6 @@ public class ViewKeyActivity extends BaseActivity implements
certify(mDataUri); certify(mDataUri);
} }
}); });
mActionEdit.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
editKey(mDataUri);
}
});
mFab.setOnClickListener(new View.OnClickListener() { mFab.setOnClickListener(new View.OnClickListener() {
@Override @Override
@ -271,6 +265,10 @@ public class ViewKeyActivity extends BaseActivity implements
} }
return true; return true;
} }
case R.id.menu_key_view_edit: {
editKey(mDataUri);
return true;
}
} }
} catch (ProviderHelper.NotFoundException e) { } catch (ProviderHelper.NotFoundException e) {
Notify.showNotify(this, R.string.error_key_not_found, Notify.Style.ERROR); Notify.showNotify(this, R.string.error_key_not_found, Notify.Style.ERROR);
@ -279,13 +277,42 @@ public class ViewKeyActivity extends BaseActivity implements
return super.onOptionsItemSelected(item); return super.onOptionsItemSelected(item);
} }
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
MenuItem register = menu.findItem(R.id.menu_key_view_edit);
register.setVisible(mIsSecret);
return true;
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP) @TargetApi(Build.VERSION_CODES.LOLLIPOP)
private void invokeNfcBeam() { private void invokeNfcBeam() {
// Check for available NFC Adapter // Check for available NFC Adapter
mNfcAdapter = NfcAdapter.getDefaultAdapter(this); mNfcAdapter = NfcAdapter.getDefaultAdapter(this);
if (mNfcAdapter != null) { if (mNfcAdapter == null || !mNfcAdapter.isEnabled()) {
mNfcAdapter.invokeBeam(this); Notify.createNotify(this, R.string.error_nfc_needed, Notify.LENGTH_LONG, Notify.Style.ERROR, new Notify.ActionListener() {
@Override
public void onAction() {
Intent intentSettings = new Intent(Settings.ACTION_NFC_SETTINGS);
startActivity(intentSettings);
}
}, R.string.menu_nfc_preferences).show();
return;
} }
if (!mNfcAdapter.isNdefPushEnabled()) {
Notify.createNotify(this, R.string.error_beam_needed, Notify.LENGTH_LONG, Notify.Style.ERROR, new Notify.ActionListener() {
@Override
public void onAction() {
Intent intentSettings = new Intent(Settings.ACTION_NFCSHARING_SETTINGS);
startActivity(intentSettings);
}
}, R.string.menu_beam_preferences).show();
return;
}
mNfcAdapter.invokeBeam(this);
} }
private void scanQrCode() { private void scanQrCode() {
@ -640,17 +667,14 @@ public class ViewKeyActivity extends BaseActivity implements
mActionEncryptFile.setVisibility(View.GONE); mActionEncryptFile.setVisibility(View.GONE);
mActionEncryptText.setVisibility(View.GONE); mActionEncryptText.setVisibility(View.GONE);
mActionVerify.setVisibility(View.GONE); mActionVerify.setVisibility(View.GONE);
mActionEdit.setVisibility(View.GONE);
mActionNfc.setVisibility(View.GONE); mActionNfc.setVisibility(View.GONE);
mFab.setVisibility(View.GONE); mFab.setVisibility(View.GONE);
mQrCodeLayout.setVisibility(View.GONE); mQrCodeLayout.setVisibility(View.GONE);
} else if (isExpired) { } else if (isExpired) {
if (mIsSecret) { if (mIsSecret) {
mStatusText.setText(R.string.view_key_expired_secret); mStatusText.setText(R.string.view_key_expired_secret);
mActionEdit.setVisibility(View.VISIBLE);
} else { } else {
mStatusText.setText(R.string.view_key_expired); mStatusText.setText(R.string.view_key_expired);
mActionEdit.setVisibility(View.GONE);
} }
mStatusImage.setVisibility(View.VISIBLE); mStatusImage.setVisibility(View.VISIBLE);
KeyFormattingUtils.setStatusImage(this, mStatusImage, mStatusText, KeyFormattingUtils.setStatusImage(this, mStatusImage, mStatusText,
@ -664,6 +688,9 @@ public class ViewKeyActivity extends BaseActivity implements
mFab.setVisibility(View.GONE); mFab.setVisibility(View.GONE);
mQrCodeLayout.setVisibility(View.GONE); mQrCodeLayout.setVisibility(View.GONE);
} else if (mIsSecret) { } else if (mIsSecret) {
// re-create options menu to see edit button
supportInvalidateOptionsMenu();
mStatusText.setText(R.string.view_key_my_key); mStatusText.setText(R.string.view_key_my_key);
mStatusImage.setVisibility(View.GONE); mStatusImage.setVisibility(View.GONE);
color = getResources().getColor(R.color.primary); color = getResources().getColor(R.color.primary);
@ -694,7 +721,6 @@ public class ViewKeyActivity extends BaseActivity implements
mActionEncryptFile.setVisibility(View.VISIBLE); mActionEncryptFile.setVisibility(View.VISIBLE);
mActionEncryptText.setVisibility(View.VISIBLE); mActionEncryptText.setVisibility(View.VISIBLE);
mActionVerify.setVisibility(View.GONE); mActionVerify.setVisibility(View.GONE);
mActionEdit.setVisibility(View.VISIBLE);
// invokeBeam is available from API 21 // invokeBeam is available from API 21
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
@ -707,7 +733,6 @@ public class ViewKeyActivity extends BaseActivity implements
} else { } else {
mActionEncryptFile.setVisibility(View.VISIBLE); mActionEncryptFile.setVisibility(View.VISIBLE);
mActionEncryptText.setVisibility(View.VISIBLE); mActionEncryptText.setVisibility(View.VISIBLE);
mActionEdit.setVisibility(View.GONE);
mQrCodeLayout.setVisibility(View.GONE); mQrCodeLayout.setVisibility(View.GONE);
mActionNfc.setVisibility(View.GONE); mActionNfc.setVisibility(View.GONE);

View File

@ -265,9 +265,10 @@ public class ViewKeyAdvMainFragment extends LoaderFragment implements
} }
} }
case LOADER_ID_USER_IDS: case LOADER_ID_USER_IDS: {
mUserIdsAdapter.swapCursor(data); mUserIdsAdapter.swapCursor(data);
break; break;
}
} }
setContentShown(true); setContentShown(true);

View File

@ -33,12 +33,15 @@ import android.widget.ListView;
import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.compatibility.DialogFragmentWorkaround; import org.sufficientlysecure.keychain.compatibility.DialogFragmentWorkaround;
import org.sufficientlysecure.keychain.provider.KeychainContract;
import org.sufficientlysecure.keychain.provider.KeychainContract.UserPackets; import org.sufficientlysecure.keychain.provider.KeychainContract.UserPackets;
import org.sufficientlysecure.keychain.provider.ProviderHelper; import org.sufficientlysecure.keychain.provider.ProviderHelper;
import org.sufficientlysecure.keychain.ui.adapter.UserIdsAdapter; import org.sufficientlysecure.keychain.ui.adapter.UserIdsAdapter;
import org.sufficientlysecure.keychain.ui.dialog.UserIdInfoDialogFragment; import org.sufficientlysecure.keychain.ui.dialog.UserIdInfoDialogFragment;
import org.sufficientlysecure.keychain.util.Log; import org.sufficientlysecure.keychain.util.Log;
import java.util.Date;
public class ViewKeyFragment extends LoaderFragment implements public class ViewKeyFragment extends LoaderFragment implements
LoaderManager.LoaderCallbacks<Cursor> { LoaderManager.LoaderCallbacks<Cursor> {
@ -46,6 +49,9 @@ public class ViewKeyFragment extends LoaderFragment implements
private ListView mUserIds; private ListView mUserIds;
boolean mIsSecret = false;
private static final int LOADER_ID_UNIFIED = 0;
private static final int LOADER_ID_USER_IDS = 1; private static final int LOADER_ID_USER_IDS = 1;
private UserIdsAdapter mUserIdsAdapter; private UserIdsAdapter mUserIdsAdapter;
@ -76,7 +82,6 @@ public class ViewKeyFragment extends LoaderFragment implements
mUserIds = (ListView) view.findViewById(R.id.view_key_user_ids); mUserIds = (ListView) view.findViewById(R.id.view_key_user_ids);
mUserIds.setOnItemClickListener(new AdapterView.OnItemClickListener() { mUserIds.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override @Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) { public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
@ -84,22 +89,23 @@ public class ViewKeyFragment extends LoaderFragment implements
} }
}); });
return root; return root;
} }
private void showUserIdInfo(final int position) { private void showUserIdInfo(final int position) {
final boolean isRevoked = mUserIdsAdapter.getIsRevoked(position); if (!mIsSecret) {
final int isVerified = mUserIdsAdapter.getIsVerified(position); final boolean isRevoked = mUserIdsAdapter.getIsRevoked(position);
final int isVerified = mUserIdsAdapter.getIsVerified(position);
DialogFragmentWorkaround.INTERFACE.runnableRunDelayed(new Runnable() { DialogFragmentWorkaround.INTERFACE.runnableRunDelayed(new Runnable() {
public void run() { public void run() {
UserIdInfoDialogFragment dialogFragment = UserIdInfoDialogFragment dialogFragment =
UserIdInfoDialogFragment.newInstance(isRevoked, isVerified); UserIdInfoDialogFragment.newInstance(isRevoked, isVerified);
dialogFragment.show(getActivity().getSupportFragmentManager(), "userIdInfoDialog"); dialogFragment.show(getActivity().getSupportFragmentManager(), "userIdInfoDialog");
} }
}); });
}
} }
@Override @Override
@ -116,28 +122,59 @@ public class ViewKeyFragment extends LoaderFragment implements
loadData(dataUri); loadData(dataUri);
} }
// These are the rows that we will retrieve.
static final String[] UNIFIED_PROJECTION = new String[]{
KeychainContract.KeyRings._ID,
KeychainContract.KeyRings.MASTER_KEY_ID,
KeychainContract.KeyRings.USER_ID,
KeychainContract.KeyRings.IS_REVOKED,
KeychainContract.KeyRings.EXPIRY,
KeychainContract.KeyRings.VERIFIED,
KeychainContract.KeyRings.HAS_ANY_SECRET,
KeychainContract.KeyRings.FINGERPRINT,
KeychainContract.KeyRings.HAS_ENCRYPT
};
static final int INDEX_MASTER_KEY_ID = 1;
static final int INDEX_USER_ID = 2;
static final int INDEX_IS_REVOKED = 3;
static final int INDEX_EXPIRY = 4;
static final int INDEX_VERIFIED = 5;
static final int INDEX_HAS_ANY_SECRET = 6;
static final int INDEX_FINGERPRINT = 7;
static final int INDEX_HAS_ENCRYPT = 8;
private void loadData(Uri dataUri) { private void loadData(Uri dataUri) {
mDataUri = dataUri; mDataUri = dataUri;
Log.i(Constants.TAG, "mDataUri: " + mDataUri.toString()); Log.i(Constants.TAG, "mDataUri: " + mDataUri.toString());
mUserIdsAdapter = new UserIdsAdapter(getActivity(), null, 0);
mUserIds.setAdapter(mUserIdsAdapter);
// Prepare the loaders. Either re-connect with an existing ones, // Prepare the loaders. Either re-connect with an existing ones,
// or start new ones. // or start new ones.
getLoaderManager().initLoader(LOADER_ID_USER_IDS, null, this); getLoaderManager().initLoader(LOADER_ID_UNIFIED, null, this);
} }
// don't show revoked user ids here, irrelevant for average users // don't show revoked user ids here, irrelevant for average users
public static final String WHERE = UserPackets.IS_REVOKED + " = 0"; public static final String USER_IDS_WHERE = UserPackets.IS_REVOKED + " = 0";
public Loader<Cursor> onCreateLoader(int id, Bundle args) { public Loader<Cursor> onCreateLoader(int id, Bundle args) {
setContentShown(false); setContentShown(false);
Uri baseUri = UserPackets.buildUserIdsUri(mDataUri); switch (id) {
return new CursorLoader(getActivity(), baseUri, case LOADER_ID_UNIFIED: {
UserIdsAdapter.USER_IDS_PROJECTION, WHERE, null, null); Uri baseUri = KeychainContract.KeyRings.buildUnifiedKeyRingUri(mDataUri);
return new CursorLoader(getActivity(), baseUri, UNIFIED_PROJECTION, null, null, null);
}
case LOADER_ID_USER_IDS: {
Uri baseUri = UserPackets.buildUserIdsUri(mDataUri);
return new CursorLoader(getActivity(), baseUri,
UserIdsAdapter.USER_IDS_PROJECTION, USER_IDS_WHERE, null, null);
}
default:
return null;
}
} }
public void onLoadFinished(Loader<Cursor> loader, Cursor data) { public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
@ -150,8 +187,32 @@ public class ViewKeyFragment extends LoaderFragment implements
} }
// Swap the new cursor in. (The framework will take care of closing the // Swap the new cursor in. (The framework will take care of closing the
// old cursor once we return.) // old cursor once we return.)
switch (loader.getId()) {
case LOADER_ID_UNIFIED: {
if (data.moveToFirst()) {
mUserIdsAdapter.swapCursor(data); mIsSecret = data.getInt(INDEX_HAS_ANY_SECRET) != 0;
boolean hasEncrypt = data.getInt(INDEX_HAS_ENCRYPT) != 0;
boolean isRevoked = data.getInt(INDEX_IS_REVOKED) > 0;
boolean isExpired = !data.isNull(INDEX_EXPIRY)
&& new Date(data.getLong(INDEX_EXPIRY) * 1000).before(new Date());
boolean isVerified = data.getInt(INDEX_VERIFIED) > 0;
// load user ids after we know if it's a secret key
mUserIdsAdapter = new UserIdsAdapter(getActivity(), null, 0, false, !mIsSecret, null);
mUserIds.setAdapter(mUserIdsAdapter);
getLoaderManager().initLoader(LOADER_ID_USER_IDS, null, this);
break;
}
}
case LOADER_ID_USER_IDS: {
mUserIdsAdapter.swapCursor(data);
break;
}
}
setContentShown(true); setContentShown(true);
} }
@ -161,9 +222,10 @@ public class ViewKeyFragment extends LoaderFragment implements
*/ */
public void onLoaderReset(Loader<Cursor> loader) { public void onLoaderReset(Loader<Cursor> loader) {
switch (loader.getId()) { switch (loader.getId()) {
case LOADER_ID_USER_IDS: case LOADER_ID_USER_IDS: {
mUserIdsAdapter.swapCursor(null); mUserIdsAdapter.swapCursor(null);
break; break;
}
} }
} }

View File

@ -43,6 +43,7 @@ public class UserIdsAdapter extends CursorAdapter implements AdapterView.OnItemC
private LayoutInflater mInflater; private LayoutInflater mInflater;
private final ArrayList<Boolean> mCheckStates; private final ArrayList<Boolean> mCheckStates;
private SaveKeyringParcel mSaveKeyringParcel; private SaveKeyringParcel mSaveKeyringParcel;
private boolean mShowStatusImages;
public static final String[] USER_IDS_PROJECTION = new String[]{ public static final String[] USER_IDS_PROJECTION = new String[]{
UserPackets._ID, UserPackets._ID,
@ -60,24 +61,30 @@ public class UserIdsAdapter extends CursorAdapter implements AdapterView.OnItemC
private static final int INDEX_IS_REVOKED = 5; private static final int INDEX_IS_REVOKED = 5;
public UserIdsAdapter(Context context, Cursor c, int flags, boolean showCheckBoxes, public UserIdsAdapter(Context context, Cursor c, int flags, boolean showCheckBoxes,
SaveKeyringParcel saveKeyringParcel) { boolean showStatusImages, SaveKeyringParcel saveKeyringParcel) {
super(context, c, flags); super(context, c, flags);
mInflater = LayoutInflater.from(context); mInflater = LayoutInflater.from(context);
mCheckStates = showCheckBoxes ? new ArrayList<Boolean>() : null; mCheckStates = showCheckBoxes ? new ArrayList<Boolean>() : null;
mSaveKeyringParcel = saveKeyringParcel; mSaveKeyringParcel = saveKeyringParcel;
mShowStatusImages = showStatusImages;
}
public UserIdsAdapter(Context context, Cursor c, int flags, boolean showCheckBoxes,
SaveKeyringParcel saveKeyringParcel) {
this(context, c, flags, showCheckBoxes, false, saveKeyringParcel);
} }
public UserIdsAdapter(Context context, Cursor c, int flags, boolean showCheckBoxes) { public UserIdsAdapter(Context context, Cursor c, int flags, boolean showCheckBoxes) {
this(context, c, flags, showCheckBoxes, null); this(context, c, flags, showCheckBoxes, false, null);
} }
public UserIdsAdapter(Context context, Cursor c, int flags, SaveKeyringParcel saveKeyringParcel) { public UserIdsAdapter(Context context, Cursor c, int flags, SaveKeyringParcel saveKeyringParcel) {
this(context, c, flags, false, saveKeyringParcel); this(context, c, flags, false, false, saveKeyringParcel);
} }
public UserIdsAdapter(Context context, Cursor c, int flags) { public UserIdsAdapter(Context context, Cursor c, int flags) {
this(context, c, flags, false, null); this(context, c, flags, false, false, null);
} }
@Override @Override
@ -157,7 +164,12 @@ public class UserIdsAdapter extends CursorAdapter implements AdapterView.OnItemC
vVerifiedLayout.setVisibility(View.GONE); vVerifiedLayout.setVisibility(View.GONE);
} else { } else {
vEditImage.setVisibility(View.GONE); vEditImage.setVisibility(View.GONE);
vVerifiedLayout.setVisibility(View.VISIBLE);
if (mShowStatusImages) {
vVerifiedLayout.setVisibility(View.VISIBLE);
} else {
vVerifiedLayout.setVisibility(View.GONE);
}
} }
if (isRevoked) { if (isRevoked) {

View File

@ -108,14 +108,6 @@
style="?android:attr/borderlessButtonStyle" style="?android:attr/borderlessButtonStyle"
android:src="@drawable/ic_action_verified_cutout" /> android:src="@drawable/ic_action_verified_cutout" />
<ImageButton
android:id="@+id/view_key_action_edit"
android:layout_width="64dp"
android:layout_height="64dp"
android:visibility="invisible"
style="?android:attr/borderlessButtonStyle"
android:src="@drawable/ic_mode_edit_white_24dp" />
<ImageButton <ImageButton
android:id="@+id/view_key_action_nfc" android:id="@+id/view_key_action_nfc"
android:layout_width="64dp" android:layout_width="64dp"

View File

@ -2,6 +2,13 @@
<menu xmlns:android="http://schemas.android.com/apk/res/android" <menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"> xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/menu_key_view_edit"
android:icon="@drawable/ic_mode_edit_white_24dp"
android:visible="false"
app:showAsAction="always"
android:title="@string/key_view_action_edit" />
<item <item
android:id="@+id/menu_key_view_refresh" android:id="@+id/menu_key_view_refresh"
android:icon="@drawable/ic_refresh_white_24dp" android:icon="@drawable/ic_refresh_white_24dp"

View File

@ -98,6 +98,7 @@
<string name="menu_create_key">"Create my key"</string> <string name="menu_create_key">"Create my key"</string>
<string name="menu_import_existing_key">"Import from file"</string> <string name="menu_import_existing_key">"Import from file"</string>
<string name="menu_search">"Search"</string> <string name="menu_search">"Search"</string>
<string name="menu_nfc_preferences">"NFC settings"</string>
<string name="menu_beam_preferences">"Beam settings"</string> <string name="menu_beam_preferences">"Beam settings"</string>
<string name="menu_key_edit_cancel">"Cancel"</string> <string name="menu_key_edit_cancel">"Cancel"</string>
<string name="menu_encrypt_to">"Encrypt to…"</string> <string name="menu_encrypt_to">"Encrypt to…"</string>
@ -272,7 +273,8 @@
<!-- errors without preceeding Error: --> <!-- errors without preceeding Error: -->
<string name="error_jelly_bean_needed">"You need Android 4.1 to use Android's NFC Beam feature!"</string> <string name="error_jelly_bean_needed">"You need Android 4.1 to use Android's NFC Beam feature!"</string>
<string name="error_nfc_needed">"NFC is not available on your device!"</string> <string name="error_nfc_needed">"NFC must be enabled!"</string>
<string name="error_beam_needed">"Beam must be enabled!"</string>
<string name="error_nothing_import">"No keys found!"</string> <string name="error_nothing_import">"No keys found!"</string>
<string name="error_contacts_key_id_missing">"Retrieving the key ID from contacts failed!"</string> <string name="error_contacts_key_id_missing">"Retrieving the key ID from contacts failed!"</string>
<string name="error_generic_report_bug">"A generic error occurred, please create a new bug report for OpenKeychain."</string> <string name="error_generic_report_bug">"A generic error occurred, please create a new bug report for OpenKeychain."</string>