From b4ac6cd33705070fbd834a73d00136ecaa5c1623 Mon Sep 17 00:00:00 2001 From: Vincent Breitmoser Date: Thu, 21 Jun 2018 14:24:52 +0200 Subject: [PATCH] Split up FlexibleKeyItem, re-add support for dummy item if user has no secret keys --- .../keychain/provider/KeychainDatabase.java | 22 +- .../keychain/ui/KeyListFragment.java | 42 +++- .../ui/adapter/FlexibleKeyDetailsItem.java | 237 ++++++++++++++++++ .../ui/adapter/FlexibleKeyDummyItem.java | 48 ++++ .../ui/adapter/FlexibleKeyHeader.java | 6 +- .../keychain/ui/adapter/FlexibleKeyItem.java | 236 ++--------------- .../ui/adapter/FlexibleKeyItemFactory.java | 5 +- .../src/main/res/layout/key_list_dummy.xml | 3 +- .../src/main/res/layout/key_list_item.xml | 2 - 9 files changed, 359 insertions(+), 242 deletions(-) create mode 100644 OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/FlexibleKeyDetailsItem.java create mode 100644 OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/FlexibleKeyDummyItem.java diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainDatabase.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainDatabase.java index 30192e3cc..e8a6c7472 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainDatabase.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/KeychainDatabase.java @@ -453,12 +453,28 @@ public class KeychainDatabase { } private void migrateUpdatedKeysToKeyMetadataTable(SupportSQLiteDatabase db) { - db.execSQL("ALTER TABLE updated_keys RENAME TO key_metadata;"); - db.execSQL("UPDATE key_metadata SET last_updated = last_updated * 1000;"); + try { + db.execSQL("ALTER TABLE updated_keys RENAME TO key_metadata;"); + db.execSQL("UPDATE key_metadata SET last_updated = last_updated * 1000;"); + } catch (SQLException e) { + if (Constants.DEBUG) { + Timber.e(e, "Ignoring migration exception, this probably happened before"); + return; + } + throw e; + } } private void renameApiAutocryptPeersTable(SupportSQLiteDatabase db) { - db.execSQL("ALTER TABLE api_autocrypt_peers RENAME TO autocrypt_peers;"); + try { + db.execSQL("ALTER TABLE api_autocrypt_peers RENAME TO autocrypt_peers;"); + } catch (SQLException e) { + if (Constants.DEBUG) { + Timber.e(e, "Ignoring migration exception, this probably happened before"); + return; + } + throw e; + } } public void onDowngrade(SupportSQLiteDatabase db, int oldVersion, int newVersion) { 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 77f51c37f..581a3b206 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java @@ -54,7 +54,6 @@ import eu.davidea.flexibleadapter.FlexibleAdapter; import eu.davidea.flexibleadapter.FlexibleAdapter.OnItemClickListener; import eu.davidea.flexibleadapter.FlexibleAdapter.OnItemLongClickListener; import eu.davidea.flexibleadapter.SelectableAdapter.Mode; -import eu.davidea.flexibleadapter.common.FlexibleItemDecoration; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.compatibility.ClipboardReflection; @@ -67,8 +66,11 @@ import org.sufficientlysecure.keychain.pgp.PgpHelper; import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings; import org.sufficientlysecure.keychain.provider.KeychainDatabase; import org.sufficientlysecure.keychain.service.BenchmarkInputParcel; +import org.sufficientlysecure.keychain.ui.adapter.FlexibleKeyDetailsItem; +import org.sufficientlysecure.keychain.ui.adapter.FlexibleKeyDummyItem; import org.sufficientlysecure.keychain.ui.adapter.FlexibleKeyHeader; import org.sufficientlysecure.keychain.ui.adapter.FlexibleKeyItem; +import org.sufficientlysecure.keychain.ui.adapter.FlexibleKeyItem.FlexibleSectionableKeyItem; import org.sufficientlysecure.keychain.ui.adapter.FlexibleKeyItemFactory; import org.sufficientlysecure.keychain.ui.base.CryptoOperationHelper; import org.sufficientlysecure.keychain.ui.base.RecyclerFragment; @@ -76,7 +78,6 @@ import org.sufficientlysecure.keychain.ui.keyview.ViewKeyActivity; import org.sufficientlysecure.keychain.ui.keyview.loader.AsyncTaskLiveData; import org.sufficientlysecure.keychain.ui.util.Notify; import org.sufficientlysecure.keychain.ui.util.Notify.Style; -import org.sufficientlysecure.keychain.ui.util.recyclerview.DividerItemDecoration; import org.sufficientlysecure.keychain.util.FabContainer; import org.sufficientlysecure.keychain.util.Preferences; import timber.log.Timber; @@ -163,7 +164,7 @@ public class KeyListFragment extends RecyclerFragment selectedPositions = adapter.getSelectedPositions(); long[] keyIds = new long[selectedPositions.size()]; for (int i = 0; i < selectedPositions.size(); i++) { - FlexibleKeyItem selectedItem = adapter.getItem(selectedPositions.get(i)); + FlexibleKeyDetailsItem selectedItem = adapter.getItem(selectedPositions.get(i), FlexibleKeyDetailsItem.class); if (selectedItem != null) { keyIds[i] = selectedItem.keyInfo.master_key_id(); } @@ -174,7 +175,7 @@ public class KeyListFragment extends RecyclerFragment adapter = getAdapter(); for (int position : adapter.getSelectedPositions()) { - FlexibleKeyItem item = adapter.getItem(position); + FlexibleKeyDetailsItem item = adapter.getItem(position, FlexibleKeyDetailsItem.class); if (item != null && item.keyInfo.has_any_secret()) { return true; } @@ -296,8 +297,14 @@ public class KeyListFragment extends RecyclerFragment + implements IFilterable { + public final UnifiedKeyInfo keyInfo; + + FlexibleKeyDetailsItem(UnifiedKeyInfo keyInfo, FlexibleKeyHeader header) { + super(header); + this.keyInfo = keyInfo; + + setSelectable(true); + } + + @Override + public int getLayoutRes() { + return R.layout.key_list_item; + } + + @Override + public FlexibleKeyItemViewHolder createViewHolder(View view, FlexibleAdapter adapter) { + return new FlexibleKeyItemViewHolder(view, adapter); + } + + @Override + public void bindViewHolder( + FlexibleAdapter adapter, FlexibleKeyItemViewHolder holder, int position, List payloads) { + String highlightString = adapter.getFilter(String.class); + holder.bind(keyInfo, highlightString); + } + + @Override + public boolean equals(Object o) { + if (o instanceof org.sufficientlysecure.keychain.ui.adapter.FlexibleKeyDetailsItem) { + org.sufficientlysecure.keychain.ui.adapter.FlexibleKeyDetailsItem + other = (org.sufficientlysecure.keychain.ui.adapter.FlexibleKeyDetailsItem) o; + return keyInfo.master_key_id() == other.keyInfo.master_key_id(); + } + return false; + } + + @Override + public int hashCode() { + long masterKeyId = keyInfo.master_key_id(); + return (int) (masterKeyId ^ (masterKeyId >>> 32)); + } + + @Override + public boolean filter(String constraint) { + String uidList = keyInfo.user_id_list(); + return constraint == null || (uidList != null && uidList.contains(constraint)); + } + + class FlexibleKeyItemViewHolder extends FlexibleViewHolder { + private static final long JUST_NOW_THRESHOLD = DateUtils.MINUTE_IN_MILLIS * 5; + + private final TextView vMainUserId; + private final TextView vMainUserIdRest; + private final TextView vCreationDate; + private final ImageView vStatusIcon; + private final ImageView vTrustIdIcon; + + FlexibleKeyItemViewHolder(View itemView, FlexibleAdapter adapter) { + super(itemView, adapter); + + vMainUserId = itemView.findViewById(R.id.key_list_item_name); + vMainUserIdRest = itemView.findViewById(R.id.key_list_item_email); + vStatusIcon = itemView.findViewById(R.id.key_list_item_status_icon); + vCreationDate = itemView.findViewById(R.id.key_list_item_creation); + vTrustIdIcon = itemView.findViewById(R.id.key_list_item_tid_icon); + } + + public void bind(UnifiedKeyInfo keyInfo, String highlightString) { + setEnabled(true); + + Context context = itemView.getContext(); + Highlighter highlighter = new Highlighter(context, highlightString); + + { // set name and stuff, common to both key types + if (keyInfo.name() == null) { + if (keyInfo.email() != null) { + vMainUserId.setText(highlighter.highlight(keyInfo.email())); + vMainUserIdRest.setVisibility(View.GONE); + } else { + vMainUserId.setText(R.string.user_id_no_name); + } + } else { + vMainUserId.setText(highlighter.highlight(keyInfo.name())); + // for some reason, this hangs for me + // FlexibleUtils.highlightText(vMainUserId, keyInfo.name(), highlightString); + if (keyInfo.email() != null) { + vMainUserIdRest.setText(highlighter.highlight(keyInfo.email())); + vMainUserIdRest.setVisibility(View.VISIBLE); + } else { + vMainUserIdRest.setVisibility(View.GONE); + } + } + } + + { // set edit button and status, specific by key type. Note: order is important! + int textColor; + if (keyInfo.is_revoked()) { + KeyFormattingUtils.setStatusImage( + context, + vStatusIcon, + null, + KeyFormattingUtils.State.REVOKED, + R.color.key_flag_gray + ); + + vStatusIcon.setVisibility(View.VISIBLE); + textColor = ContextCompat.getColor(context, R.color.key_flag_gray); + } else if (keyInfo.is_expired()) { + KeyFormattingUtils.setStatusImage( + context, + vStatusIcon, + null, + KeyFormattingUtils.State.EXPIRED, + R.color.key_flag_gray + ); + + vStatusIcon.setVisibility(View.VISIBLE); + textColor = ContextCompat.getColor(context, R.color.key_flag_gray); + } else if (!keyInfo.is_secure()) { + KeyFormattingUtils.setStatusImage( + context, + vStatusIcon, + null, + KeyFormattingUtils.State.INSECURE, + R.color.key_flag_gray + ); + + vStatusIcon.setVisibility(View.VISIBLE); + textColor = ContextCompat.getColor(context, R.color.key_flag_gray); + } else if (keyInfo.has_any_secret()) { + vStatusIcon.setVisibility(View.GONE); + textColor = FormattingUtils.getColorFromAttr(context, R.attr.colorText); + } else { + // this is a public key - show if it's verified + if (keyInfo.is_verified()) { + KeyFormattingUtils.setStatusImage( + context, + vStatusIcon, + KeyFormattingUtils.State.VERIFIED + ); + + vStatusIcon.setVisibility(View.VISIBLE); + } else { + KeyFormattingUtils.setStatusImage( + context, + vStatusIcon, + KeyFormattingUtils.State.UNVERIFIED + ); + + vStatusIcon.setVisibility(View.VISIBLE); + } + textColor = FormattingUtils.getColorFromAttr(context, R.attr.colorText); + } + + vMainUserId.setTextColor(textColor); + vMainUserIdRest.setTextColor(textColor); + + if (keyInfo.has_duplicate() || keyInfo.has_any_secret()) { + vCreationDate.setText(getSecretKeyReadableTime(context, keyInfo)); + vCreationDate.setTextColor(textColor); + vCreationDate.setVisibility(View.VISIBLE); + } else { + vCreationDate.setVisibility(View.GONE); + } + } + + { // set icons + + if (!keyInfo.has_any_secret() && !keyInfo.autocrypt_package_names().isEmpty()) { + String packageName = keyInfo.autocrypt_package_names().get(0); + Drawable drawable = PackageIconGetter.getInstance(context).getDrawableForPackageName(packageName); + if (drawable != null) { + vTrustIdIcon.setImageDrawable(drawable); + vTrustIdIcon.setVisibility(View.VISIBLE); + } else { + vTrustIdIcon.setVisibility(View.GONE); + } + } else { + vTrustIdIcon.setVisibility(View.GONE); + } + } + } + + + @NonNull + private String getSecretKeyReadableTime(Context context, UnifiedKeyInfo keyInfo) { + long creationMillis = keyInfo.creation() * 1000; + + boolean allowRelativeTimestamp = keyInfo.has_duplicate(); + if (allowRelativeTimestamp) { + long creationAgeMillis = System.currentTimeMillis() - creationMillis; + if (creationAgeMillis < JUST_NOW_THRESHOLD) { + return context.getString(R.string.label_key_created_just_now); + } + } + + String dateTime = DateUtils.formatDateTime(context, + creationMillis, + DateUtils.FORMAT_SHOW_DATE + | DateUtils.FORMAT_SHOW_TIME + | DateUtils.FORMAT_SHOW_YEAR + | DateUtils.FORMAT_ABBREV_MONTH); + return context.getString(R.string.label_key_created, dateTime); + } + } + +} diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/FlexibleKeyDummyItem.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/FlexibleKeyDummyItem.java new file mode 100644 index 000000000..a2f707983 --- /dev/null +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/FlexibleKeyDummyItem.java @@ -0,0 +1,48 @@ +package org.sufficientlysecure.keychain.ui.adapter; + + +import java.util.List; + +import android.view.View; + +import eu.davidea.flexibleadapter.FlexibleAdapter; +import eu.davidea.flexibleadapter.items.IFlexible; +import eu.davidea.viewholders.FlexibleViewHolder; +import org.sufficientlysecure.keychain.R; +import org.sufficientlysecure.keychain.ui.adapter.FlexibleKeyDummyItem.FlexibleKeyDummyViewHolder; +import org.sufficientlysecure.keychain.ui.adapter.FlexibleKeyItem.FlexibleSectionableKeyItem; + + +public class FlexibleKeyDummyItem extends FlexibleSectionableKeyItem { + FlexibleKeyDummyItem(FlexibleKeyHeader header) { + super(header); + + setSelectable(false); + } + + @Override + public int getLayoutRes() { + return R.layout.key_list_dummy; + } + + @Override + public boolean equals(Object o) { + return this == o; + } + + @Override + public FlexibleKeyDummyViewHolder createViewHolder(View view, FlexibleAdapter adapter) { + return new FlexibleKeyDummyViewHolder(view, adapter); + } + + @Override + public void bindViewHolder(FlexibleAdapter adapter, FlexibleKeyDummyViewHolder holder, + int position, List payloads) { + } + + class FlexibleKeyDummyViewHolder extends FlexibleViewHolder { + private FlexibleKeyDummyViewHolder(View view, FlexibleAdapter adapter) { + super(view, adapter, true); + } + } +} diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/FlexibleKeyHeader.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/FlexibleKeyHeader.java index fda48678f..2c2327e98 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/FlexibleKeyHeader.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/FlexibleKeyHeader.java @@ -9,18 +9,20 @@ import android.widget.TextView; import eu.davidea.flexibleadapter.FlexibleAdapter; import eu.davidea.flexibleadapter.items.AbstractHeaderItem; import eu.davidea.flexibleadapter.items.IFlexible; +import eu.davidea.flexibleadapter.items.IHeader; import eu.davidea.viewholders.FlexibleViewHolder; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.ui.adapter.FlexibleKeyHeader.FlexibleHeaderViewHolder; -public class FlexibleKeyHeader extends AbstractHeaderItem { +public class FlexibleKeyHeader extends FlexibleKeyItem + implements IHeader { private final String sectionTitle; FlexibleKeyHeader(String sectionTitle) { + super(); this.sectionTitle = sectionTitle; setEnabled(false); - setSelectable(false); } @Override diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/FlexibleKeyItem.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/FlexibleKeyItem.java index cd9f8726e..3f4c0bd5f 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/FlexibleKeyItem.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/FlexibleKeyItem.java @@ -1,236 +1,30 @@ package org.sufficientlysecure.keychain.ui.adapter; -import java.util.List; +import android.support.v7.widget.RecyclerView; -import android.content.Context; -import android.graphics.drawable.Drawable; -import android.support.annotation.NonNull; -import android.support.v4.content.ContextCompat; -import android.text.format.DateUtils; -import android.view.View; -import android.widget.ImageView; -import android.widget.TextView; - -import eu.davidea.flexibleadapter.FlexibleAdapter; -import eu.davidea.flexibleadapter.items.AbstractSectionableItem; -import eu.davidea.flexibleadapter.items.IFilterable; -import eu.davidea.flexibleadapter.items.IFlexible; -import eu.davidea.viewholders.FlexibleViewHolder; -import org.sufficientlysecure.keychain.R; -import org.sufficientlysecure.keychain.model.Key.UnifiedKeyInfo; -import org.sufficientlysecure.keychain.ui.adapter.FlexibleKeyItem.FlexibleKeyItemViewHolder; -import org.sufficientlysecure.keychain.ui.util.FormattingUtils; -import org.sufficientlysecure.keychain.ui.util.Highlighter; -import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils; -import org.sufficientlysecure.keychain.ui.util.PackageIconGetter; +import eu.davidea.flexibleadapter.items.AbstractFlexibleItem; +import eu.davidea.flexibleadapter.items.ISectionable; -public class FlexibleKeyItem extends AbstractSectionableItem - implements IFilterable { - public final UnifiedKeyInfo keyInfo; +public abstract class FlexibleKeyItem extends AbstractFlexibleItem { - FlexibleKeyItem(UnifiedKeyInfo keyInfo, FlexibleKeyHeader header) { - super(header); - this.keyInfo = keyInfo; + public static abstract class FlexibleSectionableKeyItem + extends FlexibleKeyItem implements ISectionable { + FlexibleKeyHeader header; - setSelectable(true); - } - - @Override - public int getLayoutRes() { - return R.layout.key_list_item; - } - - @Override - public FlexibleKeyItemViewHolder createViewHolder(View view, FlexibleAdapter adapter) { - return new FlexibleKeyItemViewHolder(view, adapter); - } - - @Override - public void bindViewHolder( - FlexibleAdapter adapter, FlexibleKeyItemViewHolder holder, int position, List payloads) { - String highlightString = adapter.getFilter(String.class); - holder.bind(keyInfo, highlightString); - } - - @Override - public boolean equals(Object o) { - if (o instanceof FlexibleKeyItem) { - FlexibleKeyItem other = (FlexibleKeyItem) o; - return keyInfo.master_key_id() == other.keyInfo.master_key_id(); - } - return false; - } - - @Override - public int hashCode() { - long masterKeyId = keyInfo.master_key_id(); - return (int) (masterKeyId ^ (masterKeyId >>> 32)); - } - - @Override - public boolean filter(String constraint) { - String uidList = keyInfo.user_id_list(); - return constraint == null || (uidList != null && uidList.contains(constraint)); - } - - public class FlexibleKeyItemViewHolder extends FlexibleViewHolder { - private static final long JUST_NOW_THRESHOLD = DateUtils.MINUTE_IN_MILLIS * 5; - - private final TextView vMainUserId; - private final TextView vMainUserIdRest; - private final TextView vCreationDate; - private final ImageView vStatusIcon; - private final ImageView vTrustIdIcon; - - FlexibleKeyItemViewHolder(View itemView, FlexibleAdapter adapter) { - super(itemView, adapter); - - vMainUserId = itemView.findViewById(R.id.key_list_item_name); - vMainUserIdRest = itemView.findViewById(R.id.key_list_item_email); - vStatusIcon = itemView.findViewById(R.id.key_list_item_status_icon); - vCreationDate = itemView.findViewById(R.id.key_list_item_creation); - vTrustIdIcon = itemView.findViewById(R.id.key_list_item_tid_icon); + FlexibleSectionableKeyItem(FlexibleKeyHeader header) { + this.header = header; } - public void bind(UnifiedKeyInfo keyInfo, String highlightString) { - setEnabled(true); - - Context context = itemView.getContext(); - Highlighter highlighter = new Highlighter(context, highlightString); - - { // set name and stuff, common to both key types - if (keyInfo.name() == null) { - if (keyInfo.email() != null) { - vMainUserId.setText(highlighter.highlight(keyInfo.email())); - vMainUserIdRest.setVisibility(View.GONE); - } else { - vMainUserId.setText(R.string.user_id_no_name); - } - } else { - vMainUserId.setText(highlighter.highlight(keyInfo.name())); - // for some reason, this hangs for me - // FlexibleUtils.highlightText(vMainUserId, keyInfo.name(), highlightString); - if (keyInfo.email() != null) { - vMainUserIdRest.setText(highlighter.highlight(keyInfo.email())); - vMainUserIdRest.setVisibility(View.VISIBLE); - } else { - vMainUserIdRest.setVisibility(View.GONE); - } - } - } - - { // set edit button and status, specific by key type. Note: order is important! - int textColor; - if (keyInfo.is_revoked()) { - KeyFormattingUtils.setStatusImage( - context, - vStatusIcon, - null, - KeyFormattingUtils.State.REVOKED, - R.color.key_flag_gray - ); - - vStatusIcon.setVisibility(View.VISIBLE); - textColor = ContextCompat.getColor(context, R.color.key_flag_gray); - } else if (keyInfo.is_expired()) { - KeyFormattingUtils.setStatusImage( - context, - vStatusIcon, - null, - KeyFormattingUtils.State.EXPIRED, - R.color.key_flag_gray - ); - - vStatusIcon.setVisibility(View.VISIBLE); - textColor = ContextCompat.getColor(context, R.color.key_flag_gray); - } else if (!keyInfo.is_secure()) { - KeyFormattingUtils.setStatusImage( - context, - vStatusIcon, - null, - KeyFormattingUtils.State.INSECURE, - R.color.key_flag_gray - ); - - vStatusIcon.setVisibility(View.VISIBLE); - textColor = ContextCompat.getColor(context, R.color.key_flag_gray); - } else if (keyInfo.has_any_secret()) { - vStatusIcon.setVisibility(View.GONE); - textColor = FormattingUtils.getColorFromAttr(context, R.attr.colorText); - } else { - // this is a public key - show if it's verified - if (keyInfo.is_verified()) { - KeyFormattingUtils.setStatusImage( - context, - vStatusIcon, - KeyFormattingUtils.State.VERIFIED - ); - - vStatusIcon.setVisibility(View.VISIBLE); - } else { - KeyFormattingUtils.setStatusImage( - context, - vStatusIcon, - KeyFormattingUtils.State.UNVERIFIED - ); - - vStatusIcon.setVisibility(View.VISIBLE); - } - textColor = FormattingUtils.getColorFromAttr(context, R.attr.colorText); - } - - vMainUserId.setTextColor(textColor); - vMainUserIdRest.setTextColor(textColor); - - if (keyInfo.has_duplicate() || keyInfo.has_any_secret()) { - vCreationDate.setText(getSecretKeyReadableTime(context, keyInfo)); - vCreationDate.setTextColor(textColor); - vCreationDate.setVisibility(View.VISIBLE); - } else { - vCreationDate.setVisibility(View.GONE); - } - } - - { // set icons - - if (!keyInfo.has_any_secret() && !keyInfo.autocrypt_package_names().isEmpty()) { - String packageName = keyInfo.autocrypt_package_names().get(0); - Drawable drawable = PackageIconGetter.getInstance(context).getDrawableForPackageName(packageName); - if (drawable != null) { - vTrustIdIcon.setImageDrawable(drawable); - vTrustIdIcon.setVisibility(View.VISIBLE); - } else { - vTrustIdIcon.setVisibility(View.GONE); - } - } else { - vTrustIdIcon.setVisibility(View.GONE); - } - } + @Override + public FlexibleKeyHeader getHeader() { + return header; } - - @NonNull - private String getSecretKeyReadableTime(Context context, UnifiedKeyInfo keyInfo) { - long creationMillis = keyInfo.creation() * 1000; - - boolean allowRelativeTimestamp = keyInfo.has_duplicate(); - if (allowRelativeTimestamp) { - long creationAgeMillis = System.currentTimeMillis() - creationMillis; - if (creationAgeMillis < JUST_NOW_THRESHOLD) { - return context.getString(R.string.label_key_created_just_now); - } - } - - String dateTime = DateUtils.formatDateTime(context, - creationMillis, - DateUtils.FORMAT_SHOW_DATE - | DateUtils.FORMAT_SHOW_TIME - | DateUtils.FORMAT_SHOW_YEAR - | DateUtils.FORMAT_ABBREV_MONTH); - return context.getString(R.string.label_key_created, dateTime); + @Override + public void setHeader(FlexibleKeyHeader header) { + this.header = header; } } - } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/FlexibleKeyItemFactory.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/FlexibleKeyItemFactory.java index 7b89a64c1..abf5007a8 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/FlexibleKeyItemFactory.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/FlexibleKeyItemFactory.java @@ -27,9 +27,12 @@ public class FlexibleKeyItemFactory { if (unifiedKeyInfos == null) { return result; } + if (unifiedKeyInfos.isEmpty() || !unifiedKeyInfos.get(0).has_any_secret()) { + result.add(new FlexibleKeyDummyItem(myKeysHeader)); + } for (UnifiedKeyInfo unifiedKeyInfo : unifiedKeyInfos) { FlexibleKeyHeader header = getFlexibleKeyHeader(unifiedKeyInfo); - FlexibleKeyItem flexibleKeyItem = new FlexibleKeyItem(unifiedKeyInfo, header); + FlexibleKeyItem flexibleKeyItem = new FlexibleKeyDetailsItem(unifiedKeyInfo, header); result.add(flexibleKeyItem); } return result; diff --git a/OpenKeychain/src/main/res/layout/key_list_dummy.xml b/OpenKeychain/src/main/res/layout/key_list_dummy.xml index 69a477912..41477f1fd 100644 --- a/OpenKeychain/src/main/res/layout/key_list_dummy.xml +++ b/OpenKeychain/src/main/res/layout/key_list_dummy.xml @@ -5,7 +5,8 @@ android:minHeight="?android:attr/listPreferredItemHeight" android:gravity="center_vertical" android:orientation="horizontal" - android:focusable="true" + android:paddingLeft="12dp" + android:paddingRight="12dp" android:background="?android:selectableItemBackground">