aboutsummaryrefslogtreecommitdiffstats
path: root/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget
diff options
context:
space:
mode:
Diffstat (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget')
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/CertListWidget.java143
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/CertifyKeySpinner.java18
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/KeySpinner.java14
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/PrefixedEditText.java45
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/StatusIndicator.java45
5 files changed, 258 insertions, 7 deletions
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..c413a00be
--- /dev/null
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/CertListWidget.java
@@ -0,0 +1,143 @@
+package org.sufficientlysecure.keychain.ui.widget;
+
+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.util.AttributeSet;
+import android.view.View;
+import android.widget.ListView;
+import android.widget.TextView;
+import android.widget.ViewAnimator;
+
+import org.ocpsoft.prettytime.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_IS_SECRET = "is_secret";
+
+
+ // 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 ListView vExpanded;
+ private View vExpandButton;
+ private boolean mIsSecret;
+
+ 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 = (ListView) root.findViewById(R.id.cert_expanded_list);
+ vExpandButton = root.findViewById(R.id.cert_expand_button);
+
+ // for now
+ vExpandButton.setVisibility(View.GONE);
+ vExpandButton.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ toggleExpanded();
+ }
+ });
+
+ // vExpanded.setAdapter(null);
+
+ }
+
+ void toggleExpanded() {
+ setDisplayedChild(getDisplayedChild() == 1 ? 0 : 1);
+ }
+
+ void setExpanded(boolean expanded) {
+ setDisplayedChild(expanded ? 1 : 0);
+ }
+
+ @Override
+ public Loader<Cursor> onCreateLoader(int id, Bundle args) {
+ Uri uri = args.getParcelable(ARG_URI);
+ mIsSecret = args.getBoolean(ARG_IS_SECRET, false);
+ 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;
+ }
+
+ // 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();
+ if (mIsSecret) {
+ vCollapsed.setText("You created this identity "
+ + format.format(userCert) + ".");
+ } else {
+ 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/java/org/sufficientlysecure/keychain/ui/widget/CertifyKeySpinner.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/CertifyKeySpinner.java
index 6cd33aada..6a51085f3 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/CertifyKeySpinner.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/CertifyKeySpinner.java
@@ -17,25 +17,24 @@
package org.sufficientlysecure.keychain.ui.widget;
-
-import java.util.Arrays;
-import java.util.List;
-
import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
+import android.support.annotation.StringRes;
import android.support.v4.content.CursorLoader;
import android.support.v4.content.Loader;
import android.util.AttributeSet;
import org.sufficientlysecure.keychain.Constants;
+import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.provider.KeychainContract;
import org.sufficientlysecure.keychain.provider.KeychainDatabase;
import org.sufficientlysecure.keychain.ui.adapter.KeyAdapter;
public class CertifyKeySpinner extends KeySpinner {
private long mHiddenMasterKeyId = Constants.key.none;
+ private boolean mIsSingle;
public CertifyKeySpinner(Context context) {
super(context);
@@ -94,9 +93,11 @@ public class CertifyKeySpinner extends KeySpinner {
if (!data.isNull(mIndexHasCertify)) {
if (selection == -1) {
selection = data.getPosition() + 1;
+ mIsSingle = true;
} else {
// if selection is already set, we have more than one certify key!
// get back to "none"!
+ mIsSingle = false;
selection = 0;
}
}
@@ -106,6 +107,9 @@ public class CertifyKeySpinner extends KeySpinner {
}
}
+ public boolean isSingleEntry() {
+ return mIsSingle && getSelectedItemPosition() != 0;
+ }
@Override
boolean isItemEnabled(Cursor cursor) {
@@ -128,4 +132,10 @@ public class CertifyKeySpinner extends KeySpinner {
return true;
}
+ @Override
+ public @StringRes int getNoneString() {
+ return R.string.choice_select_cert;
+ }
+
+
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/KeySpinner.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/KeySpinner.java
index 1884daf12..04ed35deb 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/KeySpinner.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/KeySpinner.java
@@ -23,6 +23,7 @@ import android.database.Cursor;
import android.os.Bundle;
import android.os.Parcelable;
import android.support.annotation.NonNull;
+import android.support.annotation.StringRes;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.LoaderManager;
import android.support.v4.content.Loader;
@@ -34,6 +35,7 @@ import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.SpinnerAdapter;
+import android.widget.TextView;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
@@ -117,8 +119,7 @@ public abstract class KeySpinner extends AppCompatSpinner implements
if (getContext() instanceof FragmentActivity) {
((FragmentActivity) getContext()).getSupportLoaderManager().restartLoader(LOADER_ID, null, this);
} else {
- throw new AssertionError("KeySpinner must be attached to FragmentActivity, this is "
- + getContext().getClass());
+ // ignore, this happens during preview! we use fragmentactivities everywhere either way
}
}
@@ -226,9 +227,11 @@ public abstract class KeySpinner extends AppCompatSpinner implements
return inner.getView(position -1, convertView, parent);
}
- return convertView != null ? convertView :
+ View view = convertView != null ? convertView :
LayoutInflater.from(getContext()).inflate(
R.layout.keyspinner_item_none, parent, false);
+ ((TextView) view.findViewById(R.id.keyspinner_key_name)).setText(getNoneString());
+ return view;
}
}
@@ -259,4 +262,9 @@ public abstract class KeySpinner extends AppCompatSpinner implements
bundle.putLong(ARG_KEY_ID, getSelectedKeyId());
return bundle;
}
+
+ public @StringRes int getNoneString() {
+ return R.string.cert_none;
+ }
+
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/PrefixedEditText.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/PrefixedEditText.java
new file mode 100644
index 000000000..3cbb114e8
--- /dev/null
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/PrefixedEditText.java
@@ -0,0 +1,45 @@
+package org.sufficientlysecure.keychain.ui.widget;
+
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.graphics.*;
+import android.support.annotation.NonNull;
+import android.util.AttributeSet;
+import android.widget.EditText;
+
+import org.sufficientlysecure.keychain.R;
+
+public class PrefixedEditText extends EditText {
+
+ private String mPrefix;
+ private Rect mPrefixRect = new Rect();
+
+ public PrefixedEditText(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ TypedArray style = context.getTheme().obtainStyledAttributes(
+ attrs, R.styleable.PrefixedEditText, 0, 0);
+ mPrefix = style.getString(R.styleable.PrefixedEditText_prefix);
+ if (mPrefix == null) {
+ mPrefix = "";
+ }
+ }
+
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ getPaint().getTextBounds(mPrefix, 0, mPrefix.length(), mPrefixRect);
+
+ super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+ }
+
+ @Override
+ protected void onDraw(@NonNull Canvas canvas) {
+ super.onDraw(canvas);
+ canvas.drawText(mPrefix, super.getCompoundPaddingLeft(), getBaseline(), getPaint());
+ }
+
+ @Override
+ public int getCompoundPaddingLeft() {
+ return super.getCompoundPaddingLeft() + mPrefixRect.width();
+ }
+
+} \ No newline at end of file
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/StatusIndicator.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/StatusIndicator.java
new file mode 100644
index 000000000..2784ac5f0
--- /dev/null
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/StatusIndicator.java
@@ -0,0 +1,45 @@
+package org.sufficientlysecure.keychain.ui.widget;
+
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.LayoutInflater;
+import android.view.animation.AnimationUtils;
+
+import org.sufficientlysecure.keychain.R;
+
+
+public class StatusIndicator extends ToolableViewAnimator {
+
+ public enum Status {
+ IDLE, PROGRESS, OK, ERROR
+ }
+
+ public StatusIndicator(Context context) {
+ super(context);
+
+ LayoutInflater.from(context).inflate(R.layout.status_indicator, this, true);
+ setInAnimation(AnimationUtils.loadAnimation(context, R.anim.fade_in));
+ setOutAnimation(AnimationUtils.loadAnimation(context, R.anim.fade_out));
+ }
+
+ public StatusIndicator(Context context, AttributeSet attrs) {
+ super(context, attrs);
+
+ LayoutInflater.from(context).inflate(R.layout.status_indicator, this, true);
+ setInAnimation(AnimationUtils.loadAnimation(context, R.anim.fade_in));
+ setOutAnimation(AnimationUtils.loadAnimation(context, R.anim.fade_out));
+ }
+
+ @Override
+ public void setDisplayedChild(int whichChild) {
+ if (whichChild != getDisplayedChild()) {
+ super.setDisplayedChild(whichChild);
+ }
+ }
+
+ public void setDisplayedChild(Status status) {
+ setDisplayedChild(status.ordinal());
+ }
+
+}