diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/UserIdsAdapter.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/UserIdsAdapter.java index 4ddde959e..126c0f829 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/UserIdsAdapter.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/UserIdsAdapter.java @@ -189,9 +189,9 @@ public class UserIdsAdapter extends UserAttributesAdapter { // don't show revoked user ids, irrelevant for average users public static final String USER_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.buildUserIdsUri(dataUri); - return new CursorLoader(activity, baseUri, + return new CursorLoader(context, baseUri, UserIdsAdapter.USER_PACKETS_PROJECTION, USER_IDS_WHERE, null, null); } 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 1d6b65d04..e4750f387 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 @@ -20,49 +20,38 @@ package org.sufficientlysecure.keychain.ui.keyview; import android.content.Intent; -import android.database.Cursor; -import android.net.Uri; import android.os.Bundle; import android.os.Handler; +import android.support.v4.app.DialogFragment; 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.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; -import android.widget.AdapterView; -import android.widget.Button; import android.widget.LinearLayout; -import android.widget.ListView; 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.EditIdentitiesActivity; -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.keyview.presenter.IdentitiesPresenter; import org.sufficientlysecure.keychain.ui.keyview.presenter.KeyHealthPresenter; import org.sufficientlysecure.keychain.ui.keyview.presenter.LinkedIdentitiesPresenter; import org.sufficientlysecure.keychain.ui.keyview.presenter.LinkedIdentitiesPresenter.LinkedIdsFragMvpView; 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.LinkedIdentitiesCardView; import org.sufficientlysecure.keychain.ui.keyview.view.SystemContactCardView; import org.sufficientlysecure.keychain.util.Preferences; -public class ViewKeyFragment extends LoaderFragment implements LoaderManager.LoaderCallbacks, - LinkedIdsFragMvpView { +public class ViewKeyFragment extends LoaderFragment implements LinkedIdsFragMvpView, ViewKeyMvpView { public static final String ARG_MASTER_KEY_ID = "master_key_id"; public static final String ARG_IS_SECRET = "is_secret"; - private ListView mUserIds; - boolean mIsSecret = false; private static final int LOADER_ID_USER_IDS = 1; @@ -70,9 +59,8 @@ public class ViewKeyFragment extends LoaderFragment implements LoaderManager.Loa private static final int LOADER_ID_LINKED_CONTACT = 3; private static final int LOADER_ID_SUBKEY_STATUS = 4; - private UserIdsAdapter mUserIdsAdapter; - - private Uri mDataUri; + private IdentitiesCardView mIdentitiesCardView; + private IdentitiesPresenter mIdentitiesPresenter; LinkedIdentitiesCardView mLinkedIdsCard; LinkedIdentitiesPresenter mLinkedIdentitiesPresenter; @@ -84,8 +72,6 @@ public class ViewKeyFragment extends LoaderFragment implements LoaderManager.Loa KeyHealthPresenter mKeyHealthPresenter; - private long mMasterKeyId; - /** * Creates new instance of this fragment */ @@ -105,64 +91,41 @@ public class ViewKeyFragment extends LoaderFragment implements LoaderManager.Loa View root = super.onCreateView(inflater, superContainer, savedInstanceState); View view = inflater.inflate(R.layout.view_key_fragment, getContainer()); - mUserIds = (ListView) view.findViewById(R.id.view_key_user_ids); - Button userIdsEditButton = (Button) view.findViewById(R.id.view_key_card_user_ids_edit); + mIdentitiesCardView = (IdentitiesCardView) view.findViewById(R.id.card_identities); mLinkedIdsCard = (LinkedIdentitiesCardView) view.findViewById(R.id.card_linked_ids); - userIdsEditButton.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - editIdentities(mDataUri); - } - }); - - mUserIds.setOnItemClickListener(new AdapterView.OnItemClickListener() { - @Override - public void onItemClick(AdapterView parent, View view, int position, long id) { - showUserIdInfo(position); - } - }); - mSystemContactCard = (SystemContactCardView) view.findViewById(R.id.linked_system_contact_card); mKeyStatusHealth = (KeyHealthView) view.findViewById(R.id.key_status_health); return root; } - private void editIdentities(Uri dataUri) { - Intent editIntent = new Intent(getActivity(), EditIdentitiesActivity.class); - editIntent.setData(KeychainContract.KeyRingData.buildSecretKeyRingUri(dataUri)); - startActivityForResult(editIntent, 0); - } - @Override public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); - mMasterKeyId = getArguments().getLong(ARG_MASTER_KEY_ID); - mDataUri = KeyRings.buildGenericKeyRingUri(mMasterKeyId); + long masterKeyId = getArguments().getLong(ARG_MASTER_KEY_ID); mIsSecret = getArguments().getBoolean(ARG_IS_SECRET); - // load user ids after we know if it's a secret key - mUserIdsAdapter = new UserIdsAdapter(getActivity(), null, 0, !mIsSecret); - mUserIds.setAdapter(mUserIdsAdapter); - // initialize loaders, which will take care of auto-refresh on change - getLoaderManager().initLoader(LOADER_ID_USER_IDS, null, this); - initCardButtonsVisibility(mIsSecret); +// initCardButtonsVisibility(mIsSecret); + + mIdentitiesPresenter = new IdentitiesPresenter( + getContext(), mIdentitiesCardView, this, LOADER_ID_USER_IDS, masterKeyId, mIsSecret); + mIdentitiesPresenter.startLoader(getLoaderManager()); if (Preferences.getPreferences(getActivity()).getExperimentalEnableLinkedIdentities()) { mLinkedIdentitiesPresenter = new LinkedIdentitiesPresenter( - getContext(), mLinkedIdsCard, this, LOADER_ID_LINKED_IDS, mMasterKeyId, mIsSecret); + getContext(), mLinkedIdsCard, this, LOADER_ID_LINKED_IDS, masterKeyId, mIsSecret); mLinkedIdentitiesPresenter.startLoader(getLoaderManager()); } mSystemContactPresenter = new SystemContactPresenter( - getContext(), mSystemContactCard, LOADER_ID_LINKED_CONTACT, mMasterKeyId, mIsSecret); + getContext(), mSystemContactCard, LOADER_ID_LINKED_CONTACT, masterKeyId, mIsSecret); mSystemContactPresenter.startLoader(getLoaderManager()); mKeyHealthPresenter = new KeyHealthPresenter( - getContext(), mKeyStatusHealth, LOADER_ID_SUBKEY_STATUS, mMasterKeyId, mIsSecret); + getContext(), mKeyStatusHealth, LOADER_ID_SUBKEY_STATUS, masterKeyId, mIsSecret); mKeyHealthPresenter.startLoader(getLoaderManager()); } @@ -180,22 +143,6 @@ public class ViewKeyFragment extends LoaderFragment implements LoaderManager.Loa }); } - private void showUserIdInfo(final int position) { - if (!mIsSecret) { - final boolean isRevoked = mUserIdsAdapter.getIsRevoked(position); - final int isVerified = mUserIdsAdapter.getIsVerified(position); - - DialogFragmentWorkaround.INTERFACE.runnableRunDelayed(new Runnable() { - public void run() { - UserIdInfoDialogFragment dialogFragment = - UserIdInfoDialogFragment.newInstance(isRevoked, isVerified); - - dialogFragment.show(getActivity().getSupportFragmentManager(), "userIdInfoDialog"); - } - }); - } - } - @Override public void onActivityResult(int requestCode, int resultCode, Intent data) { // if a result has been returned, display a notify @@ -207,51 +154,6 @@ public class ViewKeyFragment extends LoaderFragment implements LoaderManager.Loa } } - @Override - public Loader onCreateLoader(int id, Bundle args) { - - switch (id) { - case LOADER_ID_USER_IDS: { - return UserIdsAdapter.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!"); - } - - default: - return null; - } - } - - @Override - public void onLoadFinished(Loader loader, Cursor data) { - /* TODO better error handling? May cause problems when a key is deleted, - * because the notification triggers faster than the activity closes. - */ - if (data == null) { - return; - } - // Swap the new cursor in. (The framework will take care of closing the - // old cursor once we return.) - switch (loader.getId()) { - case LOADER_ID_USER_IDS: { - setContentShown(true, false); - mUserIdsAdapter.swapCursor(data); - - 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!"); - } - } - } - private void initCardButtonsVisibility(boolean isSecret) { LinearLayout buttonsUserIdsLayout = (LinearLayout) getActivity().findViewById(R.id.view_key_card_user_ids_buttons); @@ -266,22 +168,21 @@ public class ViewKeyFragment extends LoaderFragment implements LoaderManager.Loa } } - /** - * This is called when the last Cursor provided to onLoadFinished() above is about to be closed. - * We need to make sure we are no longer using it. - */ - @Override - public void onLoaderReset(Loader loader) { - switch (loader.getId()) { - case LOADER_ID_USER_IDS: { - mUserIdsAdapter.swapCursor(null); - break; - } - } - } - public boolean isValidForData(boolean isSecret) { return isSecret == mIsSecret; } + @Override + public void startActivityAndShowResultSnackbar(Intent intent) { + startActivityForResult(intent, 0); + } + + @Override + public void showDialogFragment(final DialogFragment dialogFragment, final String tag) { + DialogFragmentWorkaround.INTERFACE.runnableRunDelayed(new Runnable() { + public void run() { + dialogFragment.show(getActivity().getSupportFragmentManager(), tag); + } + }); + } } 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 new file mode 100644 index 000000000..16d122abe --- /dev/null +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/keyview/presenter/IdentitiesPresenter.java @@ -0,0 +1,121 @@ +/* + * 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.keyview.presenter; + + +import android.content.Context; +import android.content.Intent; +import android.database.Cursor; +import android.os.Bundle; +import android.support.v4.app.LoaderManager; +import android.support.v4.app.LoaderManager.LoaderCallbacks; +import android.support.v4.content.Loader; + +import org.sufficientlysecure.keychain.provider.KeychainContract; +import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings; +import org.sufficientlysecure.keychain.ui.EditIdentitiesActivity; +import org.sufficientlysecure.keychain.ui.adapter.UserIdsAdapter; +import org.sufficientlysecure.keychain.ui.dialog.UserIdInfoDialogFragment; + + +public class IdentitiesPresenter implements LoaderCallbacks { + private final Context context; + private final IdentitiesMvpView view; + private final ViewKeyMvpView viewKeyMvpView; + private final int loaderId; + + private final UserIdsAdapter userIdsAdapter; + + private final long masterKeyId; + private final boolean isSecret; + + public IdentitiesPresenter(Context context, IdentitiesMvpView view, ViewKeyMvpView viewKeyMvpView, + int loaderId, long masterKeyId, boolean isSecret) { + this.context = context; + this.view = view; + this.viewKeyMvpView = viewKeyMvpView; + this.loaderId = loaderId; + + this.masterKeyId = masterKeyId; + this.isSecret = isSecret; + + userIdsAdapter = new UserIdsAdapter(context, null, 0, !isSecret); + view.setUserIdsAdapter(userIdsAdapter); + + view.setEditIdentitiesButtonVisible(isSecret); + + view.setIdentitiesCardListener(new IdentitiesCardListener() { + @Override + public void onIdentityItemClick(int position) { + showUserIdInfo(position); + } + + @Override + public void onClickEditIdentities() { + editIdentities(); + } + }); + } + + public void startLoader(LoaderManager loaderManager) { + loaderManager.restartLoader(loaderId, null, this); + } + + @Override + public Loader onCreateLoader(int id, Bundle args) { + return UserIdsAdapter.createLoader(context, KeyRings.buildUnifiedKeyRingUri(masterKeyId)); + } + + @Override + public void onLoadFinished(Loader loader, Cursor data) { + viewKeyMvpView.setContentShown(true, false); + userIdsAdapter.swapCursor(data); + } + + @Override + public void onLoaderReset(Loader loader) { + userIdsAdapter.swapCursor(null); + } + + private void showUserIdInfo(final int position) { + if (!isSecret) { + final boolean isRevoked = userIdsAdapter.getIsRevoked(position); + final int isVerified = userIdsAdapter.getIsVerified(position); + + UserIdInfoDialogFragment dialogFragment = UserIdInfoDialogFragment.newInstance(isRevoked, isVerified); + viewKeyMvpView.showDialogFragment(dialogFragment, "userIdInfoDialog"); + } + } + + private void editIdentities() { + Intent editIntent = new Intent(context, EditIdentitiesActivity.class); + editIntent.setData(KeychainContract.KeyRingData.buildSecretKeyRingUri(masterKeyId)); + viewKeyMvpView.startActivityAndShowResultSnackbar(editIntent); + } + + public interface IdentitiesMvpView { + void setUserIdsAdapter(UserIdsAdapter userIdsAdapter); + void setIdentitiesCardListener(IdentitiesCardListener identitiesCardListener); + void setEditIdentitiesButtonVisible(boolean show); + } + + public interface IdentitiesCardListener { + void onIdentityItemClick(int position); + void onClickEditIdentities(); + } +} \ No newline at end of file diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/keyview/presenter/ViewKeyMvpView.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/keyview/presenter/ViewKeyMvpView.java new file mode 100644 index 000000000..a4118bff0 --- /dev/null +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/keyview/presenter/ViewKeyMvpView.java @@ -0,0 +1,12 @@ +package org.sufficientlysecure.keychain.ui.keyview.presenter; + + +import android.content.Intent; +import android.support.v4.app.DialogFragment; + + +public interface ViewKeyMvpView { + void startActivityAndShowResultSnackbar(Intent intent); + void showDialogFragment(DialogFragment dialogFragment, final String tag); + void setContentShown(boolean show, boolean animate); +} 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 new file mode 100644 index 000000000..57176e939 --- /dev/null +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/keyview/view/IdentitiesCardView.java @@ -0,0 +1,86 @@ +/* + * 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.keyview.view; + + +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.UserIdsAdapter; +import org.sufficientlysecure.keychain.ui.keyview.presenter.IdentitiesPresenter.IdentitiesCardListener; +import org.sufficientlysecure.keychain.ui.keyview.presenter.IdentitiesPresenter.IdentitiesMvpView; + + +public class IdentitiesCardView extends CardView implements IdentitiesMvpView { + private ListView vUserIds; + private TextView vLinkedIdsEmpty; + + private IdentitiesCardListener identitiesCardListener; + + public IdentitiesCardView(Context context, AttributeSet attrs) { + super(context, attrs); + + View view = LayoutInflater.from(context).inflate(R.layout.identities_card, this, true); + + vUserIds = (ListView) view.findViewById(R.id.view_key_user_ids); + + Button userIdsEditButton = (Button) view.findViewById(R.id.view_key_card_user_ids_edit); + userIdsEditButton.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + if (identitiesCardListener != null) { + identitiesCardListener.onClickEditIdentities(); + } + } + }); + + vUserIds.setOnItemClickListener(new OnItemClickListener() { + @Override + public void onItemClick(AdapterView parent, View view, int position, long id) { + if (identitiesCardListener != null) { + identitiesCardListener.onIdentityItemClick(position); + } + } + }); + + } + + @Override + public void setUserIdsAdapter(UserIdsAdapter userIdsAdapter) { + vUserIds.setAdapter(userIdsAdapter); + } + + @Override + public void setIdentitiesCardListener(IdentitiesCardListener identitiesCardListener) { + this.identitiesCardListener = identitiesCardListener; + } + + @Override + public void setEditIdentitiesButtonVisible(boolean show) { + findViewById(R.id.view_key_card_user_ids_buttons).setVisibility(show ? View.VISIBLE : View.GONE); + } +} diff --git a/OpenKeychain/src/main/res/layout/identities_card.xml b/OpenKeychain/src/main/res/layout/identities_card.xml new file mode 100644 index 000000000..4ef182b43 --- /dev/null +++ b/OpenKeychain/src/main/res/layout/identities_card.xml @@ -0,0 +1,41 @@ + + + + + + + + + + + +