New decryption screen UI with modernPGP icons

This commit is contained in:
Dominik Schürmann
2014-10-08 17:32:32 +02:00
parent adcc07ca65
commit b573afe235
31 changed files with 391 additions and 242 deletions

View File

@@ -21,16 +21,14 @@ import android.content.Intent;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;
import org.openintents.openpgp.OpenPgpSignatureResult;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.pgp.KeyRing;
import org.sufficientlysecure.keychain.provider.KeychainContract;
import org.sufficientlysecure.keychain.service.results.DecryptVerifyResult;
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
@@ -43,14 +41,19 @@ public abstract class DecryptFragment extends Fragment {
protected long mSignatureKeyId = 0;
protected LinearLayout mResultLayout;
protected RelativeLayout mSignatureLayout;
protected TextView mResultText;
protected ImageView mSignatureStatusImage;
protected TextView mUserId;
protected TextView mUserIdRest;
protected ImageView mEncryptionIcon;
protected TextView mEncryptionText;
protected ImageView mSignatureIcon;
protected TextView mSignatureText;
protected View mSignatureLayout;
protected View mSignatureDivider1;
protected View mSignatureDivider2;
protected TextView mSignatureName;
protected TextView mSignatureEmail;
protected TextView mSignatureAction;
protected Button mLookupKey;
// State
protected String mPassphrase;
@@ -60,20 +63,20 @@ public abstract class DecryptFragment extends Fragment {
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
mResultLayout = (LinearLayout) getView().findViewById(R.id.result);
mResultText = (TextView) getView().findViewById(R.id.result_text);
mSignatureLayout = (RelativeLayout) getView().findViewById(R.id.result_signature);
mSignatureStatusImage = (ImageView) getView().findViewById(R.id.ic_signature_status);
mUserId = (TextView) getView().findViewById(R.id.mainUserId);
mUserIdRest = (TextView) getView().findViewById(R.id.mainUserIdRest);
mLookupKey = (Button) getView().findViewById(R.id.lookup_key);
mLookupKey.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
lookupUnknownKey(mSignatureKeyId);
}
});
mResultLayout = (LinearLayout) getView().findViewById(R.id.result_main_layout);
mResultLayout.setVisibility(View.GONE);
mEncryptionIcon = (ImageView) getView().findViewById(R.id.result_encryption_icon);
mEncryptionText = (TextView) getView().findViewById(R.id.result_encryption_text);
mSignatureIcon = (ImageView) getView().findViewById(R.id.result_signature_icon);
mSignatureText = (TextView) getView().findViewById(R.id.result_signature_text);
mSignatureLayout = getView().findViewById(R.id.result_signature_layout);
mSignatureDivider1 = getView().findViewById(R.id.result_signature_divider1);
mSignatureDivider2 = getView().findViewById(R.id.result_signature_divider2);
mSignatureName = (TextView) getView().findViewById(R.id.result_signature_name);
mSignatureEmail = (TextView) getView().findViewById(R.id.result_signature_email);
mSignatureAction = (TextView) getView().findViewById(R.id.result_signature_action);
}
private void lookupUnknownKey(long unknownKeyId) {
@@ -103,101 +106,114 @@ public abstract class DecryptFragment extends Fragment {
}
protected void onResult(DecryptVerifyResult decryptVerifyResult) {
OpenPgpSignatureResult signatureResult = decryptVerifyResult.getSignatureResult();
final OpenPgpSignatureResult signatureResult = decryptVerifyResult.getSignatureResult();
mSignatureKeyId = 0;
mResultLayout.setVisibility(View.VISIBLE);
if (signatureResult != null) {
mSignatureStatusImage.setVisibility(View.VISIBLE);
mSignatureKeyId = signatureResult.getKeyId();
String userId = signatureResult.getPrimaryUserId();
String[] userIdSplit = KeyRing.splitUserId(userId);
if (userIdSplit[0] != null) {
mUserId.setText(userIdSplit[0]);
mSignatureName.setText(userIdSplit[0]);
} else {
mUserId.setText(R.string.user_id_no_name);
mSignatureName.setText(R.string.user_id_no_name);
}
if (userIdSplit[1] != null) {
mUserIdRest.setText(userIdSplit[1]);
mSignatureEmail.setText(userIdSplit[1]);
} else {
mUserIdRest.setText(KeyFormattingUtils.beautifyKeyIdWithPrefix(getActivity(), mSignatureKeyId));
mSignatureEmail.setText(KeyFormattingUtils.beautifyKeyIdWithPrefix(getActivity(), mSignatureKeyId));
}
if (signatureResult.isSignatureOnly()) {
mEncryptionText.setText(R.string.decrypt_result_not_encrypted);
KeyFormattingUtils.setStatusImage(getActivity(), mEncryptionIcon, mEncryptionText, KeyFormattingUtils.STATE_NOT_ENCRYPTED);
} else {
mEncryptionText.setText(R.string.decrypt_result_encrypted);
KeyFormattingUtils.setStatusImage(getActivity(), mEncryptionIcon, mEncryptionText, KeyFormattingUtils.STATE_ENCRYPTED);
}
switch (signatureResult.getStatus()) {
case OpenPgpSignatureResult.SIGNATURE_SUCCESS_CERTIFIED: {
if (signatureResult.isSignatureOnly()) {
mResultText.setText(R.string.decrypt_result_signature_certified);
} else {
mResultText.setText(R.string.decrypt_result_decrypted_and_signature_certified);
}
mSignatureText.setText(R.string.decrypt_result_signature_certified);
KeyFormattingUtils.setStatusImage(getActivity(), mSignatureIcon, mSignatureText, KeyFormattingUtils.STATE_VERIFIED);
mResultLayout.setBackgroundColor(getResources().getColor(R.color.android_green_light));
mSignatureStatusImage.setImageResource(R.drawable.overlay_ok);
mSignatureLayout.setVisibility(View.VISIBLE);
mLookupKey.setVisibility(View.GONE);
setSignatureLayoutVisibility(View.VISIBLE);
mSignatureAction.setText(R.string.decrypt_result_action_show);
mSignatureAction.setCompoundDrawablesWithIntrinsicBounds(0, 0, R.drawable.ic_action_accounts, 0);
mSignatureLayout.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent viewKeyIntent = new Intent(getActivity(), ViewKeyActivity.class);
viewKeyIntent.setData(KeychainContract.KeyRings
.buildGenericKeyRingUri(mSignatureKeyId));
startActivity(viewKeyIntent);
}
});
break;
}
case OpenPgpSignatureResult.SIGNATURE_SUCCESS_UNCERTIFIED: {
if (signatureResult.isSignatureOnly()) {
mResultText.setText(R.string.decrypt_result_signature_uncertified);
} else {
mResultText.setText(R.string.decrypt_result_decrypted_and_signature_uncertified);
}
mSignatureText.setText(R.string.decrypt_result_signature_uncertified);
KeyFormattingUtils.setStatusImage(getActivity(), mSignatureIcon, mSignatureText, KeyFormattingUtils.STATE_UNVERIFIED);
mResultLayout.setBackgroundColor(getResources().getColor(R.color.android_orange_light));
mSignatureStatusImage.setImageResource(R.drawable.overlay_ok);
mSignatureLayout.setVisibility(View.VISIBLE);
mLookupKey.setVisibility(View.GONE);
setSignatureLayoutVisibility(View.VISIBLE);
mSignatureAction.setText(R.string.decrypt_result_action_show);
mSignatureAction.setCompoundDrawablesWithIntrinsicBounds(0, 0, R.drawable.ic_action_accounts, 0);
mSignatureLayout.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent viewKeyIntent = new Intent(getActivity(), ViewKeyActivity.class);
viewKeyIntent.setData(KeychainContract.KeyRings
.buildGenericKeyRingUri(mSignatureKeyId));
startActivity(viewKeyIntent);
}
});
break;
}
case OpenPgpSignatureResult.SIGNATURE_KEY_MISSING: {
if (signatureResult.isSignatureOnly()) {
mResultText.setText(R.string.decrypt_result_signature_unknown_pub_key);
} else {
mResultText.setText(R.string.decrypt_result_decrypted_unknown_pub_key);
}
mSignatureText.setText(R.string.decrypt_result_signature_unknown_pub_key);
KeyFormattingUtils.setStatusImage(getActivity(), mSignatureIcon, mSignatureText, KeyFormattingUtils.STATE_UNKNOWN_KEY);
mResultLayout.setBackgroundColor(getResources().getColor(R.color.android_orange_light));
mSignatureStatusImage.setImageResource(R.drawable.overlay_error);
mSignatureLayout.setVisibility(View.VISIBLE);
mLookupKey.setVisibility(View.VISIBLE);
setSignatureLayoutVisibility(View.VISIBLE);
mSignatureAction.setText(R.string.decrypt_result_action_Lookup);
mSignatureAction.setCompoundDrawablesWithIntrinsicBounds(0, 0, R.drawable.ic_action_download, 0);
mSignatureLayout.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
lookupUnknownKey(mSignatureKeyId);
}
});
break;
}
// TODO: Maybe this should be part of the Result parcel, it is an error, not a valid status!
case OpenPgpSignatureResult.SIGNATURE_ERROR: {
mResultText.setText(R.string.decrypt_result_invalid_signature);
mSignatureText.setText(R.string.decrypt_result_invalid_signature);
KeyFormattingUtils.setStatusImage(getActivity(), mSignatureIcon, mSignatureText, KeyFormattingUtils.STATE_INVALID);
mResultLayout.setBackgroundColor(getResources().getColor(R.color.android_red_light));
mSignatureStatusImage.setImageResource(R.drawable.overlay_error);
mSignatureLayout.setVisibility(View.GONE);
mLookupKey.setVisibility(View.GONE);
break;
}
default: {
mResultText.setText(R.string.error);
mResultLayout.setBackgroundColor(getResources().getColor(R.color.android_red_light));
mSignatureStatusImage.setImageResource(R.drawable.overlay_error);
mSignatureLayout.setVisibility(View.GONE);
mLookupKey.setVisibility(View.GONE);
setSignatureLayoutVisibility(View.GONE);
break;
}
}
} else {
mSignatureLayout.setVisibility(View.GONE);
mLookupKey.setVisibility(View.GONE);
setSignatureLayoutVisibility(View.GONE);
// successful decryption-only
mResultLayout.setBackgroundColor(getResources().getColor(R.color.android_purple_light));
mResultText.setText(R.string.decrypt_result_decrypted);
mSignatureText.setText(R.string.decrypt_result_no_signature);
KeyFormattingUtils.setStatusImage(getActivity(), mSignatureIcon, mSignatureText, KeyFormattingUtils.STATE_NOT_SIGNED);
mEncryptionText.setText(R.string.decrypt_result_encrypted);
KeyFormattingUtils.setStatusImage(getActivity(), mEncryptionIcon, mEncryptionText, KeyFormattingUtils.STATE_ENCRYPTED);
}
}
private void setSignatureLayoutVisibility(int visibility) {
mSignatureLayout.setVisibility(visibility);
mSignatureDivider1.setVisibility(visibility);
mSignatureDivider2.setVisibility(visibility);
}
/**
* Should be overridden by MessageFragment and FileFragment to start actual decryption
*/

