aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--OpenKeychain/build.gradle1
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java28
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/linked/LinkedIdViewFragment.java102
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/CertListWidget.java131
-rw-r--r--OpenKeychain/src/main/res/layout/cert_list_widget.xml44
-rw-r--r--OpenKeychain/src/main/res/layout/linked_id_view_fragment.xml69
6 files changed, 295 insertions, 80 deletions
diff --git a/OpenKeychain/build.gradle b/OpenKeychain/build.gradle
index 97c8a6d5e..8a39cafc6 100644
--- a/OpenKeychain/build.gradle
+++ b/OpenKeychain/build.gradle
@@ -20,6 +20,7 @@ dependencies {
compile 'it.neokree:MaterialNavigationDrawer:1.3.1'
compile 'com.nispok:snackbar:2.9.1'
compile 'com.getbase:floatingactionbutton:1.8.0'
+ compile 'com.ocpsoft:ocpsoft-pretty-time:1.0.6'
// libs as submodules
compile project(':extern:openpgp-api-lib')
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 59e0efbd0..3edadec2f 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java
@@ -839,9 +839,7 @@ public class ViewKeyActivity extends BaseActivity implements
mIsExpired = data.getInt(INDEX_IS_EXPIRED) != 0;
mIsVerified = data.getInt(INDEX_VERIFIED) > 0;
- if (oldFingerprint == null) {
- startFragment(mIsSecret, fpData);
- }
+ startFragment(mIsSecret, fpData);
// get name, email, and comment from USER_ID
String[] mainUserId = KeyRing.splitUserId(data.getString(INDEX_USER_ID));
@@ -1000,21 +998,25 @@ public class ViewKeyActivity extends BaseActivity implements
}
- private void startFragment(boolean isSecret, byte[] fingerprint) {
- // Create an instance of the fragment
- final ViewKeyFragment frag = ViewKeyFragment.newInstance(mDataUri, isSecret, fingerprint);
-
+ private void startFragment(final boolean isSecret, final byte[] fingerprint) {
new Handler().post(new Runnable() {
@Override
public void run() {
FragmentManager manager = getSupportFragmentManager();
- manager.popBackStack("linked_id", FragmentManager.POP_BACK_STACK_INCLUSIVE);
- // Add the fragment to the 'fragment_container' FrameLayout
- // NOTE: We use commitAllowingStateLoss() to prevent weird crashes!
- manager.beginTransaction()
- .replace(R.id.view_key_fragment, frag, "main")
- .commit();
+ if (manager.getBackStackEntryCount() == 0) {
+ // Create an instance of the fragment
+ final ViewKeyFragment frag = ViewKeyFragment.newInstance(
+ mDataUri, isSecret, fingerprint);
+ manager.beginTransaction()
+ .replace(R.id.view_key_fragment, frag)
+ .commit();
+ manager.popBackStack();
+ } else {
+ // not sure yet if we actually want this!
+ // manager.popBackStack();
+ }
+
}
});
}
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 284e6e0c1..5b8d14c4c 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
@@ -22,7 +22,6 @@ 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;
@@ -44,10 +43,10 @@ import org.sufficientlysecure.keychain.service.KeychainIntentServiceHandler;
import org.sufficientlysecure.keychain.service.PassphraseCacheService;
import org.sufficientlysecure.keychain.ui.PassphraseDialogActivity;
import org.sufficientlysecure.keychain.ui.adapter.LinkedIdsAdapter;
-import org.sufficientlysecure.keychain.ui.adapter.LinkedIdsCertAdapter;
import org.sufficientlysecure.keychain.ui.adapter.UserIdsAdapter;
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils.State;
+import org.sufficientlysecure.keychain.ui.widget.CertListWidget;
import org.sufficientlysecure.keychain.ui.widget.CertifyKeySpinner;
import org.sufficientlysecure.keychain.util.Log;
@@ -61,8 +60,7 @@ public class LinkedIdViewFragment extends Fragment implements
private static final String ARG_LID_RANK = "rank";
private static final String ARG_SHOWCERT = "verified";
private static final String ARG_FINGERPRINT = "fingerprint";
- private static final int LOADER_ID_LINKED_CERTS = 1;
- private static final int LOADER_ID_LINKED_ID = 2;
+ private static final int LOADER_ID_LINKED_ID = 1;
private RawLinkedIdentity mLinkedId;
private LinkedCookieResource mLinkedResource;
@@ -74,10 +72,8 @@ public class LinkedIdViewFragment extends Fragment implements
private boolean mInProgress;
- private LinkedIdsCertAdapter mCertAdapter;
private Uri mDataUri;
private ViewHolder mViewHolder;
- private View mCurrentCert;
private int mLidRank;
private OnIdentityLoadedListener mIdLoadedListener;
@@ -109,11 +105,9 @@ public class LinkedIdViewFragment extends Fragment implements
mContext = getActivity();
mInflater = getLayoutInflater(savedInstanceState);
- mCertAdapter = new LinkedIdsCertAdapter(getActivity(), null, 0);
- // getLoaderManager().initLoader(LOADER_ID_LINKED_CERTS, null, this);
getLoaderManager().initLoader(LOADER_ID_LINKED_ID, null, this);
-
}
+
@Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
switch (id) {
@@ -122,10 +116,6 @@ public class LinkedIdViewFragment extends Fragment implements
UserIdsAdapter.USER_PACKETS_PROJECTION,
Tables.USER_PACKETS + "." + UserPackets.RANK
+ " = " + Integer.toString(mLidRank), null, null);
-
- case LOADER_ID_LINKED_CERTS:
- return LinkedIdsCertAdapter.createLoader(getActivity(), mDataUri);
-
default:
return null;
}
@@ -162,10 +152,6 @@ public class LinkedIdViewFragment extends Fragment implements
}
break;
-
- case LOADER_ID_LINKED_CERTS:
- mCertAdapter.swapCursor(cursor);
- break;
}
}
@@ -180,6 +166,16 @@ public class LinkedIdViewFragment extends Fragment implements
private void loadIdentity(RawLinkedIdentity linkedId, int certStatus) {
mLinkedId = linkedId;
+ mViewHolder.setShowVerifying(false);
+
+ {
+ Bundle args = new Bundle();
+ args.putParcelable(CertListWidget.ARG_URI, mDataUri);
+ args.putInt(CertListWidget.ARG_RANK, mLidRank);
+ getLoaderManager().initLoader(CertListWidget.LOADER_ID_LINKED_CERTS,
+ args, mViewHolder.vLinkedCerts);
+ }
+
if (mLinkedId instanceof LinkedIdentity) {
LinkedResource res = ((LinkedIdentity) mLinkedId).mResource;
mLinkedResource = (LinkedCookieResource) res;
@@ -235,30 +231,28 @@ public class LinkedIdViewFragment extends Fragment implements
@Override
public void onLoaderReset(Loader<Cursor> loader) {
- switch (loader.getId()) {
- case LOADER_ID_LINKED_CERTS:
- mCertAdapter.swapCursor(null);
- break;
- }
}
static class ViewHolder {
private final View vButtonView;
+ private final ViewAnimator vVerifyingContainer;
LinkedIdsAdapter.ViewHolder mLinkedIdHolder;
private ViewAnimator mButtonSwitcher;
- private LinearLayout vLinkedCerts;
+ private CertListWidget vLinkedCerts;
private CertifyKeySpinner vKeySpinner;
- private LinearLayout vLinkedVerify;
private final View vButtonVerify;
private final View vButtonRetry;
private final View vButtonConfirm;
private final View vButtonBack;
+ private final ViewAnimator vProgress;
+ private final ImageView vIcon;
+ private final TextView vText;
+
ViewHolder(View root) {
- vLinkedCerts = (LinearLayout) root.findViewById(R.id.linked_id_certs);
- vLinkedVerify = (LinearLayout) root.findViewById(R.id.linked_id_verify);
+ vLinkedCerts = (CertListWidget) root.findViewById(R.id.linked_id_certs);
vKeySpinner = (CertifyKeySpinner) root.findViewById(R.id.cert_key_spinner);
mButtonSwitcher = (ViewAnimator) root.findViewById(R.id.button_animator);
@@ -269,6 +263,26 @@ public class LinkedIdViewFragment extends Fragment implements
vButtonRetry = root.findViewById(R.id.button_retry);
vButtonConfirm = root.findViewById(R.id.button_confirm);
vButtonView = root.findViewById(R.id.button_view);
+
+ vVerifyingContainer = (ViewAnimator) root.findViewById(R.id.linked_verify_container);
+
+ vProgress = (ViewAnimator) root.findViewById(R.id.linked_cert_progress);
+ vIcon = (ImageView) root.findViewById(R.id.linked_cert_icon);
+ vText = (TextView) root.findViewById(R.id.linked_cert_text);
+ }
+
+ void setShowVerifying(boolean show) {
+ int child = show ? 1 : 0;
+ if (vVerifyingContainer.getDisplayedChild() != child) {
+ vVerifyingContainer.setDisplayedChild(child);
+ }
+ if (!show) {
+ vKeySpinner.setVisibility(View.GONE);
+ }
+ }
+
+ void setShowProgress(boolean show) {
+ vProgress.setDisplayedChild(show ? 0 : 1);
}
}
@@ -310,21 +324,6 @@ public class LinkedIdViewFragment extends Fragment implements
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);
- }
- }
-
void showButton(int which) {
if (mViewHolder.mButtonSwitcher.getDisplayedChild() == which) {
return;
@@ -342,20 +341,11 @@ public class LinkedIdViewFragment extends Fragment implements
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);
- mViewHolder.vLinkedVerify.addView(mCurrentCert);
- } else {
- holder = (ViewHolderCert) mCurrentCert.getTag();
- }
+ mViewHolder.setShowVerifying(true);
mViewHolder.vKeySpinner.setVisibility(View.GONE);
- holder.setShowProgress(true);
- holder.vText.setText("Verifying…");
+ mViewHolder.setShowProgress(true);
+ mViewHolder.vText.setText("Verifying…");
new AsyncTask<Void,Void,LinkedVerifyResult>() {
@Override
@@ -376,13 +366,13 @@ public class LinkedIdViewFragment extends Fragment implements
@Override
protected void onPostExecute(LinkedVerifyResult result) {
- holder.setShowProgress(false);
+ mViewHolder.setShowProgress(false);
if (result.success()) {
- holder.vText.setText("Ok");
+ mViewHolder.vText.setText("Ok");
setupForConfirmation();
} else {
showButton(1);
- holder.vText.setText("Error");
+ mViewHolder.vText.setText("Error");
}
mInProgress = false;
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/CertListWidget.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/CertListWidget.java
new file mode 100644
index 000000000..3e9cffb69
--- /dev/null
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/CertListWidget.java
@@ -0,0 +1,131 @@
+package org.sufficientlysecure.keychain.ui.widget;
+
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+import android.content.Context;
+import android.database.Cursor;
+import android.net.Uri;
+import android.os.Bundle;
+import android.support.v4.app.LoaderManager;
+import android.support.v4.content.CursorLoader;
+import android.support.v4.content.Loader;
+import android.text.SpannableStringBuilder;
+import android.util.AttributeSet;
+import android.view.View;
+import android.widget.TextView;
+import android.widget.ViewAnimator;
+
+import com.ocpsoft.pretty.time.PrettyTime;
+import org.sufficientlysecure.keychain.R;
+import org.sufficientlysecure.keychain.provider.KeychainContract;
+import org.sufficientlysecure.keychain.provider.KeychainContract.Certs;
+
+public class CertListWidget extends ViewAnimator
+ implements LoaderManager.LoaderCallbacks<Cursor> {
+
+ public static final int LOADER_ID_LINKED_CERTS = 38572;
+
+ public static final String ARG_URI = "uri";
+ public static final String ARG_RANK = "rank";
+
+
+ // These are the rows that we will retrieve.
+ static final String[] CERTS_PROJECTION = new String[]{
+ KeychainContract.Certs._ID,
+ KeychainContract.Certs.MASTER_KEY_ID,
+ KeychainContract.Certs.VERIFIED,
+ KeychainContract.Certs.TYPE,
+ KeychainContract.Certs.RANK,
+ KeychainContract.Certs.KEY_ID_CERTIFIER,
+ KeychainContract.Certs.USER_ID,
+ KeychainContract.Certs.SIGNER_UID,
+ KeychainContract.Certs.CREATION
+ };
+ public static final int INDEX_MASTER_KEY_ID = 1;
+ public static final int INDEX_VERIFIED = 2;
+ public static final int INDEX_TYPE = 3;
+ public static final int INDEX_RANK = 4;
+ public static final int INDEX_KEY_ID_CERTIFIER = 5;
+ public static final int INDEX_USER_ID = 6;
+ public static final int INDEX_SIGNER_UID = 7;
+ public static final int INDEX_CREATION = 8;
+
+ private TextView vCollapsed;
+ private View vExpanded;
+ private View vExpandButton;
+
+ public CertListWidget(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ @Override
+ protected void onFinishInflate() {
+ super.onFinishInflate();
+
+ View root = getRootView();
+ vCollapsed = (TextView) root.findViewById(R.id.cert_collapsed_list);
+ vExpanded = root.findViewById(R.id.cert_expanded_list);
+ vExpandButton = root.findViewById(R.id.cert_expand_button);
+
+ // for now
+ vExpandButton.setVisibility(View.GONE);
+ }
+
+ void setExpanded(boolean expanded) {
+ setDisplayedChild(expanded ? 1 : 0);
+ }
+
+ @Override
+ public Loader<Cursor> onCreateLoader(int id, Bundle args) {
+ Uri baseUri = args.getParcelable(ARG_URI);
+ int rank = args.getInt(ARG_RANK);
+
+ Uri uri = Certs.buildLinkedIdCertsUri(baseUri, rank);
+ return new CursorLoader(getContext(), uri,
+ CERTS_PROJECTION, null, null, null);
+
+ }
+
+ @Override
+ public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
+
+ if (data == null || !data.moveToFirst()) {
+ return;
+ }
+
+ setVisibility(View.VISIBLE);
+
+ // TODO support external certificates
+ Date userCert = null;
+ while (!data.isAfterLast()) {
+
+ int verified = data.getInt(INDEX_VERIFIED);
+ Date creation = new Date(data.getLong(INDEX_CREATION) * 1000);
+
+ if (verified == Certs.VERIFIED_SECRET) {
+ if (userCert == null || userCert.after(creation)) {
+ userCert = creation;
+ }
+ }
+
+ data.moveToNext();
+ }
+
+ if (userCert != null) {
+ PrettyTime format = new PrettyTime();
+ vCollapsed.setText("You verified and confirmed this identity "
+ + format.format(userCert) + ".");
+ } else {
+ vCollapsed.setText("This identity is not yet verified or confirmed.");
+ }
+
+ }
+
+ @Override
+ public void onLoaderReset(Loader<Cursor> loader) {
+ setVisibility(View.GONE);
+ }
+
+}
diff --git a/OpenKeychain/src/main/res/layout/cert_list_widget.xml b/OpenKeychain/src/main/res/layout/cert_list_widget.xml
new file mode 100644
index 000000000..715e4bfa5
--- /dev/null
+++ b/OpenKeychain/src/main/res/layout/cert_list_widget.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="utf-8"?>
+<org.sufficientlysecure.keychain.ui.widget.CertListWidget
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_marginLeft="12dp"
+ android:layout_marginRight="12dp"
+ android:id="@+id/linked_id_certs">
+
+ <LinearLayout
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal"
+ android:minHeight="?android:attr/listPreferredItemHeight"
+ >
+
+ <TextView
+ android:id="@+id/cert_collapsed_list"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:gravity="center_vertical"
+ android:layout_weight="1"
+ />
+
+ <ImageView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_vertical"
+ android:src="@drawable/ic_expand_more_black_24dp"
+ android:id="@+id/cert_expand_button"
+ android:padding="4dp"
+ />
+
+ </LinearLayout>
+
+ <ListView
+ android:id="@+id/cert_expanded_list"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content">
+ </ListView>
+
+</org.sufficientlysecure.keychain.ui.widget.CertListWidget> \ No newline at end of file
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 b453167ea..4244de962 100644
--- a/OpenKeychain/src/main/res/layout/linked_id_view_fragment.xml
+++ b/OpenKeychain/src/main/res/layout/linked_id_view_fragment.xml
@@ -32,21 +32,68 @@
<include layout="@layout/linked_id_item" />
- <LinearLayout
+ <ViewAnimator
android:layout_width="fill_parent"
android:layout_height="wrap_content"
- android:orientation="vertical"
- android:animateLayoutChanges="true"
- android:id="@+id/linked_id_certs">
+ android:id="@+id/linked_verify_container"
+ android:inAnimation="@anim/fade_in"
+ android:outAnimation="@anim/fade_out">
+
+ <include layout="@layout/cert_list_widget" />
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:minHeight="?android:attr/listPreferredItemHeight"
+ android:orientation="horizontal"
+ android:singleLine="true">
+
+ <LinearLayout
+ android:orientation="vertical"
+ android:layout_gravity="center_vertical"
+ android:layout_width="0dip"
+ android:layout_marginLeft="16dp"
+ android:layout_marginTop="4dp"
+ android:layout_marginBottom="4dp"
+ android:layout_height="wrap_content"
+ android:layout_weight="1">
+
+ <TextView
+ android:id="@+id/linked_cert_text"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Verifying…"
+ android:textAppearance="?android:attr/textAppearanceMedium" />
+
+ </LinearLayout>
+
+ <ViewAnimator
+ android:layout_width="22dp"
+ android:layout_height="22dp"
+ android:layout_marginLeft="16dp"
+ android:layout_marginRight="16dp"
+ android:layout_gravity="center"
+ android:id="@+id/linked_cert_progress"
+ android:inAnimation="@anim/fade_in"
+ android:outAnimation="@anim/fade_out">
+
+ <ProgressBar
+ android:layout_width="22dp"
+ android:layout_height="22dp"
+ android:indeterminate="true"
+ />
+
+ <ImageView
+ android:layout_width="22dp"
+ android:layout_height="wrap_content"
+ android:src="@drawable/status_signature_unknown_cutout_24dp"
+ android:id="@+id/linked_cert_icon"
+ />
+ </ViewAnimator>
+
</LinearLayout>
- <LinearLayout
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:orientation="vertical"
- android:animateLayoutChanges="true"
- android:id="@+id/linked_id_verify">
- </LinearLayout>
+ </ViewAnimator>
<org.sufficientlysecure.keychain.ui.widget.CertifyKeySpinner
android:layout_marginLeft="14dp"