diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/IdentityAdapter.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/IdentityAdapter.java index 860e2bf22..b8bbd43c0 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/IdentityAdapter.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/IdentityAdapter.java @@ -25,10 +25,10 @@ import android.content.Context; import android.graphics.Typeface; import android.os.Build; import android.os.Build.VERSION_CODES; +import android.support.annotation.NonNull; import android.support.v7.widget.RecyclerView; import android.view.LayoutInflater; import android.view.View; -import android.view.View.OnClickListener; import android.view.ViewGroup; import android.widget.ImageView; import android.widget.TextView; @@ -52,28 +52,28 @@ public class IdentityAdapter extends RecyclerView.Adapter { private final Context context; private final LayoutInflater layoutInflater; - private final boolean isSecret; private final IdentityClickListener identityClickListener; private List data; + private boolean isSecret; - public IdentityAdapter(Context context, boolean isSecret, IdentityClickListener identityClickListener) { + public IdentityAdapter(Context context, IdentityClickListener identityClickListener) { super(); this.layoutInflater = LayoutInflater.from(context); this.context = context; - this.isSecret = isSecret; this.identityClickListener = identityClickListener; } - public void setData(List data) { + public void setData(List data, boolean isSecret) { this.data = data; + this.isSecret = isSecret; notifyDataSetChanged(); } @Override - public void onBindViewHolder(ViewHolder holder, int position) { + public void onBindViewHolder(@NonNull ViewHolder holder, int position) { IdentityInfo info = data.get(position); int viewType = getItemViewType(position); @@ -90,8 +90,9 @@ public class IdentityAdapter extends RecyclerView.Adapter { } } + @NonNull @Override - public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { + public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { if (viewType == VIEW_TYPE_USER_ID) { return new UserIdViewHolder( layoutInflater.inflate(R.layout.view_key_identity_user_id, parent, false), identityClickListener); @@ -144,12 +145,9 @@ public class IdentityAdapter extends RecyclerView.Adapter { vTitle = view.findViewById(R.id.linked_id_title); vComment = view.findViewById(R.id.linked_id_comment); - view.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View v) { - if (identityClickListener != null) { - identityClickListener.onClickIdentity(getAdapterPosition()); - } + view.setOnClickListener(v -> { + if (identityClickListener != null) { + identityClickListener.onClickIdentity(getAdapterPosition()); } }); } @@ -213,19 +211,8 @@ public class IdentityAdapter extends RecyclerView.Adapter { vIcon = view.findViewById(R.id.trust_id_app_icon); vMore = view.findViewById(R.id.user_id_item_more); - view.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View v) { - identityClickListener.onClickIdentity(getAdapterPosition()); - } - }); - - vMore.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View v) { - identityClickListener.onClickIdentityMore(getAdapterPosition(), v); - } - }); + view.setOnClickListener(v -> identityClickListener.onClickIdentity(getAdapterPosition())); + vMore.setOnClickListener(v -> identityClickListener.onClickIdentityMore(getAdapterPosition(), v)); } public void bind(AutocryptPeerInfo info) { diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/keyview/KeyFragmentViewModel.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/keyview/KeyFragmentViewModel.java new file mode 100644 index 000000000..8144caa9c --- /dev/null +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/keyview/KeyFragmentViewModel.java @@ -0,0 +1,70 @@ +package org.sufficientlysecure.keychain.ui.keyview; + + +import java.util.List; + +import android.arch.lifecycle.LiveData; +import android.arch.lifecycle.Transformations; +import android.arch.lifecycle.ViewModel; +import android.content.Context; + +import org.sufficientlysecure.keychain.livedata.GenericLiveData; +import org.sufficientlysecure.keychain.model.KeyMetadata; +import org.sufficientlysecure.keychain.model.SubKey.UnifiedKeyInfo; +import org.sufficientlysecure.keychain.provider.KeyMetadataDao; +import org.sufficientlysecure.keychain.ui.keyview.loader.IdentityDao; +import org.sufficientlysecure.keychain.ui.keyview.loader.IdentityDao.IdentityInfo; +import org.sufficientlysecure.keychain.ui.keyview.loader.SubkeyStatusDao; +import org.sufficientlysecure.keychain.ui.keyview.loader.SubkeyStatusDao.KeySubkeyStatus; +import org.sufficientlysecure.keychain.ui.keyview.loader.SystemContactDao; +import org.sufficientlysecure.keychain.ui.keyview.loader.SystemContactDao.SystemContactInfo; + + +public class KeyFragmentViewModel extends ViewModel { + private LiveData> identityInfo; + private LiveData subkeyStatus; + private LiveData systemContactInfo; + private LiveData keyserverStatus; + + LiveData> getIdentityInfo(Context context, LiveData unifiedKeyInfoLiveData, + boolean showLinkedIds) { + if (identityInfo == null) { + IdentityDao identityDao = IdentityDao.getInstance(context); + identityInfo = Transformations.switchMap(unifiedKeyInfoLiveData, + (unifiedKeyInfo) -> new GenericLiveData<>(context, null, + () -> identityDao.getIdentityInfos(unifiedKeyInfo.master_key_id(), showLinkedIds))); + } + return identityInfo; + } + + LiveData getSubkeyStatus(Context context, LiveData unifiedKeyInfoLiveData) { + if (subkeyStatus == null) { + SubkeyStatusDao subkeyStatusDao = SubkeyStatusDao.getInstance(context); + subkeyStatus = Transformations.switchMap(unifiedKeyInfoLiveData, + (unifiedKeyInfo) -> new GenericLiveData<>(context, null, + () -> subkeyStatusDao.getSubkeyStatus(unifiedKeyInfo.master_key_id()))); + } + return subkeyStatus; + } + + LiveData getSystemContactInfo(Context context, LiveData unifiedKeyInfoLiveData) { + if (systemContactInfo == null) { + SystemContactDao systemContactDao = SystemContactDao.getInstance(context); + systemContactInfo = Transformations.switchMap(unifiedKeyInfoLiveData, + (unifiedKeyInfo) -> new GenericLiveData<>(context, null, + () -> systemContactDao.getSystemContactInfo(unifiedKeyInfo.master_key_id(), + unifiedKeyInfo.has_any_secret()))); + } + return systemContactInfo; + } + + LiveData getKeyserverStatus(Context context, LiveData unifiedKeyInfoLiveData) { + if (keyserverStatus == null) { + KeyMetadataDao keyMetadataDao = KeyMetadataDao.create(context); + keyserverStatus = Transformations.switchMap(unifiedKeyInfoLiveData, + (unifiedKeyInfo) -> new GenericLiveData<>(context, null, + () -> keyMetadataDao.getKeyMetadata(unifiedKeyInfo.master_key_id()))); + } + return keyserverStatus; + } +} diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/keyview/ViewKeyActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/keyview/ViewKeyActivity.java index 052c05a48..2eafd4806 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/keyview/ViewKeyActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/keyview/ViewKeyActivity.java @@ -313,7 +313,7 @@ public class ViewKeyActivity extends BaseSecurityTokenActivity implements } if (unifiedKeyInfoLiveData == null) { KeyRepository keyRepository = KeyRepository.create(context); - unifiedKeyInfoLiveData = new GenericLiveData<>(context, null, + unifiedKeyInfoLiveData = new GenericLiveData<>(context, KeyRings.buildGenericKeyRingUri(masterKeyId), () -> keyRepository.getUnifiedKeyInfo(masterKeyId)); } return unifiedKeyInfoLiveData; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/keyview/ViewKeyFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/keyview/ViewKeyFragment.java index f9a68c9be..2a7d83ad8 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/keyview/ViewKeyFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/keyview/ViewKeyFragment.java @@ -21,11 +21,13 @@ package org.sufficientlysecure.keychain.ui.keyview; import java.util.List; import android.arch.lifecycle.LiveData; -import android.arch.lifecycle.ViewModel; import android.arch.lifecycle.ViewModelProviders; +import android.content.Context; import android.content.Intent; +import android.net.Uri; import android.os.Bundle; import android.os.Handler; +import android.provider.ContactsContract; import android.support.annotation.NonNull; import android.support.v4.app.DialogFragment; import android.support.v4.app.Fragment; @@ -42,35 +44,43 @@ import org.sufficientlysecure.keychain.compatibility.DialogFragmentWorkaround; import org.sufficientlysecure.keychain.model.KeyMetadata; import org.sufficientlysecure.keychain.model.SubKey.UnifiedKeyInfo; import org.sufficientlysecure.keychain.operations.results.OperationResult; +import org.sufficientlysecure.keychain.pgp.CanonicalizedSecretKey.SecretKeyType; +import org.sufficientlysecure.keychain.provider.AutocryptPeerDao; +import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings; +import org.sufficientlysecure.keychain.ui.adapter.IdentityAdapter; +import org.sufficientlysecure.keychain.ui.adapter.IdentityAdapter.IdentityClickListener; +import org.sufficientlysecure.keychain.ui.dialog.UserIdInfoDialogFragment; import org.sufficientlysecure.keychain.ui.keyview.ViewKeyActivity.ViewKeyViewModel; +import org.sufficientlysecure.keychain.ui.keyview.loader.IdentityDao.AutocryptPeerInfo; import org.sufficientlysecure.keychain.ui.keyview.loader.IdentityDao.IdentityInfo; +import org.sufficientlysecure.keychain.ui.keyview.loader.IdentityDao.LinkedIdInfo; +import org.sufficientlysecure.keychain.ui.keyview.loader.IdentityDao.UserIdInfo; +import org.sufficientlysecure.keychain.ui.keyview.loader.SubkeyStatusDao.KeyHealthStatus; import org.sufficientlysecure.keychain.ui.keyview.loader.SubkeyStatusDao.KeySubkeyStatus; +import org.sufficientlysecure.keychain.ui.keyview.loader.SubkeyStatusDao.SubKeyItem; import org.sufficientlysecure.keychain.ui.keyview.loader.SystemContactDao.SystemContactInfo; -import org.sufficientlysecure.keychain.ui.keyview.presenter.IdentitiesPresenter; -import org.sufficientlysecure.keychain.ui.keyview.presenter.KeyHealthPresenter; -import org.sufficientlysecure.keychain.ui.keyview.presenter.KeyserverStatusPresenter; -import org.sufficientlysecure.keychain.ui.keyview.presenter.SystemContactPresenter; -import org.sufficientlysecure.keychain.ui.keyview.presenter.ViewKeyMvpView; import org.sufficientlysecure.keychain.ui.keyview.view.IdentitiesCardView; import org.sufficientlysecure.keychain.ui.keyview.view.KeyHealthView; +import org.sufficientlysecure.keychain.ui.keyview.view.KeyStatusList.KeyDisplayStatus; import org.sufficientlysecure.keychain.ui.keyview.view.KeyserverStatusView; import org.sufficientlysecure.keychain.ui.keyview.view.SystemContactCardView; +import org.sufficientlysecure.keychain.ui.linked.LinkedIdWizard; +import org.sufficientlysecure.keychain.util.Preferences; +import timber.log.Timber; -public class ViewKeyFragment extends Fragment implements ViewKeyMvpView, OnMenuItemClickListener { +public class ViewKeyFragment extends Fragment implements OnMenuItemClickListener { private IdentitiesCardView identitiesCardView; - private IdentitiesPresenter identitiesPresenter; + private SystemContactCardView systemContactCard; + private KeyHealthView keyStatusHealth; + private KeyserverStatusView keyserverStatusView; - SystemContactCardView systemContactCard; - SystemContactPresenter systemContactPresenter; - - KeyHealthView keyStatusHealth; - KeyserverStatusView keyStatusKeyserver; - - KeyHealthPresenter keyHealthPresenter; - KeyserverStatusPresenter keyserverStatusPresenter; + IdentityAdapter identitiesAdapter; private Integer displayedContextMenuPosition; + private UnifiedKeyInfo unifiedKeyInfo; + private KeySubkeyStatus subkeyStatus; + private boolean showingExpandedInfo; public static ViewKeyFragment newInstance() { return new ViewKeyFragment(); @@ -83,74 +93,233 @@ public class ViewKeyFragment extends Fragment implements ViewKeyMvpView, OnMenuI identitiesCardView = view.findViewById(R.id.card_identities); systemContactCard = view.findViewById(R.id.linked_system_contact_card); keyStatusHealth = view.findViewById(R.id.key_status_health); - keyStatusKeyserver = view.findViewById(R.id.key_status_keyserver); + keyserverStatusView = view.findViewById(R.id.key_status_keyserver); + + identitiesAdapter = new IdentityAdapter(requireContext(), new IdentityClickListener() { + @Override + public void onClickIdentity(int position) { + showIdentityInfo(position); + } + + @Override + public void onClickIdentityMore(int position, View anchor) { + showIdentityContextMenu(position, anchor); + } + }); + identitiesCardView.setIdentitiesAdapter(identitiesAdapter); + + keyStatusHealth.setOnHealthClickListener((v) -> onKeyHealthClick()); return view; } - public static class KeyFragmentViewModel extends ViewModel { - private LiveData> identityInfo; - private LiveData subkeyStatus; - private LiveData systemContactInfo; - private LiveData keyserverStatus; - - LiveData> getIdentityInfo(IdentitiesPresenter identitiesPresenter) { - if (identityInfo == null) { - identityInfo = identitiesPresenter.getLiveDataInstance(); - } - return identityInfo; - } - - LiveData getSubkeyStatus(KeyHealthPresenter keyHealthPresenter) { - if (subkeyStatus == null) { - subkeyStatus = keyHealthPresenter.getLiveDataInstance(); - } - return subkeyStatus; - } - - LiveData getSystemContactInfo(SystemContactPresenter systemContactPresenter) { - if (systemContactInfo == null) { - systemContactInfo = systemContactPresenter.getLiveDataInstance(); - } - return systemContactInfo; - } - - LiveData getKeyserverStatus(KeyserverStatusPresenter keyserverStatusPresenter) { - if (keyserverStatus == null) { - keyserverStatus = keyserverStatusPresenter.getLiveDataInstance(); - } - return keyserverStatus; - } - } - @Override public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); + Context context = requireContext(); + ViewKeyViewModel viewKeyViewModel = ViewModelProviders.of(requireActivity()).get(ViewKeyViewModel.class); - viewKeyViewModel.getUnifiedKeyInfoLiveData(requireContext()).observe(this, this::onLoadUnifiedKeyInfo); + LiveData unifiedKeyInfoLiveData = viewKeyViewModel.getUnifiedKeyInfoLiveData(requireContext()); + + unifiedKeyInfoLiveData.observe(this, this::onLoadUnifiedKeyInfo); + + KeyFragmentViewModel model = ViewModelProviders.of(this).get(KeyFragmentViewModel.class); + + boolean showLinkedIds = Preferences.getPreferences(context).getExperimentalEnableLinkedIdentities(); + model.getIdentityInfo(context, unifiedKeyInfoLiveData, showLinkedIds).observe(this, this::onLoadIdentityInfo); + model.getKeyserverStatus(context, unifiedKeyInfoLiveData).observe(this, this::onLoadKeyMetadata); + model.getSystemContactInfo(context, unifiedKeyInfoLiveData).observe(this, this::onLoadSystemContact); + model.getSubkeyStatus(context, unifiedKeyInfoLiveData).observe(this, this::onLoadSubkeyStatus); + } + + private void onLoadSubkeyStatus(KeySubkeyStatus subkeyStatus) { + if (subkeyStatus == null) { + return; + } + + this.subkeyStatus = subkeyStatus; + + KeyHealthStatus keyHealthStatus = subkeyStatus.keyHealthStatus; + + boolean isInsecure = keyHealthStatus == KeyHealthStatus.INSECURE; + boolean isExpired = keyHealthStatus == KeyHealthStatus.EXPIRED; + if (isInsecure) { + boolean primaryKeySecurityProblem = subkeyStatus.keyCertify.mSecurityProblem != null; + if (primaryKeySecurityProblem) { + keyStatusHealth.setKeyStatus(keyHealthStatus); + keyStatusHealth.setPrimarySecurityProblem(subkeyStatus.keyCertify.mSecurityProblem); + keyStatusHealth.setShowExpander(false); + } else { + keyStatusHealth.setKeyStatus(keyHealthStatus); + keyStatusHealth.setShowExpander(false); + displayExpandedInfo(false); + } + } else if (isExpired) { + keyStatusHealth.setKeyStatus(keyHealthStatus); + keyStatusHealth.setPrimaryExpiryDate(subkeyStatus.keyCertify.mExpiry); + keyStatusHealth.setShowExpander(false); + keyStatusHealth.hideExpandedInfo(); + } else { + keyStatusHealth.setKeyStatus(keyHealthStatus); + keyStatusHealth.setShowExpander(keyHealthStatus != KeyHealthStatus.REVOKED); + keyStatusHealth.hideExpandedInfo(); + } + } + + private void displayExpandedInfo(boolean displayAll) { + SubKeyItem keyCertify = subkeyStatus.keyCertify; + SubKeyItem keySign = subkeyStatus.keysSign.isEmpty() ? null : subkeyStatus.keysSign.get(0); + SubKeyItem keyEncrypt = subkeyStatus.keysEncrypt.isEmpty() ? null : subkeyStatus.keysEncrypt.get(0); + + KeyDisplayStatus certDisplayStatus = getKeyDisplayStatus(keyCertify); + KeyDisplayStatus signDisplayStatus = getKeyDisplayStatus(keySign); + KeyDisplayStatus encryptDisplayStatus = getKeyDisplayStatus(keyEncrypt); + + if (!displayAll) { + if (certDisplayStatus == KeyDisplayStatus.OK) { + certDisplayStatus = null; + } + if (certDisplayStatus == KeyDisplayStatus.INSECURE) { + signDisplayStatus = null; + encryptDisplayStatus = null; + } + if (signDisplayStatus == KeyDisplayStatus.OK) { + signDisplayStatus = null; + } + if (encryptDisplayStatus == KeyDisplayStatus.OK) { + encryptDisplayStatus = null; + } + } + + keyStatusHealth.showExpandedState(certDisplayStatus, signDisplayStatus, encryptDisplayStatus); + } + + private void onKeyHealthClick() { + if (showingExpandedInfo) { + showingExpandedInfo = false; + keyStatusHealth.hideExpandedInfo(); + } else { + showingExpandedInfo = true; + displayExpandedInfo(true); + } + } + + private KeyDisplayStatus getKeyDisplayStatus(SubKeyItem subKeyItem) { + if (subKeyItem == null) { + return KeyDisplayStatus.UNAVAILABLE; + } + + if (subKeyItem.mIsRevoked) { + return KeyDisplayStatus.REVOKED; + } + if (subKeyItem.mIsExpired) { + return KeyDisplayStatus.EXPIRED; + } + if (subKeyItem.mSecurityProblem != null) { + return KeyDisplayStatus.INSECURE; + } + if (subKeyItem.mSecretKeyType == SecretKeyType.GNU_DUMMY) { + return KeyDisplayStatus.STRIPPED; + } + if (subKeyItem.mSecretKeyType == SecretKeyType.DIVERT_TO_CARD) { + return KeyDisplayStatus.DIVERT; + } + + return KeyDisplayStatus.OK; } private void onLoadUnifiedKeyInfo(UnifiedKeyInfo unifiedKeyInfo) { - KeyFragmentViewModel model = ViewModelProviders.of(this).get(KeyFragmentViewModel.class); + if (unifiedKeyInfo == null) { + return; + } - identitiesPresenter = new IdentitiesPresenter( - getContext(), identitiesCardView, this, unifiedKeyInfo.master_key_id(), unifiedKeyInfo.has_any_secret()); - model.getIdentityInfo(identitiesPresenter).observe(this, identitiesPresenter); + Context context = requireContext(); - systemContactPresenter = new SystemContactPresenter( - getContext(), systemContactCard, unifiedKeyInfo.master_key_id(), unifiedKeyInfo.has_any_secret()); - model.getSystemContactInfo(systemContactPresenter).observe(this, systemContactPresenter); + this.unifiedKeyInfo = unifiedKeyInfo; - keyHealthPresenter = new KeyHealthPresenter(getContext(), keyStatusHealth, unifiedKeyInfo.master_key_id()); - model.getSubkeyStatus(keyHealthPresenter).observe(this, keyHealthPresenter); - - keyserverStatusPresenter = new KeyserverStatusPresenter( - getContext(), keyStatusKeyserver, unifiedKeyInfo.master_key_id(), unifiedKeyInfo.has_any_secret()); - model.getKeyserverStatus(keyserverStatusPresenter).observe(this, keyserverStatusPresenter); + boolean showLinkedIds = Preferences.getPreferences(context).getExperimentalEnableLinkedIdentities(); + boolean isSecret = unifiedKeyInfo.has_any_secret(); + identitiesCardView.setAddLinkedIdButtonVisible(showLinkedIds && isSecret); + identitiesCardView.setIdentitiesCardListener((v) -> addLinkedIdentity()); + } + + private void showIdentityInfo(final int position) { + IdentityInfo info = identitiesAdapter.getInfo(position); + if (info instanceof LinkedIdInfo) { + showLinkedId((LinkedIdInfo) info); + } else if (info instanceof UserIdInfo) { + showUserIdInfo((UserIdInfo) info); + } else if (info instanceof AutocryptPeerInfo) { + Intent autocryptPeerIntent = ((AutocryptPeerInfo) info).getAutocryptPeerIntent(); + if (autocryptPeerIntent != null) { + startActivity(autocryptPeerIntent); + } + } + } + + private void showIdentityContextMenu(int position, View anchor) { + showContextMenu(position, anchor); + } + + private void showLinkedId(final LinkedIdInfo info) { + LinkedIdViewFragment frag = LinkedIdViewFragment.newInstance(info.getMasterKeyId(), info.getRank(), unifiedKeyInfo.has_any_secret()); + + switchToFragment(frag, "linked_id"); + } + + private void showUserIdInfo(UserIdInfo info) { + if (!unifiedKeyInfo.has_any_secret()) { + UserIdInfoDialogFragment dialogFragment = UserIdInfoDialogFragment.newInstance(false, info.isVerified()); + showDialogFragment(dialogFragment, "userIdInfoDialog"); + } + } + + private void addLinkedIdentity() { + Intent intent = new Intent(requireContext(), LinkedIdWizard.class); + intent.setData(KeyRings.buildUnifiedKeyRingUri(unifiedKeyInfo.master_key_id())); + startActivity(intent); + } + + public void onClickForgetIdentity(int position) { + AutocryptPeerInfo info = (AutocryptPeerInfo) identitiesAdapter.getInfo(position); + if (info == null) { + Timber.e("got a 'forget' click on a bad trust id"); + return; + } + + AutocryptPeerDao.getInstance(requireContext()).deleteByIdentifier(info.getPackageName(), info.getIdentity()); + } + + private void onLoadIdentityInfo(List identityInfos) { + identitiesAdapter.setData(identityInfos, unifiedKeyInfo.has_any_secret()); + } + + private void onLoadSystemContact(SystemContactInfo systemContactInfo) { + if (systemContactInfo == null) { + systemContactCard.hideLinkedSystemContact(); + return; + } + + systemContactCard.showLinkedSystemContact(systemContactInfo.contactName, systemContactInfo.contactPicture); + systemContactCard.setSystemContactClickListener((v) -> launchAndroidContactActivity(systemContactInfo.contactId)); + } + + private void onLoadKeyMetadata(KeyMetadata keyMetadata) { + if (keyMetadata == null) { + keyserverStatusView.setDisplayStatusUnknown(); + } else if (keyMetadata.hasBeenUpdated()) { + if (keyMetadata.isPublished()) { + keyserverStatusView.setDisplayStatusPublished(); + } else { + keyserverStatusView.setDisplayStatusNotPublished(); + } + keyserverStatusView.setLastUpdated(keyMetadata.last_updated()); + } else { + keyserverStatusView.setDisplayStatusUnknown(); + } } - @Override public void switchToFragment(final Fragment frag, final String backStackName) { new Handler().post(() -> requireFragmentManager().beginTransaction() .setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE) @@ -170,18 +339,11 @@ public class ViewKeyFragment extends Fragment implements ViewKeyMvpView, OnMenuI } } - @Override - public void startActivityAndShowResultSnackbar(Intent intent) { - startActivityForResult(intent, 0); - } - - @Override public void showDialogFragment(final DialogFragment dialogFragment, final String tag) { DialogFragmentWorkaround.INTERFACE.runnableRunDelayed( () -> dialogFragment.show(requireFragmentManager(), tag)); } - @Override public void showContextMenu(int position, View anchor) { displayedContextMenuPosition = position; @@ -202,10 +364,17 @@ public class ViewKeyFragment extends Fragment implements ViewKeyMvpView, OnMenuI case R.id.autocrypt_forget: int position = displayedContextMenuPosition; displayedContextMenuPosition = null; - identitiesPresenter.onClickForgetIdentity(position); + onClickForgetIdentity(position); return true; } return false; } + + private void launchAndroidContactActivity(long contactId) { + Intent intent = new Intent(Intent.ACTION_VIEW); + Uri uri = Uri.withAppendedPath(ContactsContract.Contacts.CONTENT_URI, String.valueOf(contactId)); + intent.setData(uri); + startActivity(intent); + } } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/keyview/loader/IdentityDao.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/keyview/loader/IdentityDao.java index 0d7c06596..b802c16cd 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/keyview/loader/IdentityDao.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/keyview/loader/IdentityDao.java @@ -71,7 +71,7 @@ public class IdentityDao { this.autocryptPeerDao = autocryptPeerDao; } - List getIdentityInfos(long masterKeyId, boolean showLinkedIds) { + public List getIdentityInfos(long masterKeyId, boolean showLinkedIds) { ArrayList identities = new ArrayList<>(); if (showLinkedIds) { @@ -95,11 +95,11 @@ public class IdentityDao { if (associatedUserIdInfo != null) { int position = identities.indexOf(associatedUserIdInfo); AutocryptPeerInfo autocryptPeerInfo = AutocryptPeerInfo - .create(associatedUserIdInfo, autocryptId, packageName, drawable, autocryptPeerIntent); + .create(masterKeyId, associatedUserIdInfo, autocryptId, packageName, drawable, autocryptPeerIntent); identities.set(position, autocryptPeerInfo); } else { AutocryptPeerInfo autocryptPeerInfo = AutocryptPeerInfo - .create(autocryptId, packageName, drawable, autocryptPeerIntent); + .create(masterKeyId, autocryptId, packageName, drawable, autocryptPeerIntent); identities.add(autocryptPeerInfo); } } @@ -163,7 +163,7 @@ public class IdentityDao { try { UriAttribute uriAttribute = LinkedAttribute.fromAttributeData(userAttribute.attribute_data()); if (uriAttribute instanceof LinkedAttribute) { - return LinkedIdInfo.create(userAttribute.rank(), + return LinkedIdInfo.create(userAttribute.master_key_id(), userAttribute.rank(), userAttribute.isVerified(), userAttribute.is_primary(), (LinkedAttribute) uriAttribute); } } catch (IOException e) { @@ -180,7 +180,7 @@ public class IdentityDao { if (userId.name() != null || userId.email() != null) { IdentityInfo identityInfo = UserIdInfo.create( - userId.rank(), userId.isVerified(), userId.is_primary(), userId.name(), userId.email(), userId.comment()); + userId.master_key_id(), userId.rank(), userId.isVerified(), userId.is_primary(), userId.name(), userId.email(), userId.comment()); identities.add(identityInfo); } } @@ -188,6 +188,7 @@ public class IdentityDao { } public interface IdentityInfo { + long getMasterKeyId(); int getRank(); boolean isVerified(); boolean isPrimary(); @@ -195,6 +196,7 @@ public class IdentityDao { @AutoValue public abstract static class UserIdInfo implements IdentityInfo { + public abstract long getMasterKeyId(); public abstract int getRank(); public abstract boolean isVerified(); public abstract boolean isPrimary(); @@ -206,27 +208,29 @@ public class IdentityDao { @Nullable public abstract String getComment(); - static UserIdInfo create(int rank, boolean isVerified, boolean isPrimary, String name, String email, + static UserIdInfo create(long masterKeyId, int rank, boolean isVerified, boolean isPrimary, String name, String email, String comment) { - return new AutoValue_IdentityDao_UserIdInfo(rank, isVerified, isPrimary, name, email, comment); + return new AutoValue_IdentityDao_UserIdInfo(masterKeyId, rank, isVerified, isPrimary, name, email, comment); } } @AutoValue public abstract static class LinkedIdInfo implements IdentityInfo { + public abstract long getMasterKeyId(); public abstract int getRank(); public abstract boolean isVerified(); public abstract boolean isPrimary(); public abstract LinkedAttribute getLinkedAttribute(); - static LinkedIdInfo create(int rank, boolean isVerified, boolean isPrimary, LinkedAttribute linkedAttribute) { - return new AutoValue_IdentityDao_LinkedIdInfo(rank, isVerified, isPrimary, linkedAttribute); + static LinkedIdInfo create(long masterKeyId, int rank, boolean isVerified, boolean isPrimary, LinkedAttribute linkedAttribute) { + return new AutoValue_IdentityDao_LinkedIdInfo(masterKeyId, rank, isVerified, isPrimary, linkedAttribute); } } @AutoValue public abstract static class AutocryptPeerInfo implements IdentityInfo { + public abstract long getMasterKeyId(); public abstract int getRank(); public abstract boolean isVerified(); public abstract boolean isPrimary(); @@ -240,15 +244,14 @@ public class IdentityDao { @Nullable public abstract Intent getAutocryptPeerIntent(); - static AutocryptPeerInfo create(UserIdInfo userIdInfo, String autocryptPeer, String packageName, + static AutocryptPeerInfo create(long masterKeyId, UserIdInfo userIdInfo, String autocryptPeer, String packageName, Drawable appIcon, Intent autocryptPeerIntent) { - return new AutoValue_IdentityDao_AutocryptPeerInfo(userIdInfo.getRank(), userIdInfo.isVerified(), + return new AutoValue_IdentityDao_AutocryptPeerInfo(masterKeyId, userIdInfo.getRank(), userIdInfo.isVerified(), userIdInfo.isPrimary(), autocryptPeer, packageName, appIcon, userIdInfo, autocryptPeerIntent); } - static AutocryptPeerInfo create(String autocryptPeer, String packageName, Drawable appIcon, Intent autocryptPeerIntent) { - return new AutoValue_IdentityDao_AutocryptPeerInfo( - 0, false, false, autocryptPeer, packageName, appIcon, null, autocryptPeerIntent); + static AutocryptPeerInfo create(long masterKeyId, String autocryptPeer, String packageName, Drawable appIcon, Intent autocryptPeerIntent) { + return new AutoValue_IdentityDao_AutocryptPeerInfo(masterKeyId,0, false, false, autocryptPeer, packageName, appIcon, null, autocryptPeerIntent); } } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/keyview/loader/SubkeyStatusDao.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/keyview/loader/SubkeyStatusDao.java index 5ea41d801..494694032 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/keyview/loader/SubkeyStatusDao.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/keyview/loader/SubkeyStatusDao.java @@ -47,7 +47,7 @@ public class SubkeyStatusDao { this.keyRepository = keyRepository; } - KeySubkeyStatus getSubkeyStatus(long masterKeyId, Comparator comparator) { + public KeySubkeyStatus getSubkeyStatus(long masterKeyId) { SubKeyItem keyCertify = null; ArrayList keysSign = new ArrayList<>(); ArrayList keysEncrypt = new ArrayList<>(); @@ -73,10 +73,89 @@ public class SubkeyStatusDao { return null; } - Collections.sort(keysSign, comparator); - Collections.sort(keysEncrypt, comparator); + Collections.sort(keysSign, SUBKEY_COMPARATOR); + Collections.sort(keysEncrypt, SUBKEY_COMPARATOR); - return new KeySubkeyStatus(keyCertify, keysSign, keysEncrypt); + KeyHealthStatus keyHealthStatus = determineKeyHealthStatus(keyCertify, keysSign, keysEncrypt); + + return new KeySubkeyStatus(keyCertify, keysSign, keysEncrypt, keyHealthStatus); + } + + private KeyHealthStatus determineKeyHealthStatus(SubKeyItem keyCertify, + ArrayList keysSign, + ArrayList keysEncrypt) { + if (keyCertify.mIsRevoked) { + return KeyHealthStatus.REVOKED; + } + + if (keyCertify.mIsExpired) { + return KeyHealthStatus.EXPIRED; + } + + if (keyCertify.mSecurityProblem != null) { + return KeyHealthStatus.INSECURE; + } + + if (!keysSign.isEmpty() && keysEncrypt.isEmpty()) { + SubKeyItem keySign = keysSign.get(0); + if (!keySign.isValid()) { + return KeyHealthStatus.BROKEN; + } + + if (keySign.mSecurityProblem != null) { + return KeyHealthStatus.INSECURE; + } + + return KeyHealthStatus.SIGN_ONLY; + } + + if (keysSign.isEmpty() || keysEncrypt.isEmpty()) { + return KeyHealthStatus.BROKEN; + } + + SubKeyItem keySign = keysSign.get(0); + SubKeyItem keyEncrypt = keysEncrypt.get(0); + + if (keySign.mSecurityProblem != null && keySign.isValid() + || keyEncrypt.mSecurityProblem != null && keyEncrypt.isValid()) { + return KeyHealthStatus.INSECURE; + } + + if (!keySign.isValid() || !keyEncrypt.isValid()) { + return KeyHealthStatus.BROKEN; + } + + if (keyCertify.mSecretKeyType == SecretKeyType.GNU_DUMMY + && keySign.mSecretKeyType == SecretKeyType.GNU_DUMMY + && keyEncrypt.mSecretKeyType == SecretKeyType.GNU_DUMMY) { + return KeyHealthStatus.STRIPPED; + } + + if (keyCertify.mSecretKeyType == SecretKeyType.DIVERT_TO_CARD + && keySign.mSecretKeyType == SecretKeyType.DIVERT_TO_CARD + && keyEncrypt.mSecretKeyType == SecretKeyType.DIVERT_TO_CARD) { + return KeyHealthStatus.DIVERT; + } + + boolean containsDivertKeys = keyCertify.mSecretKeyType == SecretKeyType.DIVERT_TO_CARD || + keySign.mSecretKeyType == SecretKeyType.DIVERT_TO_CARD || + keyEncrypt.mSecretKeyType == SecretKeyType.DIVERT_TO_CARD; + if (containsDivertKeys) { + return KeyHealthStatus.DIVERT_PARTIAL; + } + + boolean containsStrippedKeys = keyCertify.mSecretKeyType == SecretKeyType.GNU_DUMMY + || keySign.mSecretKeyType == SecretKeyType.GNU_DUMMY + || keyEncrypt.mSecretKeyType == SecretKeyType.GNU_DUMMY; + if (containsStrippedKeys) { + return KeyHealthStatus.PARTIAL_STRIPPED; + } + + return KeyHealthStatus.OK; + } + + public enum KeyHealthStatus { + OK, DIVERT, DIVERT_PARTIAL, REVOKED, EXPIRED, INSECURE, SIGN_ONLY, STRIPPED, PARTIAL_STRIPPED, BROKEN } public static class KeySubkeyStatus { @@ -84,11 +163,14 @@ public class SubkeyStatusDao { public final SubKeyItem keyCertify; public final List keysSign; public final List keysEncrypt; + public final KeyHealthStatus keyHealthStatus; - KeySubkeyStatus(@NonNull SubKeyItem keyCertify, List keysSign, List keysEncrypt) { + KeySubkeyStatus(@NonNull SubKeyItem keyCertify, List keysSign, List keysEncrypt, + KeyHealthStatus keyHealthStatus) { this.keyCertify = keyCertify; this.keysSign = keysSign; this.keysEncrypt = keysEncrypt; + this.keyHealthStatus = keyHealthStatus; } } @@ -131,4 +213,24 @@ public class SubkeyStatusDao { return !mIsRevoked && !mIsExpired; } } + + private static final Comparator SUBKEY_COMPARATOR = (one, two) -> { + if (one == two) { + return 0; + } + // if one is valid and the other isn't, the valid one always comes first + if (one.isValid() ^ two.isValid()) { + return one.isValid() ? -1 : 1; + } + // compare usability, if one is "more usable" than the other, that one comes first + int usability = one.mSecretKeyType.compareUsability(two.mSecretKeyType); + if (usability != 0) { + return usability; + } + if ((one.mSecurityProblem == null) ^ (two.mSecurityProblem == null)) { + return one.mSecurityProblem == null ? -1 : 1; + } + // otherwise, the newer one comes first + return one.newerThan(two) ? -1 : 1; + }; } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/keyview/loader/SystemContactDao.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/keyview/loader/SystemContactDao.java index e666920c4..499f36347 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/keyview/loader/SystemContactDao.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/keyview/loader/SystemContactDao.java @@ -60,7 +60,7 @@ public class SystemContactDao { this.contentResolver = contentResolver; } - SystemContactInfo getSystemContactInfo(long masterKeyId, boolean isSecret) { + public SystemContactInfo getSystemContactInfo(long masterKeyId, boolean isSecret) { if (ContextCompat.checkSelfPermission(context, Manifest.permission.READ_CONTACTS) == PackageManager.PERMISSION_DENIED) { Timber.w(Constants.TAG, "loading linked system contact not possible READ_CONTACTS permission denied!"); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/keyview/loader/ViewKeyLiveData.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/keyview/loader/ViewKeyLiveData.java deleted file mode 100644 index 8d09591ea..000000000 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/keyview/loader/ViewKeyLiveData.java +++ /dev/null @@ -1,99 +0,0 @@ -package org.sufficientlysecure.keychain.ui.keyview.loader; - - -import java.util.Comparator; -import java.util.List; - -import android.content.Context; - -import org.sufficientlysecure.keychain.model.KeyMetadata; -import org.sufficientlysecure.keychain.provider.KeyMetadataDao; -import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings; -import org.sufficientlysecure.keychain.ui.keyview.loader.IdentityDao.IdentityInfo; -import org.sufficientlysecure.keychain.ui.keyview.loader.SubkeyStatusDao.KeySubkeyStatus; -import org.sufficientlysecure.keychain.ui.keyview.loader.SubkeyStatusDao.SubKeyItem; -import org.sufficientlysecure.keychain.ui.keyview.loader.SystemContactDao.SystemContactInfo; - - -public class ViewKeyLiveData { - public static class IdentityLiveData extends AsyncTaskLiveData> { - private final IdentityDao identityDao; - - private final long masterKeyId; - private final boolean showLinkedIds; - - public IdentityLiveData(Context context, long masterKeyId, boolean showLinkedIds) { - super(context, KeyRings.buildGenericKeyRingUri(masterKeyId)); - - this.identityDao = IdentityDao.getInstance(context); - - this.masterKeyId = masterKeyId; - this.showLinkedIds = showLinkedIds; - } - - @Override - public List asyncLoadData() { - return identityDao.getIdentityInfos(masterKeyId, showLinkedIds); - } - } - - public static class SubkeyStatusLiveData extends AsyncTaskLiveData { - private final SubkeyStatusDao subkeyStatusDao; - - private final long masterKeyId; - private final Comparator comparator; - - public SubkeyStatusLiveData(Context context, long masterKeyId, Comparator comparator) { - super(context, KeyRings.buildGenericKeyRingUri(masterKeyId)); - - this.subkeyStatusDao = SubkeyStatusDao.getInstance(context); - - this.masterKeyId = masterKeyId; - this.comparator = comparator; - } - - @Override - public KeySubkeyStatus asyncLoadData() { - return subkeyStatusDao.getSubkeyStatus(masterKeyId, comparator); - } - } - - public static class SystemContactInfoLiveData extends AsyncTaskLiveData { - private final SystemContactDao systemContactDao; - - private final long masterKeyId; - private final boolean isSecret; - - public SystemContactInfoLiveData(Context context, long masterKeyId, boolean isSecret) { - super(context, null); - - this.systemContactDao = SystemContactDao.getInstance(context); - - this.masterKeyId = masterKeyId; - this.isSecret = isSecret; - } - - @Override - public SystemContactInfo asyncLoadData() { - return systemContactDao.getSystemContactInfo(masterKeyId, isSecret); - } - } - - public static class KeyserverStatusLiveData extends AsyncTaskLiveData { - private final KeyMetadataDao keyMetadataDao; - - private final long masterKeyId; - - public KeyserverStatusLiveData(Context context, long masterKeyId) { - super(context, KeyRings.buildGenericKeyRingUri(masterKeyId)); - - this.keyMetadataDao = KeyMetadataDao.create(context); - this.masterKeyId = masterKeyId; - } - - @Override - public KeyMetadata asyncLoadData() { - return keyMetadataDao.getKeyMetadata(masterKeyId); - } - } -} diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/keyview/presenter/IdentitiesPresenter.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/keyview/presenter/IdentitiesPresenter.java deleted file mode 100644 index 0b043e91c..000000000 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/keyview/presenter/IdentitiesPresenter.java +++ /dev/null @@ -1,154 +0,0 @@ -/* - * Copyright (C) 2017 Schürmann & Breitmoser GbR - * - * 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 . - */ - -package org.sufficientlysecure.keychain.ui.keyview.presenter; - - -import java.util.List; - -import android.arch.lifecycle.LiveData; -import android.arch.lifecycle.Observer; -import android.content.Context; -import android.content.Intent; -import android.support.annotation.Nullable; -import android.view.View; - -import org.sufficientlysecure.keychain.provider.AutocryptPeerDao; -import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings; -import org.sufficientlysecure.keychain.ui.adapter.IdentityAdapter; -import org.sufficientlysecure.keychain.ui.adapter.IdentityAdapter.IdentityClickListener; -import org.sufficientlysecure.keychain.ui.dialog.UserIdInfoDialogFragment; -import org.sufficientlysecure.keychain.ui.keyview.LinkedIdViewFragment; -import org.sufficientlysecure.keychain.ui.keyview.loader.IdentityDao.AutocryptPeerInfo; -import org.sufficientlysecure.keychain.ui.keyview.loader.IdentityDao.IdentityInfo; -import org.sufficientlysecure.keychain.ui.keyview.loader.IdentityDao.LinkedIdInfo; -import org.sufficientlysecure.keychain.ui.keyview.loader.IdentityDao.UserIdInfo; -import org.sufficientlysecure.keychain.ui.keyview.loader.ViewKeyLiveData.IdentityLiveData; -import org.sufficientlysecure.keychain.ui.linked.LinkedIdWizard; -import org.sufficientlysecure.keychain.util.Preferences; -import timber.log.Timber; - - -public class IdentitiesPresenter implements Observer> { - private final Context context; - private final IdentitiesMvpView view; - private final ViewKeyMvpView viewKeyMvpView; - - private final IdentityAdapter identitiesAdapter; - - private final long masterKeyId; - private final boolean isSecret; - private final boolean showLinkedIds; - private AutocryptPeerDao autocryptPeerDao; - - public IdentitiesPresenter(Context context, IdentitiesMvpView view, ViewKeyMvpView viewKeyMvpView, - long masterKeyId, boolean isSecret) { - this.context = context; - this.view = view; - this.viewKeyMvpView = viewKeyMvpView; - this.autocryptPeerDao = AutocryptPeerDao.getInstance(context); - - this.masterKeyId = masterKeyId; - this.isSecret = isSecret; - - showLinkedIds = Preferences.getPreferences(context).getExperimentalEnableLinkedIdentities(); - - identitiesAdapter = new IdentityAdapter(context, isSecret, new IdentityClickListener() { - @Override - public void onClickIdentity(int position) { - showIdentityInfo(position); - } - - @Override - public void onClickIdentityMore(int position, View anchor) { - showIdentityContextMenu(position, anchor); - - } - }); - view.setIdentitiesAdapter(identitiesAdapter); - - view.setAddLinkedIdButtonVisible(showLinkedIds && isSecret); - - view.setIdentitiesCardListener(() -> addLinkedIdentity()); - } - - @Override - public void onChanged(@Nullable List identityInfos) { - identitiesAdapter.setData(identityInfos); - } - - private void showIdentityInfo(final int position) { - IdentityInfo info = identitiesAdapter.getInfo(position); - if (info instanceof LinkedIdInfo) { - showLinkedId((LinkedIdInfo) info); - } else if (info instanceof UserIdInfo) { - showUserIdInfo((UserIdInfo) info); - } else if (info instanceof AutocryptPeerInfo) { - Intent autocryptPeerIntent = ((AutocryptPeerInfo) info).getAutocryptPeerIntent(); - if (autocryptPeerIntent != null) { - viewKeyMvpView.startActivity(autocryptPeerIntent); - } - } - } - - private void showIdentityContextMenu(int position, View anchor) { - viewKeyMvpView.showContextMenu(position, anchor); - } - - private void showLinkedId(final LinkedIdInfo info) { - LinkedIdViewFragment frag = LinkedIdViewFragment.newInstance(masterKeyId, info.getRank(), isSecret); - - viewKeyMvpView.switchToFragment(frag, "linked_id"); - } - - private void showUserIdInfo(UserIdInfo info) { - if (!isSecret) { - UserIdInfoDialogFragment dialogFragment = UserIdInfoDialogFragment.newInstance(false, info.isVerified()); - viewKeyMvpView.showDialogFragment(dialogFragment, "userIdInfoDialog"); - } - } - - private void addLinkedIdentity() { - Intent intent = new Intent(context, LinkedIdWizard.class); - intent.setData(KeyRings.buildUnifiedKeyRingUri(masterKeyId)); - context.startActivity(intent); - } - - public void onClickForgetIdentity(int position) { - AutocryptPeerInfo info = (AutocryptPeerInfo) identitiesAdapter.getInfo(position); - if (info == null) { - Timber.e("got a 'forget' click on a bad trust id"); - return; - } - - autocryptPeerDao.deleteByIdentifier(info.getPackageName(), info.getIdentity()); - } - - public LiveData> getLiveDataInstance() { - return new IdentityLiveData(context, masterKeyId, showLinkedIds); - } - - public interface IdentitiesMvpView { - void setIdentitiesAdapter(IdentityAdapter userIdsAdapter); - void setIdentitiesCardListener(IdentitiesCardListener identitiesCardListener); - void setAddLinkedIdButtonVisible(boolean showLinkedIds); - } - - public interface IdentitiesCardListener { - void onClickAddIdentity(); - } -} \ No newline at end of file diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/keyview/presenter/KeyHealthPresenter.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/keyview/presenter/KeyHealthPresenter.java deleted file mode 100644 index 6c83be8f7..000000000 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/keyview/presenter/KeyHealthPresenter.java +++ /dev/null @@ -1,278 +0,0 @@ -/* - * Copyright (C) 2017 Schürmann & Breitmoser GbR - * - * 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 . - */ - -package org.sufficientlysecure.keychain.ui.keyview.presenter; - - -import java.util.Comparator; -import java.util.Date; - -import android.arch.lifecycle.LiveData; -import android.arch.lifecycle.Observer; -import android.content.Context; -import android.support.annotation.Nullable; - -import org.sufficientlysecure.keychain.pgp.CanonicalizedSecretKey.SecretKeyType; -import org.sufficientlysecure.keychain.pgp.SecurityProblem.KeySecurityProblem; -import org.sufficientlysecure.keychain.ui.keyview.loader.SubkeyStatusDao.KeySubkeyStatus; -import org.sufficientlysecure.keychain.ui.keyview.loader.SubkeyStatusDao.SubKeyItem; -import org.sufficientlysecure.keychain.ui.keyview.loader.ViewKeyLiveData.SubkeyStatusLiveData; -import org.sufficientlysecure.keychain.ui.keyview.view.KeyStatusList.KeyDisplayStatus; - - -public class KeyHealthPresenter implements Observer { - private static final Comparator SUBKEY_COMPARATOR = new Comparator() { - @Override - public int compare(SubKeyItem one, SubKeyItem two) { - // if one is valid and the other isn't, the valid one always comes first - if (one.isValid() ^ two.isValid()) { - return one.isValid() ? -1 : 1; - } - // compare usability, if one is "more usable" than the other, that one comes first - int usability = one.mSecretKeyType.compareUsability(two.mSecretKeyType); - if (usability != 0) { - return usability; - } - if ((one.mSecurityProblem == null) ^ (two.mSecurityProblem == null)) { - return one.mSecurityProblem == null ? -1 : 1; - } - // otherwise, the newer one comes first - return one.newerThan(two) ? -1 : 1; - } - }; - - private final Context context; - private final KeyHealthMvpView view; - private final long masterKeyId; - - private KeySubkeyStatus subkeyStatus; - private boolean showingExpandedInfo; - - - public KeyHealthPresenter(Context context, KeyHealthMvpView view, long masterKeyId) { - this.context = context; - this.view = view; - this.masterKeyId = masterKeyId; - - view.setOnHealthClickListener(new KeyHealthClickListener() { - @Override - public void onKeyHealthClick() { - KeyHealthPresenter.this.onKeyHealthClick(); - } - }); - } - - @Override - public void onChanged(@Nullable KeySubkeyStatus subkeyStatus) { - this.subkeyStatus = subkeyStatus; - if (subkeyStatus == null) { - return; - } - - KeyHealthStatus keyHealthStatus = determineKeyHealthStatus(subkeyStatus); - - boolean isInsecure = keyHealthStatus == KeyHealthStatus.INSECURE; - boolean isExpired = keyHealthStatus == KeyHealthStatus.EXPIRED; - if (isInsecure) { - boolean primaryKeySecurityProblem = subkeyStatus.keyCertify.mSecurityProblem != null; - if (primaryKeySecurityProblem) { - view.setKeyStatus(keyHealthStatus); - view.setPrimarySecurityProblem(subkeyStatus.keyCertify.mSecurityProblem); - view.setShowExpander(false); - } else { - view.setKeyStatus(keyHealthStatus); - view.setShowExpander(false); - displayExpandedInfo(false); - } - } else if (isExpired) { - view.setKeyStatus(keyHealthStatus); - view.setPrimaryExpiryDate(subkeyStatus.keyCertify.mExpiry); - view.setShowExpander(false); - view.hideExpandedInfo(); - } else { - view.setKeyStatus(keyHealthStatus); - view.setShowExpander(keyHealthStatus != KeyHealthStatus.REVOKED); - view.hideExpandedInfo(); - } - } - - private KeyHealthStatus determineKeyHealthStatus(KeySubkeyStatus subkeyStatus) { - SubKeyItem keyCertify = subkeyStatus.keyCertify; - if (keyCertify.mIsRevoked) { - return KeyHealthStatus.REVOKED; - } - - if (keyCertify.mIsExpired) { - return KeyHealthStatus.EXPIRED; - } - - if (keyCertify.mSecurityProblem != null) { - return KeyHealthStatus.INSECURE; - } - - if (!subkeyStatus.keysSign.isEmpty() && subkeyStatus.keysEncrypt.isEmpty()) { - SubKeyItem keySign = subkeyStatus.keysSign.get(0); - if (!keySign.isValid()) { - return KeyHealthStatus.BROKEN; - } - - if (keySign.mSecurityProblem != null) { - return KeyHealthStatus.INSECURE; - } - - return KeyHealthStatus.SIGN_ONLY; - } - - if (subkeyStatus.keysSign.isEmpty() || subkeyStatus.keysEncrypt.isEmpty()) { - return KeyHealthStatus.BROKEN; - } - - SubKeyItem keySign = subkeyStatus.keysSign.get(0); - SubKeyItem keyEncrypt = subkeyStatus.keysEncrypt.get(0); - - if (keySign.mSecurityProblem != null && keySign.isValid() - || keyEncrypt.mSecurityProblem != null && keyEncrypt.isValid()) { - return KeyHealthStatus.INSECURE; - } - - if (!keySign.isValid() || !keyEncrypt.isValid()) { - return KeyHealthStatus.BROKEN; - } - - if (keyCertify.mSecretKeyType == SecretKeyType.GNU_DUMMY - && keySign.mSecretKeyType == SecretKeyType.GNU_DUMMY - && keyEncrypt.mSecretKeyType == SecretKeyType.GNU_DUMMY) { - return KeyHealthStatus.STRIPPED; - } - - if (keyCertify.mSecretKeyType == SecretKeyType.DIVERT_TO_CARD - && keySign.mSecretKeyType == SecretKeyType.DIVERT_TO_CARD - && keyEncrypt.mSecretKeyType == SecretKeyType.DIVERT_TO_CARD) { - return KeyHealthStatus.DIVERT; - } - - boolean containsDivertKeys = keyCertify.mSecretKeyType == SecretKeyType.DIVERT_TO_CARD || - keySign.mSecretKeyType == SecretKeyType.DIVERT_TO_CARD || - keyEncrypt.mSecretKeyType == SecretKeyType.DIVERT_TO_CARD; - if (containsDivertKeys) { - return KeyHealthStatus.DIVERT_PARTIAL; - } - - boolean containsStrippedKeys = keyCertify.mSecretKeyType == SecretKeyType.GNU_DUMMY - || keySign.mSecretKeyType == SecretKeyType.GNU_DUMMY - || keyEncrypt.mSecretKeyType == SecretKeyType.GNU_DUMMY; - if (containsStrippedKeys) { - return KeyHealthStatus.PARTIAL_STRIPPED; - } - - return KeyHealthStatus.OK; - } - - private void onKeyHealthClick() { - if (showingExpandedInfo) { - showingExpandedInfo = false; - view.hideExpandedInfo(); - } else { - showingExpandedInfo = true; - displayExpandedInfo(true); - } - } - - private void displayExpandedInfo(boolean displayAll) { - SubKeyItem keyCertify = subkeyStatus.keyCertify; - SubKeyItem keySign = subkeyStatus.keysSign.isEmpty() ? null : subkeyStatus.keysSign.get(0); - SubKeyItem keyEncrypt = subkeyStatus.keysEncrypt.isEmpty() ? null : subkeyStatus.keysEncrypt.get(0); - - KeyDisplayStatus certDisplayStatus = getKeyDisplayStatus(keyCertify); - KeyDisplayStatus signDisplayStatus = getKeyDisplayStatus(keySign); - KeyDisplayStatus encryptDisplayStatus = getKeyDisplayStatus(keyEncrypt); - - if (!displayAll) { - if (certDisplayStatus == KeyDisplayStatus.OK) { - certDisplayStatus = null; - } - if (certDisplayStatus == KeyDisplayStatus.INSECURE) { - signDisplayStatus = null; - encryptDisplayStatus = null; - } - if (signDisplayStatus == KeyDisplayStatus.OK) { - signDisplayStatus = null; - } - if (encryptDisplayStatus == KeyDisplayStatus.OK) { - encryptDisplayStatus = null; - } - } - - view.showExpandedState(certDisplayStatus, signDisplayStatus, encryptDisplayStatus); - } - - private KeyDisplayStatus getKeyDisplayStatus(SubKeyItem subKeyItem) { - if (subKeyItem == null) { - return KeyDisplayStatus.UNAVAILABLE; - } - - if (subKeyItem.mIsRevoked) { - return KeyDisplayStatus.REVOKED; - } - if (subKeyItem.mIsExpired) { - return KeyDisplayStatus.EXPIRED; - } - if (subKeyItem.mSecurityProblem != null) { - return KeyDisplayStatus.INSECURE; - } - if (subKeyItem.mSecretKeyType == SecretKeyType.GNU_DUMMY) { - return KeyDisplayStatus.STRIPPED; - } - if (subKeyItem.mSecretKeyType == SecretKeyType.DIVERT_TO_CARD) { - return KeyDisplayStatus.DIVERT; - } - - return KeyDisplayStatus.OK; - } - - public LiveData getLiveDataInstance() { - return new SubkeyStatusLiveData(context, masterKeyId, SUBKEY_COMPARATOR); - } - - public enum KeyHealthStatus { - OK, DIVERT, DIVERT_PARTIAL, REVOKED, EXPIRED, INSECURE, SIGN_ONLY, STRIPPED, PARTIAL_STRIPPED, BROKEN - } - - public interface KeyHealthMvpView { - void setKeyStatus(KeyHealthStatus keyHealthStatus); - void setPrimarySecurityProblem(KeySecurityProblem securityProblem); - void setPrimaryExpiryDate(Date expiry); - - void setShowExpander(boolean showExpander); - void showExpandedState(KeyDisplayStatus certifyStatus, KeyDisplayStatus signStatus, - KeyDisplayStatus encryptStatus); - void hideExpandedInfo(); - - void setOnHealthClickListener(KeyHealthClickListener keyHealthClickListener); - - } - - public interface KeyStatusMvpView { - void setCertifyStatus(KeyDisplayStatus unavailable); - void setSignStatus(KeyDisplayStatus signStatus); - void setDecryptStatus(KeyDisplayStatus encryptStatus); - } - - public interface KeyHealthClickListener { - void onKeyHealthClick(); - } -} diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/keyview/presenter/KeyserverStatusPresenter.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/keyview/presenter/KeyserverStatusPresenter.java deleted file mode 100644 index c0548848f..000000000 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/keyview/presenter/KeyserverStatusPresenter.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright (C) 2017 Schürmann & Breitmoser GbR - * - * 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 . - */ - -package org.sufficientlysecure.keychain.ui.keyview.presenter; - - -import java.util.Date; - -import android.arch.lifecycle.LiveData; -import android.arch.lifecycle.Observer; -import android.content.Context; -import android.support.annotation.Nullable; - -import org.sufficientlysecure.keychain.model.KeyMetadata; -import org.sufficientlysecure.keychain.ui.keyview.loader.ViewKeyLiveData.KeyserverStatusLiveData; - - -public class KeyserverStatusPresenter implements Observer { - private final Context context; - private final KeyserverStatusMvpView view; - - private final long masterKeyId; - private final boolean isSecret; - - - public KeyserverStatusPresenter(Context context, KeyserverStatusMvpView view, long masterKeyId, - boolean isSecret) { - this.context = context; - this.view = view; - - this.masterKeyId = masterKeyId; - this.isSecret = isSecret; - } - - public LiveData getLiveDataInstance() { - return new KeyserverStatusLiveData(context, masterKeyId); - } - - @Override - public void onChanged(@Nullable KeyMetadata keyserverStatus) { - if (keyserverStatus == null) { - view.setDisplayStatusUnknown(); - return; - } - - if (keyserverStatus.hasBeenUpdated()) { - if (keyserverStatus.isPublished()) { - view.setDisplayStatusPublished(); - } else { - view.setDisplayStatusNotPublished(); - } - view.setLastUpdated(keyserverStatus.last_updated()); - } else { - view.setDisplayStatusUnknown(); - } - } - - public interface KeyserverStatusMvpView { - void setDisplayStatusPublished(); - void setDisplayStatusNotPublished(); - void setLastUpdated(Date lastUpdated); - void setDisplayStatusUnknown(); - } -} diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/keyview/presenter/SystemContactPresenter.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/keyview/presenter/SystemContactPresenter.java deleted file mode 100644 index 4c4dfbd43..000000000 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/keyview/presenter/SystemContactPresenter.java +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright (C) 2017 Schürmann & Breitmoser GbR - * - * 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 . - */ - -package org.sufficientlysecure.keychain.ui.keyview.presenter; - - -import android.arch.lifecycle.LiveData; -import android.arch.lifecycle.Observer; -import android.content.Context; -import android.content.Intent; -import android.graphics.Bitmap; -import android.net.Uri; -import android.provider.ContactsContract; -import android.support.annotation.Nullable; - -import org.sufficientlysecure.keychain.ui.keyview.loader.SystemContactDao.SystemContactInfo; -import org.sufficientlysecure.keychain.ui.keyview.loader.ViewKeyLiveData.SystemContactInfoLiveData; - - -public class SystemContactPresenter implements Observer { - private final Context context; - private final SystemContactMvpView view; - - private final long masterKeyId; - private final boolean isSecret; - - private long contactId; - - - public SystemContactPresenter(Context context, SystemContactMvpView view, long masterKeyId, boolean isSecret) { - this.context = context; - this.view = view; - - this.masterKeyId = masterKeyId; - this.isSecret = isSecret; - - view.setSystemContactClickListener(SystemContactPresenter.this::onSystemContactClick); - } - - public LiveData getLiveDataInstance() { - return new SystemContactInfoLiveData(context, masterKeyId, isSecret); - } - - @Override - public void onChanged(@Nullable SystemContactInfo systemContactInfo) { - if (systemContactInfo == null) { - view.hideLinkedSystemContact(); - return; - } - - this.contactId = systemContactInfo.contactId; - view.showLinkedSystemContact(systemContactInfo.contactName, systemContactInfo.contactPicture); - } - - private void onSystemContactClick() { - launchAndroidContactActivity(contactId, context); - } - - public interface SystemContactMvpView { - void setSystemContactClickListener(SystemContactClickListener systemContactClickListener); - - void showLinkedSystemContact(String contactName, Bitmap picture); - void hideLinkedSystemContact(); - } - - public interface SystemContactClickListener { - void onSystemContactClick(); - } - - private static void launchAndroidContactActivity(long contactId, Context context) { - Intent intent = new Intent(Intent.ACTION_VIEW); - Uri uri = Uri.withAppendedPath(ContactsContract.Contacts.CONTENT_URI, String.valueOf(contactId)); - intent.setData(uri); - context.startActivity(intent); - } -} diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/keyview/view/IdentitiesCardView.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/keyview/view/IdentitiesCardView.java index 26d8b5801..98b7ccdba 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/keyview/view/IdentitiesCardView.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/keyview/view/IdentitiesCardView.java @@ -29,15 +29,12 @@ import android.widget.Button; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.ui.adapter.IdentityAdapter; -import org.sufficientlysecure.keychain.ui.keyview.presenter.IdentitiesPresenter.IdentitiesCardListener; -import org.sufficientlysecure.keychain.ui.keyview.presenter.IdentitiesPresenter.IdentitiesMvpView; import org.sufficientlysecure.keychain.ui.util.recyclerview.DividerItemDecoration; -public class IdentitiesCardView extends CardView implements IdentitiesMvpView { +public class IdentitiesCardView extends CardView { private final RecyclerView vIdentities; - private IdentitiesCardListener identitiesCardListener; private final Button linkedIdsAddButton; public IdentitiesCardView(Context context, AttributeSet attrs) { @@ -50,24 +47,16 @@ public class IdentitiesCardView extends CardView implements IdentitiesMvpView { vIdentities.addItemDecoration(new DividerItemDecoration(context, DividerItemDecoration.VERTICAL_LIST, false)); linkedIdsAddButton = view.findViewById(R.id.view_key_card_linked_ids_add); - linkedIdsAddButton.setOnClickListener(v -> { - if (identitiesCardListener != null) { - identitiesCardListener.onClickAddIdentity(); - } - }); } - @Override public void setIdentitiesAdapter(IdentityAdapter identityAdapter) { vIdentities.setAdapter(identityAdapter); } - @Override - public void setIdentitiesCardListener(IdentitiesCardListener identitiesCardListener) { - this.identitiesCardListener = identitiesCardListener; + public void setIdentitiesCardListener(OnClickListener identitiesCardListener) { + linkedIdsAddButton.setOnClickListener(identitiesCardListener); } - @Override public void setAddLinkedIdButtonVisible(boolean show) { linkedIdsAddButton.setVisibility(show ? View.VISIBLE : View.GONE); } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/keyview/view/KeyHealthView.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/keyview/view/KeyHealthView.java index 191c6c6da..9b94195b3 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/keyview/view/KeyHealthView.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/keyview/view/KeyHealthView.java @@ -39,14 +39,12 @@ import org.sufficientlysecure.keychain.pgp.SecurityProblem.InsecureBitStrength; import org.sufficientlysecure.keychain.pgp.SecurityProblem.KeySecurityProblem; import org.sufficientlysecure.keychain.pgp.SecurityProblem.NotWhitelistedCurve; import org.sufficientlysecure.keychain.pgp.SecurityProblem.UnidentifiedKeyProblem; -import org.sufficientlysecure.keychain.ui.keyview.presenter.KeyHealthPresenter.KeyHealthClickListener; -import org.sufficientlysecure.keychain.ui.keyview.presenter.KeyHealthPresenter.KeyHealthMvpView; -import org.sufficientlysecure.keychain.ui.keyview.presenter.KeyHealthPresenter.KeyHealthStatus; +import org.sufficientlysecure.keychain.ui.keyview.loader.SubkeyStatusDao.KeyHealthStatus; import org.sufficientlysecure.keychain.ui.keyview.view.KeyStatusList.KeyDisplayStatus; import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils; -public class KeyHealthView extends LinearLayout implements KeyHealthMvpView, OnClickListener { +public class KeyHealthView extends LinearLayout implements OnClickListener { private final View vLayout; private final TextView vTitle, vSubtitle; private final ImageView vIcon; @@ -59,7 +57,7 @@ public class KeyHealthView extends LinearLayout implements KeyHealthMvpView, OnC private final View vExpiryLayout; private final TextView vExpiryText; - private KeyHealthClickListener keyHealthClickListener; + private OnClickListener keyHealthClickListener; public KeyHealthView(Context context, AttributeSet attrs) { super(context, attrs); @@ -125,7 +123,6 @@ public class KeyHealthView extends LinearLayout implements KeyHealthMvpView, OnC } } - @Override public void setKeyStatus(KeyHealthStatus keyHealthStatus) { switch (keyHealthStatus) { case OK: @@ -161,7 +158,6 @@ public class KeyHealthView extends LinearLayout implements KeyHealthMvpView, OnC } } - @Override public void setPrimarySecurityProblem(KeySecurityProblem securityProblem) { if (securityProblem == null) { vInsecureLayout.setVisibility(View.GONE); @@ -190,7 +186,6 @@ public class KeyHealthView extends LinearLayout implements KeyHealthMvpView, OnC } - @Override public void setPrimaryExpiryDate(Date expiry) { if (expiry == null) { vExpiryLayout.setVisibility(View.GONE); @@ -205,23 +200,20 @@ public class KeyHealthView extends LinearLayout implements KeyHealthMvpView, OnC @Override public void onClick(View view) { if (keyHealthClickListener != null) { - keyHealthClickListener.onKeyHealthClick(); + keyHealthClickListener.onClick(view); } } - @Override - public void setOnHealthClickListener(KeyHealthClickListener keyHealthClickListener) { + public void setOnHealthClickListener(OnClickListener keyHealthClickListener) { this.keyHealthClickListener = keyHealthClickListener; vLayout.setClickable(keyHealthClickListener != null); } - @Override public void setShowExpander(boolean showExpander) { vLayout.setClickable(showExpander); vExpander.setVisibility(showExpander ? View.VISIBLE : View.GONE); } - @Override public void showExpandedState(KeyDisplayStatus certifyStatus, KeyDisplayStatus signStatus, KeyDisplayStatus encryptStatus) { if (certifyStatus == null && signStatus == null && encryptStatus == null) { @@ -240,7 +232,6 @@ public class KeyHealthView extends LinearLayout implements KeyHealthMvpView, OnC } - @Override public void hideExpandedInfo() { showExpandedState(null, null, null); } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/keyview/view/KeyStatusList.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/keyview/view/KeyStatusList.java index e1a0c3e6a..b4bb2669d 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/keyview/view/KeyStatusList.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/keyview/view/KeyStatusList.java @@ -30,10 +30,9 @@ import android.widget.LinearLayout; import android.widget.TextView; import org.sufficientlysecure.keychain.R; -import org.sufficientlysecure.keychain.ui.keyview.presenter.KeyHealthPresenter.KeyStatusMvpView; -public class KeyStatusList extends LinearLayout implements KeyStatusMvpView { +public class KeyStatusList extends LinearLayout { private final TextView vCertText, vSignText, vDecryptText; private final ImageView vCertIcon, vSignIcon, vDecryptIcon; private final View vCertToken, vSignToken, vDecryptToken; @@ -107,7 +106,6 @@ public class KeyStatusList extends LinearLayout implements KeyStatusMvpView { } - @Override public void setCertifyStatus(KeyDisplayStatus keyDisplayStatus) { if (keyDisplayStatus == null) { vCertifyLayout.setVisibility(View.GONE); @@ -121,7 +119,6 @@ public class KeyStatusList extends LinearLayout implements KeyStatusMvpView { vCertifyLayout.setVisibility(View.VISIBLE); } - @Override public void setSignStatus(KeyDisplayStatus keyDisplayStatus) { if (keyDisplayStatus == null) { vSignLayout.setVisibility(View.GONE); @@ -134,7 +131,6 @@ public class KeyStatusList extends LinearLayout implements KeyStatusMvpView { vSignLayout.setVisibility(View.VISIBLE); } - @Override public void setDecryptStatus(KeyDisplayStatus keyDisplayStatus) { if (keyDisplayStatus == null) { vDecryptLayout.setVisibility(View.GONE); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/keyview/view/KeyserverStatusView.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/keyview/view/KeyserverStatusView.java index 641153bc1..1b353e729 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/keyview/view/KeyserverStatusView.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/keyview/view/KeyserverStatusView.java @@ -34,10 +34,9 @@ import android.widget.ImageView; import android.widget.TextView; import org.sufficientlysecure.keychain.R; -import org.sufficientlysecure.keychain.ui.keyview.presenter.KeyserverStatusPresenter.KeyserverStatusMvpView; -public class KeyserverStatusView extends FrameLayout implements KeyserverStatusMvpView { +public class KeyserverStatusView extends FrameLayout { private final View vLayout; private final TextView vTitle; private final TextView vSubtitle; @@ -75,23 +74,19 @@ public class KeyserverStatusView extends FrameLayout implements KeyserverStatusM } } - @Override public void setDisplayStatusPublished() { setDisplayStatus(KeyserverDisplayStatus.PUBLISHED); } - @Override public void setDisplayStatusNotPublished() { setDisplayStatus(KeyserverDisplayStatus.NOT_PUBLISHED); } - @Override public void setDisplayStatusUnknown() { setDisplayStatus(KeyserverDisplayStatus.UNKNOWN); vSubtitle.setText(R.string.keyserver_last_updated_never); } - @Override public void setLastUpdated(Date lastUpdated) { String lastUpdatedText = DateFormat.getMediumDateFormat(getContext()).format(lastUpdated); vSubtitle.setText(getResources().getString(R.string.keyserver_last_updated, lastUpdatedText)); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/keyview/view/SystemContactCardView.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/keyview/view/SystemContactCardView.java index 61fb46ed8..2cfd01440 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/keyview/view/SystemContactCardView.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/keyview/view/SystemContactCardView.java @@ -24,23 +24,18 @@ import android.support.v7.widget.CardView; import android.util.AttributeSet; import android.view.LayoutInflater; import android.view.View; -import android.view.View.OnClickListener; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.TextView; import org.sufficientlysecure.keychain.R; -import org.sufficientlysecure.keychain.ui.keyview.presenter.SystemContactPresenter.SystemContactClickListener; -import org.sufficientlysecure.keychain.ui.keyview.presenter.SystemContactPresenter.SystemContactMvpView; -public class SystemContactCardView extends CardView implements SystemContactMvpView, OnClickListener { +public class SystemContactCardView extends CardView { private LinearLayout vSystemContactLayout; private ImageView vSystemContactPicture; private TextView vSystemContactName; - private SystemContactClickListener systemContactClickListener; - public SystemContactCardView(Context context, AttributeSet attrs) { super(context, attrs); @@ -49,28 +44,16 @@ public class SystemContactCardView extends CardView implements SystemContactMvpV vSystemContactLayout = view.findViewById(R.id.system_contact_layout); vSystemContactName = view.findViewById(R.id.system_contact_name); vSystemContactPicture = view.findViewById(R.id.system_contact_picture); - - vSystemContactLayout.setOnClickListener(this); } - @Override - public void onClick(View view) { - if (systemContactClickListener != null) { - systemContactClickListener.onSystemContactClick(); - } - } - - @Override - public void setSystemContactClickListener(SystemContactClickListener systemContactClickListener) { - this.systemContactClickListener = systemContactClickListener; - vSystemContactLayout.setClickable(systemContactClickListener != null); + public void setSystemContactClickListener(OnClickListener onClickListener) { + vSystemContactLayout.setOnClickListener(onClickListener); } public void hideLinkedSystemContact() { setVisibility(View.GONE); } - @Override public void showLinkedSystemContact(String contactName, Bitmap picture) { vSystemContactName.setText(contactName); if (picture != null) {