From f34edae294d6892345db16049da9df2f860edd1c Mon Sep 17 00:00:00 2001 From: Vincent Breitmoser Date: Sun, 21 May 2017 03:07:35 +0200 Subject: [PATCH] use mvp pattern for linked id card --- .../keychain/ui/ViewKeyActivity.java | 10 +- .../keychain/ui/ViewKeyFragment.java | 177 ++++-------------- .../keychain/ui/adapter/LinkedIdsAdapter.java | 55 +----- .../ui/linked/LinkedIdViewFragment.java | 19 -- .../ui/widget/LinkedIdentitiesCardView.java | 91 +++++++++ .../ui/widget/LinkedIdentitiesPresenter.java | 139 ++++++++++++++ .../res/layout/linked_identities_card.xml | 50 +++++ .../src/main/res/layout/view_key_fragment.xml | 75 +------- 8 files changed, 326 insertions(+), 290 deletions(-) create mode 100644 OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/LinkedIdentitiesCardView.java create mode 100644 OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/LinkedIdentitiesPresenter.java create mode 100644 OpenKeychain/src/main/res/layout/linked_identities_card.xml diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java index 1c2bf024f..f1e61b219 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java @@ -84,7 +84,6 @@ import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings; import org.sufficientlysecure.keychain.service.ChangeUnlockParcel; import org.sufficientlysecure.keychain.service.ImportKeyringParcel; import org.sufficientlysecure.keychain.service.input.RequiredInputParcel; -import org.sufficientlysecure.keychain.ui.ViewKeyFragment.PostponeType; import org.sufficientlysecure.keychain.ui.base.BaseSecurityTokenActivity; import org.sufficientlysecure.keychain.ui.base.CryptoOperationHelper; import org.sufficientlysecure.keychain.ui.dialog.SetPassphraseDialogFragment; @@ -111,7 +110,6 @@ public class ViewKeyActivity extends BaseSecurityTokenActivity implements public static final String EXTRA_SECURITY_TOKEN_AID = "security_token_aid"; public static final String EXTRA_SECURITY_TOKEN_VERSION = "security_token_version"; public static final String EXTRA_SECURITY_TOKEN_FINGERPRINTS = "security_token_fingerprints"; - private boolean mLinkedTransition; @Retention(RetentionPolicy.SOURCE) @IntDef({REQUEST_QR_FINGERPRINT, REQUEST_BACKUP, REQUEST_CERTIFY, REQUEST_DELETE}) @@ -332,11 +330,6 @@ public class ViewKeyActivity extends BaseSecurityTokenActivity implements return; } - mLinkedTransition = getIntent().getBooleanExtra(EXTRA_LINKED_TRANSITION, false); - if (mLinkedTransition && Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { - postponeEnterTransition(); - } - if (Preferences.getPreferences(this).getExperimentalEnableKeybase()) { FragmentManager manager = getSupportFragmentManager(); final ViewKeyKeybaseFragment keybaseFrag = ViewKeyKeybaseFragment.newInstance(mDataUri); @@ -742,8 +735,7 @@ public class ViewKeyActivity extends BaseSecurityTokenActivity implements } // if the main fragment doesn't exist, or is not of the correct type, (re)create it - frag = ViewKeyFragment.newInstance(mMasterKeyId, mIsSecret, - mLinkedTransition ? PostponeType.LINKED : PostponeType.NONE); + frag = ViewKeyFragment.newInstance(mMasterKeyId, mIsSecret); // get rid of possible backstack, this fragment is always at the bottom manager.popBackStack("security_token", FragmentManager.POP_BACK_STACK_INCLUSIVE); manager.beginTransaction() diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyFragment.java index b5b897c58..034ffb7c8 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyFragment.java @@ -19,67 +19,49 @@ package org.sufficientlysecure.keychain.ui; -import java.io.IOException; - -import android.annotation.TargetApi; import android.content.Intent; import android.database.Cursor; import android.net.Uri; -import android.os.Build; -import android.os.Build.VERSION_CODES; import android.os.Bundle; import android.os.Handler; +import android.support.v4.app.Fragment; +import android.support.v4.app.FragmentTransaction; import android.support.v4.app.LoaderManager; import android.support.v4.content.Loader; -import android.support.v7.widget.CardView; -import android.transition.Fade; -import android.transition.Transition; -import android.transition.TransitionInflater; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; -import android.view.ViewTreeObserver.OnPreDrawListener; import android.widget.AdapterView; -import android.widget.AdapterView.OnItemClickListener; import android.widget.Button; import android.widget.LinearLayout; import android.widget.ListView; -import android.widget.TextView; -import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.compatibility.DialogFragmentWorkaround; import org.sufficientlysecure.keychain.operations.results.OperationResult; import org.sufficientlysecure.keychain.provider.KeychainContract; import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings; -import org.sufficientlysecure.keychain.ui.adapter.LinkedIdsAdapter; import org.sufficientlysecure.keychain.ui.adapter.UserIdsAdapter; import org.sufficientlysecure.keychain.ui.base.LoaderFragment; import org.sufficientlysecure.keychain.ui.dialog.UserIdInfoDialogFragment; -import org.sufficientlysecure.keychain.ui.linked.LinkedIdViewFragment; -import org.sufficientlysecure.keychain.ui.linked.LinkedIdViewFragment.OnIdentityLoadedListener; -import org.sufficientlysecure.keychain.ui.linked.LinkedIdWizard; import org.sufficientlysecure.keychain.ui.widget.KeyHealthCardView; import org.sufficientlysecure.keychain.ui.widget.KeyHealthPresenter; +import org.sufficientlysecure.keychain.ui.widget.LinkedIdentitiesCardView; +import org.sufficientlysecure.keychain.ui.widget.LinkedIdentitiesPresenter; +import org.sufficientlysecure.keychain.ui.widget.LinkedIdentitiesPresenter.LinkedIdsFragMvpView; import org.sufficientlysecure.keychain.ui.widget.SystemContactCardView; import org.sufficientlysecure.keychain.ui.widget.SystemContactPresenter; -import org.sufficientlysecure.keychain.util.Log; import org.sufficientlysecure.keychain.util.Preferences; -public class ViewKeyFragment extends LoaderFragment implements - LoaderManager.LoaderCallbacks { +public class ViewKeyFragment extends LoaderFragment implements LoaderManager.LoaderCallbacks, + LinkedIdsFragMvpView { public static final String ARG_MASTER_KEY_ID = "master_key_id"; public static final String ARG_IS_SECRET = "is_secret"; - public static final String ARG_POSTPONE_TYPE = "postpone_type"; private ListView mUserIds; - enum PostponeType { - NONE, LINKED - } - boolean mIsSecret = false; private static final int LOADER_ID_USER_IDS = 1; @@ -88,16 +70,11 @@ public class ViewKeyFragment extends LoaderFragment implements private static final int LOADER_ID_SUBKEY_STATUS = 4; private UserIdsAdapter mUserIdsAdapter; - private LinkedIdsAdapter mLinkedIdsAdapter; private Uri mDataUri; - private PostponeType mPostponeType; - - private ListView mLinkedIds; - private CardView mLinkedIdsCard; - private TextView mLinkedIdsEmpty; - private TextView mLinkedIdsExpander; + LinkedIdentitiesCardView mLinkedIdsCard; + LinkedIdentitiesPresenter mLinkedIdentitiesPresenter; SystemContactCardView mSystemContactCard; SystemContactPresenter mSystemContactPresenter; @@ -110,12 +87,11 @@ public class ViewKeyFragment extends LoaderFragment implements /** * Creates new instance of this fragment */ - public static ViewKeyFragment newInstance(long masterKeyId, boolean isSecret, PostponeType postponeType) { + public static ViewKeyFragment newInstance(long masterKeyId, boolean isSecret) { ViewKeyFragment frag = new ViewKeyFragment(); Bundle args = new Bundle(); args.putLong(ARG_MASTER_KEY_ID, masterKeyId); args.putBoolean(ARG_IS_SECRET, isSecret); - args.putString(ARG_POSTPONE_TYPE, postponeType.toString()); frag.setArguments(args); @@ -129,11 +105,7 @@ public class ViewKeyFragment extends LoaderFragment implements mUserIds = (ListView) view.findViewById(R.id.view_key_user_ids); Button userIdsEditButton = (Button) view.findViewById(R.id.view_key_card_user_ids_edit); - mLinkedIdsCard = (CardView) view.findViewById(R.id.card_linked_ids); - mLinkedIds = (ListView) view.findViewById(R.id.view_key_linked_ids); - mLinkedIdsExpander = (TextView) view.findViewById(R.id.view_key_linked_ids_expander); - mLinkedIdsEmpty = (TextView) view.findViewById(R.id.view_key_linked_ids_empty); - Button linkedIdsAddButton = (Button) view.findViewById(R.id.view_key_card_linked_ids_add); + mLinkedIdsCard = (LinkedIdentitiesCardView) view.findViewById(R.id.card_linked_ids); userIdsEditButton.setOnClickListener(new View.OnClickListener() { @Override @@ -142,25 +114,12 @@ public class ViewKeyFragment extends LoaderFragment implements } }); - linkedIdsAddButton.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - addLinkedIdentity(mDataUri); - } - }); - mUserIds.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView parent, View view, int position, long id) { showUserIdInfo(position); } }); - mLinkedIds.setOnItemClickListener(new OnItemClickListener() { - @Override - public void onItemClick(AdapterView parent, View view, int position, long id) { - showLinkedId(position); - } - }); mSystemContactCard = (SystemContactCardView) view.findViewById(R.id.linked_system_contact_card); mKeyHealthCard = (KeyHealthCardView) view.findViewById(R.id.subkey_status_card); @@ -174,53 +133,6 @@ public class ViewKeyFragment extends LoaderFragment implements startActivityForResult(editIntent, 0); } - private void addLinkedIdentity(Uri dataUri) { - Intent intent = new Intent(getActivity(), LinkedIdWizard.class); - intent.setData(dataUri); - startActivity(intent); - getActivity().finish(); - } - - private void showLinkedId(final int position) { - final LinkedIdViewFragment frag; - try { - frag = mLinkedIdsAdapter.getLinkedIdFragment(mDataUri, position, mMasterKeyId); - } catch (IOException e) { - Log.e(Constants.TAG, "IOException", e); - return; - } - - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { - Transition trans = TransitionInflater.from(getActivity()) - .inflateTransition(R.transition.linked_id_card_trans); - // setSharedElementReturnTransition(trans); - setExitTransition(new Fade()); - frag.setSharedElementEnterTransition(trans); - } - - getFragmentManager().beginTransaction() - .add(R.id.view_key_fragment, frag) - .hide(frag) - .commit(); - - frag.setOnIdentityLoadedListener(new OnIdentityLoadedListener() { - @Override - public void onIdentityLoaded() { - new Handler().post(new Runnable() { - @Override - public void run() { - getFragmentManager().beginTransaction() - .show(frag) - .addSharedElement(mLinkedIdsCard, "card_linked_ids") - .remove(ViewKeyFragment.this) - .addToBackStack("linked_id") - .commit(); - } - }); - } - }); - } - @Override public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); @@ -228,7 +140,6 @@ public class ViewKeyFragment extends LoaderFragment implements mMasterKeyId = getArguments().getLong(ARG_MASTER_KEY_ID); mDataUri = KeyRings.buildGenericKeyRingUri(mMasterKeyId); mIsSecret = getArguments().getBoolean(ARG_IS_SECRET); - mPostponeType = PostponeType.valueOf(getArguments().getString(ARG_POSTPONE_TYPE)); // load user ids after we know if it's a secret key mUserIdsAdapter = new UserIdsAdapter(getActivity(), null, 0, !mIsSecret, null); @@ -236,9 +147,14 @@ public class ViewKeyFragment extends LoaderFragment implements // initialize loaders, which will take care of auto-refresh on change getLoaderManager().initLoader(LOADER_ID_USER_IDS, null, this); - initLinkedIds(mIsSecret); initCardButtonsVisibility(mIsSecret); + if (Preferences.getPreferences(getActivity()).getExperimentalEnableLinkedIdentities()) { + mLinkedIdentitiesPresenter = new LinkedIdentitiesPresenter( + getContext(), mLinkedIdsCard, this, LOADER_ID_LINKED_IDS, mMasterKeyId, mIsSecret); + mLinkedIdentitiesPresenter.startLoader(getLoaderManager()); + } + mSystemContactPresenter = new SystemContactPresenter( getContext(), mSystemContactCard, LOADER_ID_LINKED_CONTACT, mMasterKeyId, mIsSecret); mSystemContactPresenter.startLoader(getLoaderManager()); @@ -248,6 +164,20 @@ public class ViewKeyFragment extends LoaderFragment implements mKeyHealthPresenter.startLoader(getLoaderManager()); } + @Override + public void switchToFragment(final Fragment frag, final String backStackName) { + new Handler().post(new Runnable() { + @Override + public void run() { + getFragmentManager().beginTransaction() + .setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE) + .replace(R.id.view_key_fragment, frag) + .addToBackStack(backStackName) + .commit(); + } + }); + } + private void showUserIdInfo(final int position) { if (!mIsSecret) { final boolean isRevoked = mUserIdsAdapter.getIsRevoked(position); @@ -283,10 +213,7 @@ public class ViewKeyFragment extends LoaderFragment implements return UserIdsAdapter.createLoader(getActivity(), mDataUri); } - case LOADER_ID_LINKED_IDS: { - return LinkedIdsAdapter.createLoader(getActivity(), mDataUri); - } - + case LOADER_ID_LINKED_IDS: case LOADER_ID_LINKED_CONTACT: case LOADER_ID_SUBKEY_STATUS: { throw new IllegalStateException("This callback should never end up here!"); @@ -315,31 +242,7 @@ public class ViewKeyFragment extends LoaderFragment implements break; } - case LOADER_ID_LINKED_IDS: { - mLinkedIdsAdapter.swapCursor(data); - - if (mIsSecret) { - mLinkedIdsCard.setVisibility(View.VISIBLE); - mLinkedIdsEmpty.setVisibility(mLinkedIdsAdapter.getCount() > 0 ? View.GONE : View.VISIBLE); - } else { - mLinkedIdsCard.setVisibility(mLinkedIdsAdapter.getCount() > 0 ? View.VISIBLE : View.GONE); - mLinkedIdsEmpty.setVisibility(View.GONE); - } - - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && mPostponeType == PostponeType.LINKED) { - mLinkedIdsCard.getViewTreeObserver().addOnPreDrawListener(new OnPreDrawListener() { - @TargetApi(VERSION_CODES.LOLLIPOP) - @Override - public boolean onPreDraw() { - mLinkedIdsCard.getViewTreeObserver().removeOnPreDrawListener(this); - getActivity().startPostponedEnterTransition(); - return true; - } - }); - } - break; - } - + case LOADER_ID_LINKED_IDS: case LOADER_ID_LINKED_CONTACT: case LOADER_ID_SUBKEY_STATUS: { throw new IllegalStateException("This callback should never end up here!"); @@ -347,16 +250,6 @@ public class ViewKeyFragment extends LoaderFragment implements } } - private void initLinkedIds(boolean isSecret) { - if (!Preferences.getPreferences(getActivity()).getExperimentalEnableLinkedIdentities()) { - return; - } - - mLinkedIdsAdapter = new LinkedIdsAdapter(getActivity(), null, 0, isSecret, mLinkedIdsExpander); - mLinkedIds.setAdapter(mLinkedIdsAdapter); - getLoaderManager().initLoader(LOADER_ID_LINKED_IDS, null, this); - } - private void initCardButtonsVisibility(boolean isSecret) { LinearLayout buttonsUserIdsLayout = (LinearLayout) getActivity().findViewById(R.id.view_key_card_user_ids_buttons); @@ -382,10 +275,6 @@ public class ViewKeyFragment extends LoaderFragment implements mUserIdsAdapter.swapCursor(null); break; } - case LOADER_ID_LINKED_IDS: { - mLinkedIdsAdapter.swapCursor(null); - break; - } } } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/LinkedIdsAdapter.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/LinkedIdsAdapter.java index cbc9837c1..fc253a30d 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/LinkedIdsAdapter.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/LinkedIdsAdapter.java @@ -18,8 +18,11 @@ package org.sufficientlysecure.keychain.ui.adapter; + +import java.io.IOException; +import java.util.WeakHashMap; + import android.animation.ObjectAnimator; -import android.app.Activity; import android.content.Context; import android.database.Cursor; import android.net.Uri; @@ -37,6 +40,7 @@ import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.linked.LinkedAttribute; import org.sufficientlysecure.keychain.linked.UriAttribute; import org.sufficientlysecure.keychain.provider.KeychainContract.Certs; +import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings; import org.sufficientlysecure.keychain.provider.KeychainContract.UserPackets; import org.sufficientlysecure.keychain.ui.linked.LinkedIdViewFragment; import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils; @@ -45,45 +49,22 @@ import org.sufficientlysecure.keychain.ui.util.SubtleAttentionSeeker; import org.sufficientlysecure.keychain.util.FilterCursorWrapper; import org.sufficientlysecure.keychain.util.Log; -import java.io.IOException; -import java.util.WeakHashMap; - public class LinkedIdsAdapter extends UserAttributesAdapter { private final boolean mIsSecret; protected LayoutInflater mInflater; WeakHashMap mLinkedIdentityCache = new WeakHashMap<>(); - private Cursor mUnfilteredCursor; - - private TextView mExpander; - - public LinkedIdsAdapter(Context context, Cursor c, int flags, - boolean isSecret, TextView expander) { + public LinkedIdsAdapter(Context context, Cursor c, int flags, boolean isSecret) { super(context, c, flags); mInflater = LayoutInflater.from(context); mIsSecret = isSecret; - - if (expander != null) { - expander.setVisibility(View.GONE); - /* don't show an expander (maybe in some sort of advanced view?) - mExpander = expander; - mExpander.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View v) { - showUnfiltered(); - } - }); - */ - } } @Override public Cursor swapCursor(Cursor cursor) { if (cursor == null) { - mUnfilteredCursor = null; return super.swapCursor(null); } - mUnfilteredCursor = cursor; FilterCursorWrapper filteredCursor = new FilterCursorWrapper(cursor) { @Override public boolean isVisible(Cursor cursor) { @@ -92,25 +73,9 @@ public class LinkedIdsAdapter extends UserAttributesAdapter { } }; - if (mExpander != null) { - int hidden = filteredCursor.getHiddenCount(); - if (hidden == 0) { - mExpander.setVisibility(View.GONE); - } else { - mExpander.setVisibility(View.VISIBLE); - mExpander.setText(mContext.getResources().getQuantityString( - R.plurals.linked_id_expand, hidden)); - } - } - return super.swapCursor(filteredCursor); } - private void showUnfiltered() { - mExpander.setVisibility(View.GONE); - super.swapCursor(mUnfilteredCursor); - } - @Override public void bindView(View view, Context context, Cursor cursor) { @@ -183,18 +148,18 @@ public class LinkedIdsAdapter extends UserAttributesAdapter { // don't show revoked user ids, irrelevant for average users public static final String LINKED_IDS_WHERE = UserPackets.IS_REVOKED + " = 0"; - public static CursorLoader createLoader(Activity activity, Uri dataUri) { + public static CursorLoader createLoader(Context context, Uri dataUri) { Uri baseUri = UserPackets.buildLinkedIdsUri(dataUri); - return new CursorLoader(activity, baseUri, + return new CursorLoader(context, baseUri, UserIdsAdapter.USER_PACKETS_PROJECTION, LINKED_IDS_WHERE, null, null); } - public LinkedIdViewFragment getLinkedIdFragment(Uri baseUri, int position, long masterKeyId) throws IOException { + public LinkedIdViewFragment getLinkedIdFragment(int position, long masterKeyId) throws IOException { Cursor c = getCursor(); c.moveToPosition(position); int rank = c.getInt(UserIdsAdapter.INDEX_RANK); - Uri dataUri = UserPackets.buildLinkedIdsUri(baseUri); + Uri dataUri = UserPackets.buildLinkedIdsUri(KeyRings.buildGenericKeyRingUri(masterKeyId)); return LinkedIdViewFragment.newInstance(dataUri, rank, mIsSecret, masterKeyId); } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/linked/LinkedIdViewFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/linked/LinkedIdViewFragment.java index 57854dcce..fd9ed1f98 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/linked/LinkedIdViewFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/linked/LinkedIdViewFragment.java @@ -96,7 +96,6 @@ public class LinkedIdViewFragment extends CryptoOperationFragment implements private Uri mDataUri; private ViewHolder mViewHolder; private int mLidRank; - private OnIdentityLoadedListener mIdLoadedListener; private long mCertifyKeyId; public static LinkedIdViewFragment newInstance(Uri dataUri, int rank, @@ -156,11 +155,6 @@ public class LinkedIdViewFragment extends CryptoOperationFragment implements // Nothing to load means break if we are *expected* to load if (!cursor.moveToFirst()) { - if (mIdLoadedListener != null) { - Notify.create(getActivity(), "Error loading identity!", - Notify.LENGTH_LONG, Style.ERROR).show(); - finishFragment(); - } // Or just ignore, this is probably some intermediate state during certify break; } @@ -173,11 +167,6 @@ public class LinkedIdViewFragment extends CryptoOperationFragment implements loadIdentity(linkedId, certStatus); - if (mIdLoadedListener != null) { - mIdLoadedListener.onIdentityLoaded(); - mIdLoadedListener = null; - } - } catch (IOException e) { Log.e(Constants.TAG, "error parsing identity", e); Notify.create(getActivity(), "Error parsing identity!", @@ -200,14 +189,6 @@ public class LinkedIdViewFragment extends CryptoOperationFragment implements }); } - public interface OnIdentityLoadedListener { - void onIdentityLoaded(); - } - - public void setOnIdentityLoadedListener(OnIdentityLoadedListener listener) { - mIdLoadedListener = listener; - } - private void loadIdentity(UriAttribute linkedId, int certStatus) { mLinkedId = linkedId; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/LinkedIdentitiesCardView.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/LinkedIdentitiesCardView.java new file mode 100644 index 000000000..b4133ce43 --- /dev/null +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/LinkedIdentitiesCardView.java @@ -0,0 +1,91 @@ +/* + * Copyright (C) 2017 Vincent Breitmoser + * + * 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.widget; + + +import android.content.Context; +import android.support.v7.widget.CardView; +import android.util.AttributeSet; +import android.view.LayoutInflater; +import android.view.View; +import android.widget.AdapterView; +import android.widget.AdapterView.OnItemClickListener; +import android.widget.Button; +import android.widget.ListView; +import android.widget.TextView; + +import org.sufficientlysecure.keychain.R; +import org.sufficientlysecure.keychain.ui.adapter.LinkedIdsAdapter; +import org.sufficientlysecure.keychain.ui.widget.LinkedIdentitiesPresenter.LinkedIdsClickListener; +import org.sufficientlysecure.keychain.ui.widget.LinkedIdentitiesPresenter.LinkedIdsMvpView; + + +public class LinkedIdentitiesCardView extends CardView implements LinkedIdsMvpView { + private ListView vLinkedIds; + private TextView vLinkedIdsEmpty; + + private LinkedIdsClickListener linkedIdsClickListener; + + public LinkedIdentitiesCardView(Context context, AttributeSet attrs) { + super(context, attrs); + + View view = LayoutInflater.from(context).inflate(R.layout.linked_identities_card, this, true); + + vLinkedIds = (ListView) view.findViewById(R.id.view_key_linked_ids); + vLinkedIdsEmpty = (TextView) view.findViewById(R.id.view_key_linked_ids_empty); + Button linkedIdsAddButton = (Button) view.findViewById(R.id.view_key_card_linked_ids_add); + + linkedIdsAddButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (linkedIdsClickListener != null) { + linkedIdsClickListener.onClickAddIdentity(); + } + } + }); + + vLinkedIds.setOnItemClickListener(new OnItemClickListener() { + @Override + public void onItemClick(AdapterView parent, View view, int position, long id) { + if (linkedIdsClickListener != null) { + linkedIdsClickListener.onLinkedIdItemClick(position); + } + } + }); + } + + @Override + public void setSystemContactClickListener(LinkedIdsClickListener linkedIdsClickListener) { + this.linkedIdsClickListener = linkedIdsClickListener; + } + + @Override + public void setLinkedIdsAdapter(LinkedIdsAdapter linkedIdsAdapter) { + vLinkedIds.setAdapter(linkedIdsAdapter); + } + + @Override + public void showCard(boolean visible) { + setVisibility(visible ? View.VISIBLE : View.GONE); + } + + @Override + public void showEmptyView(boolean visible) { + vLinkedIdsEmpty.setVisibility(visible ? View.VISIBLE : View.GONE); + } +} diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/LinkedIdentitiesPresenter.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/LinkedIdentitiesPresenter.java new file mode 100644 index 000000000..a47582b80 --- /dev/null +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/LinkedIdentitiesPresenter.java @@ -0,0 +1,139 @@ +/* + * Copyright (C) 2017 Vincent Breitmoser + * + * 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.widget; + + +import java.io.IOException; + +import android.content.Context; +import android.content.Intent; +import android.database.Cursor; +import android.os.Bundle; +import android.support.v4.app.Fragment; +import android.support.v4.app.LoaderManager; +import android.support.v4.app.LoaderManager.LoaderCallbacks; +import android.support.v4.content.Loader; + +import org.sufficientlysecure.keychain.Constants; +import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings; +import org.sufficientlysecure.keychain.ui.adapter.LinkedIdsAdapter; +import org.sufficientlysecure.keychain.ui.linked.LinkedIdViewFragment; +import org.sufficientlysecure.keychain.ui.linked.LinkedIdWizard; +import org.sufficientlysecure.keychain.util.Log; + + +public class LinkedIdentitiesPresenter implements LoaderCallbacks { + private final Context context; + private final LinkedIdsMvpView view; + private final int loaderId; + private final LinkedIdsFragMvpView fragView; + + private LinkedIdsAdapter linkedIdsAdapter; + + private final long masterKeyId; + private final boolean isSecret; + + public LinkedIdentitiesPresenter( + Context context, LinkedIdsMvpView view, LinkedIdsFragMvpView fragView, int loaderId, long masterKeyId, boolean isSecret) { + this.context = context; + this.view = view; + this.fragView = fragView; + this.loaderId = loaderId; + + this.masterKeyId = masterKeyId; + this.isSecret = isSecret; + + linkedIdsAdapter = new LinkedIdsAdapter(context, null, 0, isSecret); + view.setLinkedIdsAdapter(linkedIdsAdapter); + + view.setSystemContactClickListener(new LinkedIdsClickListener() { + @Override + public void onLinkedIdItemClick(int position) { + showLinkedId(position); + } + + @Override + public void onClickAddIdentity() { + addLinkedIdentity(); + } + }); + } + + public void startLoader(LoaderManager loaderManager) { + loaderManager.restartLoader(loaderId, null, this); + } + + @Override + public Loader onCreateLoader(int id, Bundle args) { + return LinkedIdsAdapter.createLoader(context, KeyRings.buildUnifiedKeyRingUri(masterKeyId)); + } + + @Override + public void onLoadFinished(Loader loader, Cursor data) { + linkedIdsAdapter.swapCursor(data); + + boolean hasLinkedIdentities = linkedIdsAdapter.getCount() > 0; + if (isSecret) { + view.showCard(true); + view.showEmptyView(!hasLinkedIdentities); + } else { + view.showCard(hasLinkedIdentities); + view.showEmptyView(false); + } + } + + @Override + public void onLoaderReset(Loader loader) { + linkedIdsAdapter.swapCursor(null); + } + + private void showLinkedId(final int position) { + final LinkedIdViewFragment frag; + try { + frag = linkedIdsAdapter.getLinkedIdFragment(position, masterKeyId); + } catch (IOException e) { + Log.e(Constants.TAG, "IOException", e); + return; + } + + fragView.switchToFragment(frag, "linked_id"); + } + + interface LinkedIdsMvpView { + void setSystemContactClickListener(LinkedIdsClickListener linkedIdsClickListener); + void setLinkedIdsAdapter(LinkedIdsAdapter linkedIdsAdapter); + + void showCard(boolean visible); + void showEmptyView(boolean visible); + } + + public interface LinkedIdsFragMvpView { + void switchToFragment(Fragment frag, String backStackName); + } + + interface LinkedIdsClickListener { + void onLinkedIdItemClick(int position); + void onClickAddIdentity(); + } + + private void addLinkedIdentity() { + Intent intent = new Intent(context, LinkedIdWizard.class); + intent.setData(KeyRings.buildUnifiedKeyRingUri(masterKeyId)); + context.startActivity(intent); + } +} \ No newline at end of file diff --git a/OpenKeychain/src/main/res/layout/linked_identities_card.xml b/OpenKeychain/src/main/res/layout/linked_identities_card.xml new file mode 100644 index 000000000..8e281df3a --- /dev/null +++ b/OpenKeychain/src/main/res/layout/linked_identities_card.xml @@ -0,0 +1,50 @@ + + + + + + + + + + + + + +