View File

@@ -64,12 +64,12 @@ public class UserIdInfoDialogFragment extends DialogFragment {
} else {
switch (isVerified) {
case KeychainContract.Certs.VERIFIED_SECRET:
title = getString(R.string.user_id_info_verified_title);
message = getString(R.string.user_id_info_verified_text);
title = getString(R.string.user_id_info_certified_title);
message = getString(R.string.user_id_info_certified_text);
break;
case KeychainContract.Certs.VERIFIED_SELF:
title = getString(R.string.user_id_info_not_verified_title);
message = getString(R.string.user_id_info_not_verified_text);
title = getString(R.string.user_id_info_uncertified_title);
message = getString(R.string.user_id_info_uncertified_text);
break;
default:
title = getString(R.string.user_id_info_invalid_title);

View File

@@ -19,18 +19,13 @@
package org.sufficientlysecure.keychain.ui.util;
import android.content.Context;
import android.database.Cursor;
import android.graphics.Color;
import android.graphics.PorterDuff;
import android.graphics.Typeface;
import android.text.Spannable;
import android.text.SpannableString;
import android.text.SpannableStringBuilder;
import android.text.style.ForegroundColorSpan;
import android.text.style.StyleSpan;
import android.text.style.TypefaceSpan;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import org.spongycastle.asn1.ASN1ObjectIdentifier;
import org.spongycastle.asn1.nist.NISTNamedCurves;
@@ -386,36 +381,126 @@ public class KeyFormattingUtils {
public static final int STATE_EXPIRED = 2;
public static final int STATE_VERIFIED = 3;
public static final int STATE_UNAVAILABLE = 4;
public static final int STATE_ENCRYPTED = 5;
public static final int STATE_NOT_ENCRYPTED = 6;
public static final int STATE_UNVERIFIED = 7;
public static final int STATE_UNKNOWN_KEY = 8;
public static final int STATE_INVALID = 9;
public static final int STATE_NOT_SIGNED = 10;
public static void setStatusImage(Context context, ImageView statusIcon, int state) {
setStatusImage(context, statusIcon, null, state);
}
/**
* Sets status image based on constant
*/
public static void setStatusImage(Context context, ImageView statusView, int state) {
public static void setStatusImage(Context context, ImageView statusIcon, TextView statusText, int state) {
switch (state) {
case STATE_REVOKED:
statusView.setImageDrawable(
context.getResources().getDrawable(R.drawable.status_signature_revoked_cutout));
statusView.setColorFilter(context.getResources().getColor(R.color.android_red_dark),
PorterDuff.Mode.SRC_ATOP);
break;
case STATE_EXPIRED:
statusView.setImageDrawable(
context.getResources().getDrawable(R.drawable.status_signature_expired_cutout));
statusView.setColorFilter(context.getResources().getColor(R.color.android_orange_dark),
PorterDuff.Mode.SRC_ATOP);
break;
case STATE_UNAVAILABLE:
statusView.setImageDrawable(
context.getResources().getDrawable(R.drawable.status_signature_invalid_cutout));
statusView.setColorFilter(context.getResources().getColor(R.color.bg_gray),
PorterDuff.Mode.SRC_ATOP);
break;
case STATE_VERIFIED:
statusView.setImageDrawable(
/** GREEN: everything is good **/
case STATE_VERIFIED: {
statusIcon.setImageDrawable(
context.getResources().getDrawable(R.drawable.status_signature_verified_cutout));
statusView.setColorFilter(context.getResources().getColor(R.color.android_green_dark),
statusIcon.setColorFilter(context.getResources().getColor(R.color.android_green_dark),
PorterDuff.Mode.SRC_ATOP);
if (statusText != null) {
statusText.setTextColor(context.getResources().getColor(R.color.android_green_dark));
}
break;
}
case STATE_ENCRYPTED: {
statusIcon.setImageDrawable(
context.getResources().getDrawable(R.drawable.status_lock_closed));
statusIcon.setColorFilter(context.getResources().getColor(R.color.android_green_dark),
PorterDuff.Mode.SRC_ATOP);
if (statusText != null) {
statusText.setTextColor(context.getResources().getColor(R.color.android_green_dark));
}
break;
}
/** ORANGE: mostly bad... **/
case STATE_UNVERIFIED: {
statusIcon.setImageDrawable(
context.getResources().getDrawable(R.drawable.status_signature_unverified_cutout));
statusIcon.setColorFilter(context.getResources().getColor(R.color.android_orange_dark),
PorterDuff.Mode.SRC_ATOP);
if (statusText != null) {
statusText.setTextColor(context.getResources().getColor(R.color.android_orange_dark));
}
break;
}
case STATE_EXPIRED: {
statusIcon.setImageDrawable(
context.getResources().getDrawable(R.drawable.status_signature_expired_cutout));
statusIcon.setColorFilter(context.getResources().getColor(R.color.android_orange_dark),
PorterDuff.Mode.SRC_ATOP);
if (statusText != null) {
statusText.setTextColor(context.getResources().getColor(R.color.android_orange_dark));
}
break;
}
case STATE_UNKNOWN_KEY: {
statusIcon.setImageDrawable(
context.getResources().getDrawable(R.drawable.status_signature_unknown_cutout));
statusIcon.setColorFilter(context.getResources().getColor(R.color.android_orange_dark),
PorterDuff.Mode.SRC_ATOP);
if (statusText != null) {
statusText.setTextColor(context.getResources().getColor(R.color.android_orange_dark));
}
break;
}
/** RED: really bad... **/
case STATE_REVOKED: {
statusIcon.setImageDrawable(
context.getResources().getDrawable(R.drawable.status_signature_revoked_cutout));
statusIcon.setColorFilter(context.getResources().getColor(R.color.android_red_dark),
PorterDuff.Mode.SRC_ATOP);
if (statusText != null) {
statusText.setTextColor(context.getResources().getColor(R.color.android_red_dark));
}
break;
}
case STATE_NOT_ENCRYPTED: {
statusIcon.setImageDrawable(
context.getResources().getDrawable(R.drawable.status_lock_open));
statusIcon.setColorFilter(context.getResources().getColor(R.color.android_red_dark),
PorterDuff.Mode.SRC_ATOP);
if (statusText != null) {
statusText.setTextColor(context.getResources().getColor(R.color.android_red_dark));
}
break;
}
case STATE_NOT_SIGNED: {
statusIcon.setImageDrawable(
context.getResources().getDrawable(R.drawable.status_signature_unknown_cutout));
statusIcon.setColorFilter(context.getResources().getColor(R.color.android_red_dark),
PorterDuff.Mode.SRC_ATOP);
if (statusText != null) {
statusText.setTextColor(context.getResources().getColor(R.color.android_red_dark));
}
break;
}
case STATE_INVALID: {
statusIcon.setImageDrawable(
context.getResources().getDrawable(R.drawable.status_signature_invalid_cutout));
statusIcon.setColorFilter(context.getResources().getColor(R.color.android_red_dark),
PorterDuff.Mode.SRC_ATOP);
if (statusText != null) {
statusText.setTextColor(context.getResources().getColor(R.color.android_red_dark));
}
break;
}
/** special **/
case STATE_UNAVAILABLE: {
statusIcon.setImageDrawable(
context.getResources().getDrawable(R.drawable.status_signature_invalid_cutout));
statusIcon.setColorFilter(context.getResources().getColor(R.color.bg_gray),
PorterDuff.Mode.SRC_ATOP);
if (statusText != null) {
statusText.setTextColor(context.getResources().getColor(R.color.bg_gray));
}
break;
}
}
}