diff options
7 files changed, 155 insertions, 84 deletions
| diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java index e409e1bc8..e32677c7a 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java @@ -56,6 +56,7 @@ import android.widget.TextView;  import org.sufficientlysecure.keychain.Constants;  import org.sufficientlysecure.keychain.R; +import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;  import org.sufficientlysecure.keychain.util.ExportHelper;  import org.sufficientlysecure.keychain.util.KeyUpdateHelper;  import org.sufficientlysecure.keychain.util.Preferences; @@ -572,16 +573,10 @@ public class KeyListFragment extends LoaderFragment                  // Note: order is important!                  if (isRevoked) { -                    h.mStatus.setImageDrawable( -                            getResources().getDrawable(R.drawable.status_signature_revoked_cutout)); -                    h.mStatus.setColorFilter(getResources().getColor(R.color.android_red_dark), -                            PorterDuff.Mode.SRC_ATOP); +                    KeyFormattingUtils.setStatusImage(getActivity(), h.mStatus, KeyFormattingUtils.STATE_REVOKED);                      h.mStatus.setVisibility(View.VISIBLE);                  } else if (isExpired) { -                    h.mStatus.setImageDrawable( -                            getResources().getDrawable(R.drawable.status_signature_expired_cutout)); -                    h.mStatus.setColorFilter(getResources().getColor(R.color.android_orange_dark), -                            PorterDuff.Mode.SRC_ATOP); +                    KeyFormattingUtils.setStatusImage(getActivity(), h.mStatus, KeyFormattingUtils.STATE_EXPIRED);                      h.mStatus.setVisibility(View.VISIBLE);                  } else if (isVerified) {                      if (cursor.getInt(KeyListFragment.INDEX_HAS_ANY_SECRET) != 0) { @@ -589,10 +584,7 @@ public class KeyListFragment extends LoaderFragment                          h.mStatus.setVisibility(View.GONE);                      } else {                          // this is a public key - show if it's verified -                        h.mStatus.setImageDrawable( -                                getResources().getDrawable(R.drawable.status_signature_verified_cutout)); -                        h.mStatus.setColorFilter(getResources().getColor(R.color.android_green_dark), -                                PorterDuff.Mode.SRC_ATOP); +                        KeyFormattingUtils.setStatusImage(getActivity(), h.mStatus, KeyFormattingUtils.STATE_VERIFIED);                          h.mStatus.setVisibility(View.VISIBLE);                      }                  } else { diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/util/KeyFormattingUtils.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/util/KeyFormattingUtils.java index dd389a587..dad1f19a8 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/util/KeyFormattingUtils.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/util/KeyFormattingUtils.java @@ -19,10 +19,14 @@  package org.sufficientlysecure.keychain.ui.util;  import android.content.Context; +import android.database.Cursor;  import android.graphics.Color; +import android.graphics.PorterDuff;  import android.text.Spannable;  import android.text.SpannableStringBuilder;  import android.text.style.ForegroundColorSpan; +import android.view.View; +import android.widget.ImageView;  import org.spongycastle.asn1.ASN1ObjectIdentifier;  import org.spongycastle.asn1.nist.NISTNamedCurves; @@ -330,4 +334,41 @@ public class KeyFormattingUtils {                  ((int) digest[2] + 256) % 256};      } +    public static final int STATE_REVOKED = 1; +    public static final int STATE_EXPIRED = 2; +    public static final int STATE_VERIFIED = 3; +    public static final int STATE_UNAVAILABLE = 4; + +    /** +     * returns true if status has been set, if false no status! +     */ +    public static void setStatusImage(Context context, ImageView statusView, 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( +                        context.getResources().getDrawable(R.drawable.status_signature_verified_cutout)); +                statusView.setColorFilter(context.getResources().getColor(R.color.android_green_dark), +                        PorterDuff.Mode.SRC_ATOP); +                break; +        } +    } +  } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/CertifyKeySpinner.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/CertifyKeySpinner.java index 7224c4b03..07f6529f1 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/CertifyKeySpinner.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/CertifyKeySpinner.java @@ -24,10 +24,13 @@ import android.os.Bundle;  import android.support.v4.content.CursorLoader;  import android.support.v4.content.Loader;  import android.util.AttributeSet; +import android.widget.ImageView; +  import org.sufficientlysecure.keychain.Constants;  import org.sufficientlysecure.keychain.provider.KeychainContract;  import org.sufficientlysecure.keychain.provider.KeychainDatabase;  import org.sufficientlysecure.keychain.provider.KeychainDatabase.Tables; +import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;  public class CertifyKeySpinner extends KeySpinner {      private long mHiddenMasterKeyId = Constants.key.none; @@ -61,22 +64,23 @@ public class CertifyKeySpinner extends KeySpinner {                  KeychainContract.KeyRings.MASTER_KEY_ID,                  KeychainContract.KeyRings.KEY_ID,                  KeychainContract.KeyRings.USER_ID, +                KeychainContract.KeyRings.IS_REVOKED,                  KeychainContract.KeyRings.IS_EXPIRED,                  KeychainContract.KeyRings.HAS_CERTIFY,                  KeychainContract.KeyRings.HAS_ANY_SECRET          };          String where = KeychainContract.KeyRings.HAS_ANY_SECRET + " = 1 AND " -                + KeychainContract.KeyRings.HAS_CERTIFY + " NOT NULL AND " -                + Tables.KEYS + "." + KeychainContract.KeyRings.IS_REVOKED + " = 0 AND " -                + KeychainContract.KeyRings.IS_EXPIRED + " = 0 AND " + KeychainDatabase.Tables.KEYS + "." -                + KeychainContract.KeyRings.MASTER_KEY_ID + " != " + mHiddenMasterKeyId; +                + KeychainDatabase.Tables.KEYS + "." + KeychainContract.KeyRings.MASTER_KEY_ID +                + " != " + mHiddenMasterKeyId;          // Now create and return a CursorLoader that will take care of          // creating a Cursor for the data being displayed.          return new CursorLoader(getContext(), baseUri, projection, where, null, null);      } +    private int mIndexHasCertify, mIndexIsRevoked, mIndexIsExpired; +      @Override      public void onLoadFinished(Loader<Cursor> loader, Cursor data) {          super.onLoadFinished(loader, data); @@ -84,6 +88,29 @@ public class CertifyKeySpinner extends KeySpinner {          if (mAdapter.getCount() == 2) {              setSelection(1);          } +        mIndexHasCertify = data.getColumnIndex(KeychainContract.KeyRings.HAS_CERTIFY); +        mIndexIsRevoked = data.getColumnIndex(KeychainContract.KeyRings.IS_REVOKED); +        mIndexIsExpired = data.getColumnIndex(KeychainContract.KeyRings.IS_EXPIRED); +    } + +    @Override +    boolean setStatus(Context context, Cursor cursor, ImageView statusView) { +        if (cursor.getInt(mIndexIsRevoked) != 0) { +            KeyFormattingUtils.setStatusImage(getContext(), statusView, KeyFormattingUtils.STATE_REVOKED); +            return false; +        } +        if (cursor.getInt(mIndexIsExpired) != 0) { +            KeyFormattingUtils.setStatusImage(getContext(), statusView, KeyFormattingUtils.STATE_EXPIRED); +            return false; +        } +        // don't invalidate the "None" entry, which is also null! +        if (cursor.getPosition() != 0 && cursor.isNull(mIndexHasCertify)) { +            KeyFormattingUtils.setStatusImage(getContext(), statusView, KeyFormattingUtils.STATE_UNAVAILABLE); +            return false; +        } + +        // valid key +        return true;      }  } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/KeySpinner.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/KeySpinner.java index 63287c799..df8250ab6 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/KeySpinner.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/KeySpinner.java @@ -29,6 +29,7 @@ import android.view.View;  import android.view.ViewGroup;  import android.widget.AdapterView;  import android.widget.BaseAdapter; +import android.widget.ImageView;  import android.widget.Spinner;  import android.widget.SpinnerAdapter;  import android.widget.TextView; @@ -139,21 +140,28 @@ public abstract class KeySpinner extends Spinner implements LoaderManager.Loader                  @Override                  public void bindView(View view, Context context, Cursor cursor) { +                    TextView vKeyName = (TextView) view.findViewById(R.id.keyspinner_key_name); +                    ImageView vKeyStatus = (ImageView) view.findViewById(R.id.keyspinner_key_status); +                    TextView vKeyEmail = (TextView) view.findViewById(R.id.keyspinner_key_email); +                    TextView vKeyId = (TextView) view.findViewById(R.id.keyspinner_key_id); +                      String[] userId = KeyRing.splitUserId(cursor.getString(mIndexUserId)); -                    TextView vKeyName = ((TextView) view.findViewById(R.id.keyspinner_key_name)); -                    TextView vKeyStatus = ((TextView) view.findViewById(R.id.keyspinner_key_status));                      vKeyName.setText(userId[2] == null ? userId[0] : (userId[0] + " (" + userId[2] + ")")); -                    ((TextView) view.findViewById(R.id.keyspinner_key_email)).setText(userId[1]); -                    ((TextView) view.findViewById(R.id.keyspinner_key_id)).setText(KeyFormattingUtils.convertKeyIdToHex(cursor.getLong(mIndexKeyId))); -                    String status = getStatus(getContext(), cursor); -                    if (status == null) { +                    vKeyEmail.setText(userId[1]); +                    vKeyId.setText(KeyFormattingUtils.convertKeyIdToHex(cursor.getLong(mIndexKeyId))); + +                    boolean valid = setStatus(getContext(), cursor, vKeyStatus); +                    if (valid) {                          vKeyName.setTextColor(Color.BLACK); +                        vKeyEmail.setTextColor(Color.BLACK); +                        vKeyId.setTextColor(Color.BLACK);                          vKeyStatus.setVisibility(View.GONE);                          view.setClickable(false);                      } else {                          vKeyName.setTextColor(Color.GRAY); +                        vKeyEmail.setTextColor(Color.GRAY); +                        vKeyId.setTextColor(Color.GRAY);                          vKeyStatus.setVisibility(View.VISIBLE); -                        vKeyStatus.setText(status);                          // this is a HACK. the trick is, if the element itself is clickable, the                          // click is not passed on to the view list                          view.setClickable(true); @@ -228,19 +236,19 @@ public abstract class KeySpinner extends Spinner implements LoaderManager.Loader                  }                  ((TextView) v.findViewById(R.id.keyspinner_key_name)).setText(R.string.choice_none);                  v.findViewById(R.id.keyspinner_key_email).setVisibility(View.GONE); -                v.findViewById(R.id.keyspinner_key_row).setVisibility(View.GONE); +                v.findViewById(R.id.keyspinner_key_id).setVisibility(View.GONE); +                v.findViewById(R.id.keyspinner_key_status).setVisibility(View.GONE);              } else {                  v = inner.getView(position - 1, convertView, parent);                  v.findViewById(R.id.keyspinner_key_email).setVisibility(View.VISIBLE); -                v.findViewById(R.id.keyspinner_key_row).setVisibility(View.VISIBLE); +                v.findViewById(R.id.keyspinner_key_id).setVisibility(View.VISIBLE);              }              return v;          }      } -    /** Return a string which should be the disabled status of the key, or null if the key is enabled. */ -    String getStatus(Context context, Cursor cursor) { -        return null; +    boolean setStatus(Context context, Cursor cursor, ImageView statusView) { +        return true;      }  } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/SignKeySpinner.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/SignKeySpinner.java index 648fcd4eb..ce1f7bb44 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/SignKeySpinner.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/SignKeySpinner.java @@ -24,9 +24,11 @@ import android.os.Bundle;  import android.support.v4.content.CursorLoader;  import android.support.v4.content.Loader;  import android.util.AttributeSet; +import android.widget.ImageView;  import org.sufficientlysecure.keychain.R;  import org.sufficientlysecure.keychain.provider.KeychainContract; +import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;  public class SignKeySpinner extends KeySpinner {      public SignKeySpinner(Context context) { @@ -69,25 +71,30 @@ public class SignKeySpinner extends KeySpinner {      private int mIndexHasSign, mIndexIsRevoked, mIndexIsExpired;      @Override -    public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) { -        super.onLoadFinished(loader, cursor); -        mIndexHasSign = cursor.getColumnIndex(KeychainContract.KeyRings.HAS_SIGN); -        mIndexIsRevoked = cursor.getColumnIndex(KeychainContract.KeyRings.IS_REVOKED); -        mIndexIsExpired = cursor.getColumnIndex(KeychainContract.KeyRings.IS_EXPIRED); +    public void onLoadFinished(Loader<Cursor> loader, Cursor data) { +        super.onLoadFinished(loader, data); +        mIndexHasSign = data.getColumnIndex(KeychainContract.KeyRings.HAS_SIGN); +        mIndexIsRevoked = data.getColumnIndex(KeychainContract.KeyRings.IS_REVOKED); +        mIndexIsExpired = data.getColumnIndex(KeychainContract.KeyRings.IS_EXPIRED);      }      @Override -    String getStatus(Context context, Cursor cursor) { +    boolean setStatus(Context context, Cursor cursor, ImageView statusView) {          if (cursor.getInt(mIndexIsRevoked) != 0) { -            return context.getString(R.string.revoked); -        } -        if (cursor.getInt(mIndexHasSign) == 0) { -            return context.getString(R.string.key_unavailable); +            KeyFormattingUtils.setStatusImage(getContext(), statusView, KeyFormattingUtils.STATE_REVOKED); +            return false;          }          if (cursor.getInt(mIndexIsExpired) != 0) { -            return context.getString(R.string.expired); +            KeyFormattingUtils.setStatusImage(getContext(), statusView, KeyFormattingUtils.STATE_EXPIRED); +            return false;          } -        return null; +        if (cursor.getInt(mIndexHasSign) == 0) { +            KeyFormattingUtils.setStatusImage(getContext(), statusView, KeyFormattingUtils.STATE_UNAVAILABLE); +            return false; +        } + +        // valid key +        return true;      }  } diff --git a/OpenKeychain/src/main/res/layout/key_list_item.xml b/OpenKeychain/src/main/res/layout/key_list_item.xml index 8d600464c..a7a195ffa 100644 --- a/OpenKeychain/src/main/res/layout/key_list_item.xml +++ b/OpenKeychain/src/main/res/layout/key_list_item.xml @@ -39,9 +39,9 @@      </LinearLayout>      <ImageView +        android:id="@+id/status_image"          android:layout_width="wrap_content"          android:layout_height="wrap_content" -        android:id="@+id/status_image"          android:layout_gravity="center"          android:src="@drawable/status_signature_revoked_cutout"          android:padding="16dp" /> diff --git a/OpenKeychain/src/main/res/layout/keyspinner_item.xml b/OpenKeychain/src/main/res/layout/keyspinner_item.xml index c519a92cc..e231664f3 100644 --- a/OpenKeychain/src/main/res/layout/keyspinner_item.xml +++ b/OpenKeychain/src/main/res/layout/keyspinner_item.xml @@ -1,63 +1,59 @@  <?xml version="1.0" encoding="utf-8"?>  <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" -    android:orientation="vertical" -    android:layout_width="wrap_content" -    android:padding="4dp" +    android:layout_width="match_parent" +    android:layout_height="wrap_content"      android:minHeight="24dp" -    android:layout_height="wrap_content"> +    android:gravity="center_vertical" +    android:singleLine="true" +    android:orientation="horizontal" +    android:descendantFocusability="blocksDescendants" +    android:focusable="false"> -    <TextView -        android:id="@+id/keyspinner_key_name" -        android:textColor="?android:attr/textColorSecondary" -        android:textSize="18sp" -        android:layout_width="wrap_content" -        android:layout_height="wrap_content" -        android:singleLine="true" -        android:ellipsize="end" /> - -    <TextView -        android:id="@+id/keyspinner_key_email" -        android:textColor="?android:attr/textColorTertiary" -        android:textSize="14sp" -        android:layout_width="wrap_content" +    <LinearLayout +        android:layout_width="0dip"          android:layout_height="wrap_content" -        android:singleLine="true" -        android:ellipsize="end" -        android:layout_marginTop="-4dip" -        android:text="alice@example.com" /> +        android:layout_gravity="center_vertical" +        android:layout_weight="1" +        android:focusable="true" +        android:orientation="vertical" +        android:paddingLeft="8dp" +        android:paddingRight="4dp" +        android:paddingTop="4dp" +        android:paddingBottom="4dp"> -    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" -                  android:orientation="horizontal" -                  android:layout_width="match_parent" -                  android:padding="4dp" -                  android:minHeight="24dp" -                  android:layout_height="wrap_content" -                  android:id="@+id/keyspinner_key_row"> +        <TextView +            android:id="@+id/keyspinner_key_name" +            android:layout_width="wrap_content" +            android:layout_height="wrap_content" +            android:text="@string/label_main_user_id" +            android:textAppearance="?android:attr/textAppearanceMedium" />          <TextView -            android:id="@+id/keyspinner_key_id" -            android:textColor="?android:attr/textColorTertiary" -            android:textSize="14sp" -            android:layout_width="0dip" +            android:id="@+id/keyspinner_key_email" +            android:layout_width="wrap_content"              android:layout_height="wrap_content"              android:singleLine="true"              android:ellipsize="end" -            android:typeface="monospace" -            android:layout_marginTop="-4dip" -            android:layout_weight="1"/> +            android:text="user@example.com" +            android:textAppearance="?android:attr/textAppearanceSmall" />          <TextView -            android:id="@+id/keyspinner_key_status" -            android:textColor="#e00" -            android:textSize="12sp" +            android:id="@+id/keyspinner_key_id" +            android:text="12345"              android:layout_width="wrap_content"              android:layout_height="wrap_content"              android:singleLine="true"              android:ellipsize="end" -            android:layout_gravity="right" -            android:text="status" -            android:visibility="gone"/> - +            android:typeface="monospace" +            android:textAppearance="?android:attr/textAppearanceSmall"/>      </LinearLayout> +    <ImageView +        android:id="@+id/keyspinner_key_status" +        android:layout_width="wrap_content" +        android:layout_height="wrap_content" +        android:layout_gravity="center" +        android:src="@drawable/status_signature_revoked_cutout" +        android:padding="16dp" /> +  </LinearLayout>
\ No newline at end of file | 
