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 678ecd289..be1e0a4c1 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java @@ -261,7 +261,6 @@ public class ViewKeyActivity extends BaseActivity implements initNfc(mDataUri); - startFragment(savedInstanceState, mDataUri); } @Override @@ -269,26 +268,6 @@ public class ViewKeyActivity extends BaseActivity implements setContentView(R.layout.view_key_activity); } - private void startFragment(Bundle savedInstanceState, Uri dataUri) { - // However, if we're being restored from a previous state, - // then we don't need to do anything and should return or else - // we could end up with overlapping fragments. - if (savedInstanceState != null) { - return; - } - - // Create an instance of the fragment - ViewKeyFragment frag = ViewKeyFragment.newInstance(dataUri); - - // Add the fragment to the 'fragment_container' FrameLayout - // NOTE: We use commitAllowingStateLoss() to prevent weird crashes! - getSupportFragmentManager().beginTransaction() - .replace(R.id.view_key_fragment, frag, "main") - .commitAllowingStateLoss(); - // do it immediately! - getSupportFragmentManager().executePendingTransactions(); - } - @Override public boolean onCreateOptionsMenu(Menu menu) { super.onCreateOptionsMenu(menu); @@ -807,166 +786,172 @@ public class ViewKeyActivity extends BaseActivity implements // old cursor once we return.) switch (loader.getId()) { case LOADER_ID_UNIFIED: { - if (data.moveToFirst()) { - // get name, email, and comment from USER_ID - String[] mainUserId = KeyRing.splitUserId(data.getString(INDEX_USER_ID)); - if (mainUserId[0] != null) { - mName.setText(mainUserId[0]); - } else { - mName.setText(R.string.user_id_no_name); - } - - String oldFingerprint = mFingerprint; - mMasterKeyId = data.getLong(INDEX_MASTER_KEY_ID); - mFingerprint = KeyFormattingUtils.convertFingerprintToHex(data.getBlob(INDEX_FINGERPRINT)); - - mIsSecret = data.getInt(INDEX_HAS_ANY_SECRET) != 0; - mHasEncrypt = data.getInt(INDEX_HAS_ENCRYPT) != 0; - mIsRevoked = data.getInt(INDEX_IS_REVOKED) > 0; - mIsExpired = data.getInt(INDEX_IS_EXPIRED) != 0; - mIsVerified = data.getInt(INDEX_VERIFIED) > 0; - - // if the refresh animation isn't playing - if (!mRotate.hasStarted() && !mRotateSpin.hasStarted()) { - // re-create options menu based on mIsSecret, mIsVerified - supportInvalidateOptionsMenu(); - // this is done at the end of the animation otherwise - } - - AsyncTask photoTask = - new AsyncTask() { - protected Bitmap doInBackground(Long... mMasterKeyId) { - return ContactHelper.loadPhotoByMasterKeyId(getContentResolver(), mMasterKeyId[0], true); - } - - protected void onPostExecute(Bitmap photo) { - mPhoto.setImageBitmap(photo); - mPhoto.setVisibility(View.VISIBLE); - } - }; - - // Note: order is important - int color; - if (mIsRevoked) { - mStatusText.setText(R.string.view_key_revoked); - mStatusImage.setVisibility(View.VISIBLE); - KeyFormattingUtils.setStatusImage(this, mStatusImage, mStatusText, - State.REVOKED, R.color.icons, true); - color = getResources().getColor(R.color.android_red_light); - - mActionEncryptFile.setVisibility(View.GONE); - mActionEncryptText.setVisibility(View.GONE); - mActionNfc.setVisibility(View.GONE); - mFab.setVisibility(View.GONE); - mQrCodeLayout.setVisibility(View.GONE); - } else if (mIsExpired) { - if (mIsSecret) { - mStatusText.setText(R.string.view_key_expired_secret); - } else { - mStatusText.setText(R.string.view_key_expired); - } - mStatusImage.setVisibility(View.VISIBLE); - KeyFormattingUtils.setStatusImage(this, mStatusImage, mStatusText, - State.EXPIRED, R.color.icons, true); - color = getResources().getColor(R.color.android_red_light); - - mActionEncryptFile.setVisibility(View.GONE); - mActionEncryptText.setVisibility(View.GONE); - mActionNfc.setVisibility(View.GONE); - mFab.setVisibility(View.GONE); - mQrCodeLayout.setVisibility(View.GONE); - } else if (mIsSecret) { - mStatusText.setText(R.string.view_key_my_key); - mStatusImage.setVisibility(View.GONE); - color = getResources().getColor(R.color.primary); - // reload qr code only if the fingerprint changed - if (!mFingerprint.equals(oldFingerprint)) { - loadQrCode(mFingerprint); - } - photoTask.execute(mMasterKeyId); - mQrCodeLayout.setVisibility(View.VISIBLE); - - // and place leftOf qr code - RelativeLayout.LayoutParams nameParams = (RelativeLayout.LayoutParams) - mName.getLayoutParams(); - // remove right margin - nameParams.setMargins(FormattingUtils.dpToPx(this, 48), 0, 0, 0); - if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { - nameParams.setMarginEnd(0); - } - nameParams.addRule(RelativeLayout.LEFT_OF, R.id.view_key_qr_code_layout); - mName.setLayoutParams(nameParams); - - RelativeLayout.LayoutParams statusParams = (RelativeLayout.LayoutParams) - mStatusText.getLayoutParams(); - statusParams.setMargins(FormattingUtils.dpToPx(this, 48), 0, 0, 0); - if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { - statusParams.setMarginEnd(0); - } - statusParams.addRule(RelativeLayout.LEFT_OF, R.id.view_key_qr_code_layout); - mStatusText.setLayoutParams(statusParams); - - mActionEncryptFile.setVisibility(View.VISIBLE); - mActionEncryptText.setVisibility(View.VISIBLE); - - // invokeBeam is available from API 21 - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { - mActionNfc.setVisibility(View.VISIBLE); - } else { - mActionNfc.setVisibility(View.GONE); - } - mFab.setVisibility(View.VISIBLE); - mFab.setIconDrawable(getResources().getDrawable(R.drawable.ic_repeat_white_24dp)); - } else { - mActionEncryptFile.setVisibility(View.VISIBLE); - mActionEncryptText.setVisibility(View.VISIBLE); - mQrCodeLayout.setVisibility(View.GONE); - mActionNfc.setVisibility(View.GONE); - - if (mIsVerified) { - mStatusText.setText(R.string.view_key_verified); - mStatusImage.setVisibility(View.VISIBLE); - KeyFormattingUtils.setStatusImage(this, mStatusImage, mStatusText, - State.VERIFIED, R.color.icons, true); - color = getResources().getColor(R.color.primary); - photoTask.execute(mMasterKeyId); - - mFab.setVisibility(View.GONE); - } else { - mStatusText.setText(R.string.view_key_unverified); - mStatusImage.setVisibility(View.VISIBLE); - KeyFormattingUtils.setStatusImage(this, mStatusImage, mStatusText, - State.UNVERIFIED, R.color.icons, true); - color = getResources().getColor(R.color.android_orange_light); - - mFab.setVisibility(View.VISIBLE); - } - } - - if (mPreviousColor == 0 || mPreviousColor == color) { - mStatusBar.setBackgroundColor(color); - mBigToolbar.setBackgroundColor(color); - mPreviousColor = color; - } else { - ObjectAnimator colorFade1 = - ObjectAnimator.ofObject(mStatusBar, "backgroundColor", - new ArgbEvaluator(), mPreviousColor, color); - ObjectAnimator colorFade2 = - ObjectAnimator.ofObject(mBigToolbar, "backgroundColor", - new ArgbEvaluator(), mPreviousColor, color); - - colorFade1.setDuration(1200); - colorFade2.setDuration(1200); - colorFade1.start(); - colorFade2.start(); - mPreviousColor = color; - } - - //noinspection deprecation - mStatusImage.setAlpha(80); - + // if there is no data, just break + if (!data.moveToFirst()) { break; } + + String oldFingerprint = mFingerprint; + mMasterKeyId = data.getLong(INDEX_MASTER_KEY_ID); + byte[] fpData = data.getBlob(INDEX_FINGERPRINT); + mFingerprint = KeyFormattingUtils.convertFingerprintToHex(fpData); + + mIsSecret = data.getInt(INDEX_HAS_ANY_SECRET) != 0; + mHasEncrypt = data.getInt(INDEX_HAS_ENCRYPT) != 0; + mIsRevoked = data.getInt(INDEX_IS_REVOKED) > 0; + mIsExpired = data.getInt(INDEX_IS_EXPIRED) != 0; + mIsVerified = data.getInt(INDEX_VERIFIED) > 0; + + startFragment(mIsSecret, fpData); + + // get name, email, and comment from USER_ID + String[] mainUserId = KeyRing.splitUserId(data.getString(INDEX_USER_ID)); + if (mainUserId[0] != null) { + mName.setText(mainUserId[0]); + } else { + mName.setText(R.string.user_id_no_name); + } + + // if the refresh animation isn't playing + if (!mRotate.hasStarted() && !mRotateSpin.hasStarted()) { + // re-create options menu based on mIsSecret, mIsVerified + supportInvalidateOptionsMenu(); + // this is done at the end of the animation otherwise + } + + AsyncTask photoTask = + new AsyncTask() { + protected Bitmap doInBackground(Long... mMasterKeyId) { + return ContactHelper.loadPhotoByMasterKeyId(getContentResolver(), mMasterKeyId[0], true); + } + + protected void onPostExecute(Bitmap photo) { + mPhoto.setImageBitmap(photo); + mPhoto.setVisibility(View.VISIBLE); + } + }; + + // Note: order is important + int color; + if (mIsRevoked) { + mStatusText.setText(R.string.view_key_revoked); + mStatusImage.setVisibility(View.VISIBLE); + KeyFormattingUtils.setStatusImage(this, mStatusImage, mStatusText, + State.REVOKED, R.color.icons, true); + color = getResources().getColor(R.color.android_red_light); + + mActionEncryptFile.setVisibility(View.GONE); + mActionEncryptText.setVisibility(View.GONE); + mActionNfc.setVisibility(View.GONE); + mFab.setVisibility(View.GONE); + mQrCodeLayout.setVisibility(View.GONE); + } else if (mIsExpired) { + if (mIsSecret) { + mStatusText.setText(R.string.view_key_expired_secret); + } else { + mStatusText.setText(R.string.view_key_expired); + } + mStatusImage.setVisibility(View.VISIBLE); + KeyFormattingUtils.setStatusImage(this, mStatusImage, mStatusText, + State.EXPIRED, R.color.icons, true); + color = getResources().getColor(R.color.android_red_light); + + mActionEncryptFile.setVisibility(View.GONE); + mActionEncryptText.setVisibility(View.GONE); + mActionNfc.setVisibility(View.GONE); + mFab.setVisibility(View.GONE); + mQrCodeLayout.setVisibility(View.GONE); + } else if (mIsSecret) { + mStatusText.setText(R.string.view_key_my_key); + mStatusImage.setVisibility(View.GONE); + color = getResources().getColor(R.color.primary); + // reload qr code only if the fingerprint changed + if (!mFingerprint.equals(oldFingerprint)) { + loadQrCode(mFingerprint); + } + photoTask.execute(mMasterKeyId); + mQrCodeLayout.setVisibility(View.VISIBLE); + + // and place leftOf qr code + RelativeLayout.LayoutParams nameParams = (RelativeLayout.LayoutParams) + mName.getLayoutParams(); + // remove right margin + nameParams.setMargins(FormattingUtils.dpToPx(this, 48), 0, 0, 0); + if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { + nameParams.setMarginEnd(0); + } + nameParams.addRule(RelativeLayout.LEFT_OF, R.id.view_key_qr_code_layout); + mName.setLayoutParams(nameParams); + + RelativeLayout.LayoutParams statusParams = (RelativeLayout.LayoutParams) + mStatusText.getLayoutParams(); + statusParams.setMargins(FormattingUtils.dpToPx(this, 48), 0, 0, 0); + if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { + statusParams.setMarginEnd(0); + } + statusParams.addRule(RelativeLayout.LEFT_OF, R.id.view_key_qr_code_layout); + mStatusText.setLayoutParams(statusParams); + + mActionEncryptFile.setVisibility(View.VISIBLE); + mActionEncryptText.setVisibility(View.VISIBLE); + + // invokeBeam is available from API 21 + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + mActionNfc.setVisibility(View.VISIBLE); + } else { + mActionNfc.setVisibility(View.GONE); + } + mFab.setVisibility(View.VISIBLE); + mFab.setIconDrawable(getResources().getDrawable(R.drawable.ic_repeat_white_24dp)); + } else { + mActionEncryptFile.setVisibility(View.VISIBLE); + mActionEncryptText.setVisibility(View.VISIBLE); + mQrCodeLayout.setVisibility(View.GONE); + mActionNfc.setVisibility(View.GONE); + + if (mIsVerified) { + mStatusText.setText(R.string.view_key_verified); + mStatusImage.setVisibility(View.VISIBLE); + KeyFormattingUtils.setStatusImage(this, mStatusImage, mStatusText, + State.VERIFIED, R.color.icons, true); + color = getResources().getColor(R.color.primary); + photoTask.execute(mMasterKeyId); + + mFab.setVisibility(View.GONE); + } else { + mStatusText.setText(R.string.view_key_unverified); + mStatusImage.setVisibility(View.VISIBLE); + KeyFormattingUtils.setStatusImage(this, mStatusImage, mStatusText, + State.UNVERIFIED, R.color.icons, true); + color = getResources().getColor(R.color.android_orange_light); + + mFab.setVisibility(View.VISIBLE); + } + } + + if (mPreviousColor == 0 || mPreviousColor == color) { + mStatusBar.setBackgroundColor(color); + mBigToolbar.setBackgroundColor(color); + mPreviousColor = color; + } else { + ObjectAnimator colorFade1 = + ObjectAnimator.ofObject(mStatusBar, "backgroundColor", + new ArgbEvaluator(), mPreviousColor, color); + ObjectAnimator colorFade2 = + ObjectAnimator.ofObject(mBigToolbar, "backgroundColor", + new ArgbEvaluator(), mPreviousColor, color); + + colorFade1.setDuration(1200); + colorFade2.setDuration(1200); + colorFade1.start(); + colorFade2.start(); + mPreviousColor = color; + } + + //noinspection deprecation + mStatusImage.setAlpha(80); + + break; } } } @@ -975,4 +960,18 @@ public class ViewKeyActivity extends BaseActivity implements public void onLoaderReset(Loader loader) { } + + private void startFragment(boolean isSecret, byte[] fingerprint) { + // Create an instance of the fragment + ViewKeyFragment frag = ViewKeyFragment.newInstance(mDataUri, isSecret, fingerprint); + + // Add the fragment to the 'fragment_container' FrameLayout + // NOTE: We use commitAllowingStateLoss() to prevent weird crashes! + getSupportFragmentManager().beginTransaction() + .replace(R.id.view_key_fragment, frag, "main") + .commitAllowingStateLoss(); + // do it immediately! + getSupportFragmentManager().executePendingTransactions(); + } + } 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 311e1d0ee..240dd3547 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyFragment.java @@ -29,7 +29,6 @@ import android.support.v4.app.LoaderManager; import android.support.v4.content.CursorLoader; import android.support.v4.content.Loader; import android.support.v7.widget.CardView; -import android.transition.Explode; import android.transition.Fade; import android.transition.Transition; import android.transition.TransitionInflater; @@ -47,21 +46,21 @@ import org.sufficientlysecure.keychain.provider.KeychainContract; import org.sufficientlysecure.keychain.ui.adapter.LinkedIdsAdapter; import org.sufficientlysecure.keychain.ui.adapter.UserIdsAdapter; import org.sufficientlysecure.keychain.ui.dialog.UserIdInfoDialogFragment; -import org.sufficientlysecure.keychain.ui.util.Notify; import org.sufficientlysecure.keychain.util.Log; public class ViewKeyFragment extends LoaderFragment implements LoaderManager.LoaderCallbacks { public static final String ARG_DATA_URI = "uri"; + private static final String ARG_FINGERPRINT = "fingerprint"; + private static final String ARG_IS_SECRET = "is_secret"; private ListView mUserIds; boolean mIsSecret = false; - private static final int LOADER_ID_UNIFIED = 0; - private static final int LOADER_ID_USER_IDS = 1; - private static final int LOADER_ID_LINKED_IDS = 2; + private static final int LOADER_ID_USER_IDS = 0; + private static final int LOADER_ID_LINKED_IDS = 1; private UserIdsAdapter mUserIdsAdapter; private LinkedIdsAdapter mLinkedIdsAdapter; @@ -69,20 +68,40 @@ public class ViewKeyFragment extends LoaderFragment implements private Uri mDataUri; private ListView mLinkedIds; private CardView mLinkedIdsCard; + private byte[] mFingerprint; /** * Creates new instance of this fragment */ - public static ViewKeyFragment newInstance(Uri dataUri) { + public static ViewKeyFragment newInstance(Uri dataUri, boolean isSecret, byte[] fingerprint) { ViewKeyFragment frag = new ViewKeyFragment(); Bundle args = new Bundle(); args.putParcelable(ARG_DATA_URI, dataUri); + args.putBoolean(ARG_IS_SECRET, isSecret); + args.putByteArray(ARG_FINGERPRINT, fingerprint); frag.setArguments(args); return frag; } + @Override + public void onActivityCreated(Bundle savedInstanceState) { + super.onActivityCreated(savedInstanceState); + + Bundle args = getArguments(); + Uri dataUri = args.getParcelable(ARG_DATA_URI); + if (dataUri == null) { + Log.e(Constants.TAG, "Data missing. Should be Uri of key!"); + getActivity().finish(); + return; + } + boolean isSecret = args.getBoolean(ARG_IS_SECRET); + byte[] fingerprint = args.getByteArray(ARG_FINGERPRINT); + + loadData(dataUri, isSecret, fingerprint); + } + @Override public View onCreateView(LayoutInflater inflater, ViewGroup superContainer, Bundle savedInstanceState) { View root = super.onCreateView(inflater, superContainer, savedInstanceState); @@ -112,7 +131,7 @@ public class ViewKeyFragment extends LoaderFragment implements private void showLinkedId(final int position) { Fragment frag; try { - frag = mLinkedIdsAdapter.getLinkedIdFragment(position); + frag = mLinkedIdsAdapter.getLinkedIdFragment(position, mFingerprint); } catch (IOException e) { e.printStackTrace(); return; @@ -149,45 +168,28 @@ public class ViewKeyFragment extends LoaderFragment implements } } - @Override - public void onActivityCreated(Bundle savedInstanceState) { - super.onActivityCreated(savedInstanceState); - - Uri dataUri = getArguments().getParcelable(ARG_DATA_URI); - if (dataUri == null) { - Log.e(Constants.TAG, "Data missing. Should be Uri of key!"); - getActivity().finish(); - return; - } - - loadData(dataUri); - } - - - // These are the rows that we will retrieve. - static final String[] UNIFIED_PROJECTION = new String[]{ - KeychainContract.KeyRings._ID, - KeychainContract.KeyRings.HAS_ANY_SECRET, - }; - - static final int INDEX_HAS_ANY_SECRET = 1; - - private void loadData(Uri dataUri) { + private void loadData(Uri dataUri, boolean isSecret, byte[] fingerprint) { mDataUri = dataUri; + mIsSecret = isSecret; + mFingerprint = fingerprint; Log.i(Constants.TAG, "mDataUri: " + mDataUri); - getLoaderManager().initLoader(LOADER_ID_UNIFIED, null, this); + // load user ids after we know if it's a secret key + mUserIdsAdapter = new UserIdsAdapter(getActivity(), null, 0, !mIsSecret, null); + mUserIds.setAdapter(mUserIdsAdapter); + getLoaderManager().initLoader(LOADER_ID_USER_IDS, null, this); + + mLinkedIdsAdapter = new LinkedIdsAdapter(getActivity(), null, 0, !mIsSecret); + mLinkedIds.setAdapter(mLinkedIdsAdapter); + getLoaderManager().initLoader(LOADER_ID_LINKED_IDS, null, this); + } public Loader onCreateLoader(int id, Bundle args) { setContentShown(false); switch (id) { - case LOADER_ID_UNIFIED: { - Uri baseUri = KeychainContract.KeyRings.buildUnifiedKeyRingUri(mDataUri); - return new CursorLoader(getActivity(), baseUri, UNIFIED_PROJECTION, null, null, null); - } case LOADER_ID_USER_IDS: return UserIdsAdapter.createLoader(getActivity(), mDataUri); @@ -203,28 +205,6 @@ public class ViewKeyFragment extends LoaderFragment implements // Swap the new cursor in. (The framework will take care of closing the // old cursor once we return.) switch (loader.getId()) { - case LOADER_ID_UNIFIED: { - // Avoid NullPointerExceptions... - if (data.getCount() == 0) { - return; - } - if (data.moveToFirst()) { - - mIsSecret = data.getInt(INDEX_HAS_ANY_SECRET) != 0; - - // load user ids after we know if it's a secret key - mUserIdsAdapter = new UserIdsAdapter(getActivity(), null, 0, !mIsSecret, null); - mUserIds.setAdapter(mUserIdsAdapter); - getLoaderManager().initLoader(LOADER_ID_USER_IDS, null, this); - - mLinkedIdsAdapter = new LinkedIdsAdapter(getActivity(), null, 0, !mIsSecret); - mLinkedIds.setAdapter(mLinkedIdsAdapter); - getLoaderManager().initLoader(LOADER_ID_LINKED_IDS, null, this); - - break; - } - } - case LOADER_ID_USER_IDS: { mUserIdsAdapter.swapCursor(data); 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 7383db1b0..365b8d265 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 @@ -125,7 +125,7 @@ public class LinkedIdsAdapter extends UserAttributesAdapter { UserIdsAdapter.USER_PACKETS_PROJECTION, LINKED_IDS_WHERE, null, null); } - public Fragment getLinkedIdFragment(int position) throws IOException { + public Fragment getLinkedIdFragment(int position, byte[] fingerprint) throws IOException { RawLinkedIdentity id = getItem(position); Integer isVerified; @@ -137,7 +137,7 @@ public class LinkedIdsAdapter extends UserAttributesAdapter { isVerified = null; } - return LinkedIdViewFragment.newInstance(id, isVerified); + return LinkedIdViewFragment.newInstance(id, isVerified, fingerprint); } public static class ViewHolder { 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 b526776f0..5cf0ed115 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 @@ -4,6 +4,7 @@ import java.io.IOException; import android.content.Context; import android.content.Intent; +import android.os.AsyncTask; import android.os.Bundle; import android.support.v4.app.Fragment; import android.support.v7.widget.CardView; @@ -11,8 +12,13 @@ import android.view.LayoutInflater; import android.view.View; import android.view.View.OnClickListener; import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.TextView; +import android.widget.ViewAnimator; import org.sufficientlysecure.keychain.R; +import org.sufficientlysecure.keychain.operations.results.LinkedVerifyResult; import org.sufficientlysecure.keychain.pgp.linked.LinkedCookieResource; import org.sufficientlysecure.keychain.pgp.linked.LinkedIdentity; import org.sufficientlysecure.keychain.pgp.linked.LinkedResource; @@ -21,12 +27,15 @@ import org.sufficientlysecure.keychain.provider.KeychainContract.Certs; import org.sufficientlysecure.keychain.ui.adapter.LinkedIdsAdapter.ViewHolder; import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils; import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils.State; +import org.sufficientlysecure.keychain.ui.util.Notify; +import org.sufficientlysecure.keychain.ui.util.Notify.Style; public class LinkedIdViewFragment extends Fragment { - private static final String EXTRA_ENCODED_LID = "encoded_lid"; - private static final String EXTRA_VERIFIED = "verified"; + private static final String ARG_ENCODED_LID = "encoded_lid"; + private static final String ARG_VERIFIED = "verified"; + private static final String ARG_FINGERPRINT = "fingerprint"; private RawLinkedIdentity mLinkedId; private LinkedCookieResource mLinkedResource; @@ -34,13 +43,20 @@ public class LinkedIdViewFragment extends Fragment { private CardView vLinkedIdsCard; private Context mContext; + private byte[] mFingerprint; + private LayoutInflater mInflater; + private LinearLayout vLinkedCerts; + + private View mCurrentCert; + private boolean mInProgress; + private ViewAnimator mButtonSwitcher; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); Bundle args = getArguments(); - byte[] data = args.getByteArray(EXTRA_ENCODED_LID); + byte[] data = args.getByteArray(ARG_ENCODED_LID); try { mLinkedId = LinkedIdentity.fromAttributeData(data); @@ -55,19 +71,24 @@ public class LinkedIdViewFragment extends Fragment { mLinkedResource = (LinkedCookieResource) res; } - mVerified = args.containsKey(EXTRA_VERIFIED) ? args.getInt(EXTRA_VERIFIED) : null; + mVerified = args.containsKey(ARG_VERIFIED) ? args.getInt(ARG_VERIFIED) : null; + mFingerprint = args.getByteArray(ARG_FINGERPRINT); mContext = getActivity(); + mInflater = getLayoutInflater(savedInstanceState); + } - public static Fragment newInstance(RawLinkedIdentity id, Integer isVerified) throws IOException { + public static Fragment newInstance(RawLinkedIdentity id, + Integer isVerified, byte[] fingerprint) throws IOException { LinkedIdViewFragment frag = new LinkedIdViewFragment(); Bundle args = new Bundle(); - args.putByteArray(EXTRA_ENCODED_LID, id.toUserAttribute().getEncoded()); + args.putByteArray(ARG_ENCODED_LID, id.toUserAttribute().getEncoded()); if (isVerified != null) { - args.putInt(EXTRA_VERIFIED, isVerified); + args.putInt(ARG_VERIFIED, isVerified); } + args.putByteArray(ARG_FINGERPRINT, fingerprint); frag.setArguments(args); return frag; @@ -78,6 +99,7 @@ public class LinkedIdViewFragment extends Fragment { View root = inflater.inflate(R.layout.linked_id_view_fragment, null); vLinkedIdsCard = (CardView) root.findViewById(R.id.card_linked_ids); + vLinkedCerts = (LinearLayout) root.findViewById(R.id.linked_id_certs); View back = root.findViewById(R.id.back_button); back.setClickable(true); @@ -136,6 +158,8 @@ public class LinkedIdViewFragment extends Fragment { button_view.setVisibility(View.GONE); } + mButtonSwitcher = (ViewAnimator) root.findViewById(R.id.button_animator); + View button_verify = root.findViewById(R.id.button_verify); button_verify.setOnClickListener(new OnClickListener() { @Override @@ -144,12 +168,88 @@ public class LinkedIdViewFragment extends Fragment { } }); + View button_retry = root.findViewById(R.id.button_retry); + button_retry.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + verifyResource(); + } + }); + + View button_confirm = root.findViewById(R.id.button_confirm); + button_confirm.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + Notify.createNotify(getActivity(), "confirmed!", Notify.LENGTH_LONG, Style.INFO).show(); + } + }); + return root; } + static class ViewHolderCert { + final ViewAnimator vProgress; + final ImageView vIcon; + final TextView vText; + + ViewHolderCert(View view) { + vProgress = (ViewAnimator) view.findViewById(R.id.linked_cert_progress); + vIcon = (ImageView) view.findViewById(R.id.linked_cert_icon); + vText = (TextView) view.findViewById(R.id.linked_cert_text); + } + void setShowProgress(boolean show) { + vProgress.setDisplayedChild(show ? 0 : 1); + } + } + public void verifyResource() { - // TODO + // only one at a time + synchronized (this) { + if (mInProgress) { + return; + } + mInProgress = true; + } + + // is there a current certification? if not create a new one + final ViewHolderCert holder; + if (mCurrentCert == null) { + mCurrentCert = mInflater.inflate(R.layout.linked_id_cert, null); + holder = new ViewHolderCert(mCurrentCert); + mCurrentCert.setTag(holder); + vLinkedCerts.addView(mCurrentCert); + } else { + holder = (ViewHolderCert) mCurrentCert.getTag(); + } + + holder.setShowProgress(true); + holder.vText.setText("Verifying…"); + + new AsyncTask() { + @Override + protected LinkedVerifyResult doInBackground(Void... params) { + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + // nvm + } + return mLinkedResource.verify(mFingerprint, mLinkedId.mNonce); + } + + @Override + protected void onPostExecute(LinkedVerifyResult result) { + holder.setShowProgress(false); + if (result.success()) { + mButtonSwitcher.setDisplayedChild(2); + holder.vText.setText("Ok"); + } else { + mButtonSwitcher.setDisplayedChild(1); + holder.vText.setText("Error"); + } + mInProgress = false; + } + }.execute(); } diff --git a/OpenKeychain/src/main/res/anim/fade_in.xml b/OpenKeychain/src/main/res/anim/fade_in.xml new file mode 100644 index 000000000..5e2b8be60 --- /dev/null +++ b/OpenKeychain/src/main/res/anim/fade_in.xml @@ -0,0 +1,7 @@ + + + + \ No newline at end of file diff --git a/OpenKeychain/src/main/res/anim/fade_out.xml b/OpenKeychain/src/main/res/anim/fade_out.xml new file mode 100644 index 000000000..f96bf3cb3 --- /dev/null +++ b/OpenKeychain/src/main/res/anim/fade_out.xml @@ -0,0 +1,7 @@ + + + + \ No newline at end of file diff --git a/OpenKeychain/src/main/res/layout/linked_id_cert.xml b/OpenKeychain/src/main/res/layout/linked_id_cert.xml new file mode 100644 index 000000000..b2b841ffc --- /dev/null +++ b/OpenKeychain/src/main/res/layout/linked_id_cert.xml @@ -0,0 +1,52 @@ + + + + + + + + + + + + + + + + + diff --git a/OpenKeychain/src/main/res/layout/linked_id_view_fragment.xml b/OpenKeychain/src/main/res/layout/linked_id_view_fragment.xml index abd71416f..b1a6490c7 100644 --- a/OpenKeychain/src/main/res/layout/linked_id_view_fragment.xml +++ b/OpenKeychain/src/main/res/layout/linked_id_view_fragment.xml @@ -31,6 +31,14 @@ + + + -