aboutsummaryrefslogtreecommitdiffstats
path: root/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter
diff options
context:
space:
mode:
Diffstat (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter')
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysAdapter.java29
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysListCloudLoader.java48
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/KeyAdapter.java136
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/KeySelectableAdapter.java87
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/MultiUserIdsAdapter.java13
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/SelectKeyCursorAdapter.java4
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/SubkeysAdapter.java51
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/UserIdsAdapter.java2
8 files changed, 295 insertions, 75 deletions
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysAdapter.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysAdapter.java
index db88de676..0be7e8f76 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysAdapter.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysAdapter.java
@@ -33,6 +33,7 @@ import android.widget.TextView;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.keyimport.ImportKeysListEntry;
+import org.sufficientlysecure.keychain.operations.ImportOperation;
import org.sufficientlysecure.keychain.pgp.KeyRing;
import org.sufficientlysecure.keychain.ui.util.FormattingUtils;
import org.sufficientlysecure.keychain.ui.util.Highlighter;
@@ -92,8 +93,8 @@ public class ImportKeysAdapter extends ArrayAdapter<ImportKeysListEntry> {
}
/** This method returns a list of all selected entries, with public keys sorted
- * before secret keys, see ImportExportOperation for specifics.
- * @see org.sufficientlysecure.keychain.operations.ImportExportOperation
+ * before secret keys, see ImportOperation for specifics.
+ * @see ImportOperation
*/
public ArrayList<ImportKeysListEntry> getSelectedEntries() {
ArrayList<ImportKeysListEntry> result = new ArrayList<>();
@@ -176,9 +177,9 @@ public class ImportKeysAdapter extends ArrayAdapter<ImportKeysListEntry> {
}
if (entry.isRevoked()) {
- KeyFormattingUtils.setStatusImage(getContext(), holder.status, null, State.REVOKED, R.color.bg_gray);
+ KeyFormattingUtils.setStatusImage(getContext(), holder.status, null, State.REVOKED, R.color.key_flag_gray);
} else if (entry.isExpired()) {
- KeyFormattingUtils.setStatusImage(getContext(), holder.status, null, State.EXPIRED, R.color.bg_gray);
+ KeyFormattingUtils.setStatusImage(getContext(), holder.status, null, State.EXPIRED, R.color.key_flag_gray);
}
if (entry.isRevoked() || entry.isExpired()) {
@@ -187,9 +188,9 @@ public class ImportKeysAdapter extends ArrayAdapter<ImportKeysListEntry> {
// no more space for algorithm display
holder.algorithm.setVisibility(View.GONE);
- holder.mainUserId.setTextColor(getContext().getResources().getColor(R.color.bg_gray));
- holder.mainUserIdRest.setTextColor(getContext().getResources().getColor(R.color.bg_gray));
- holder.keyId.setTextColor(getContext().getResources().getColor(R.color.bg_gray));
+ holder.mainUserId.setTextColor(getContext().getResources().getColor(R.color.key_flag_gray));
+ holder.mainUserIdRest.setTextColor(getContext().getResources().getColor(R.color.key_flag_gray));
+ holder.keyId.setTextColor(getContext().getResources().getColor(R.color.key_flag_gray));
} else {
holder.status.setVisibility(View.GONE);
holder.algorithm.setVisibility(View.VISIBLE);
@@ -197,11 +198,11 @@ public class ImportKeysAdapter extends ArrayAdapter<ImportKeysListEntry> {
if (entry.isSecretKey()) {
holder.mainUserId.setTextColor(Color.RED);
} else {
- holder.mainUserId.setTextColor(Color.BLACK);
+ holder.mainUserId.setTextColor(FormattingUtils.getColorFromAttr(mActivity, R.attr.colorText));
}
- holder.mainUserIdRest.setTextColor(Color.BLACK);
- holder.keyId.setTextColor(Color.BLACK);
+ holder.mainUserIdRest.setTextColor(FormattingUtils.getColorFromAttr(mActivity, R.attr.colorText));
+ holder.keyId.setTextColor(FormattingUtils.getColorFromAttr(mActivity, R.attr.colorText));
}
if (entry.getUserIds().size() == 1) {
@@ -241,9 +242,9 @@ public class ImportKeysAdapter extends ArrayAdapter<ImportKeysListEntry> {
uidView.setPadding(0, 0, FormattingUtils.dpToPx(getContext(), 8), 0);
if (entry.isRevoked() || entry.isExpired()) {
- uidView.setTextColor(getContext().getResources().getColor(R.color.bg_gray));
+ uidView.setTextColor(getContext().getResources().getColor(R.color.key_flag_gray));
} else {
- uidView.setTextColor(getContext().getResources().getColor(R.color.black));
+ uidView.setTextColor(FormattingUtils.getColorFromAttr(getContext(), R.attr.colorText));
}
holder.userIdsList.addView(uidView);
@@ -257,9 +258,9 @@ public class ImportKeysAdapter extends ArrayAdapter<ImportKeysListEntry> {
emailView.setText(highlighter.highlight(email));
if (entry.isRevoked() || entry.isExpired()) {
- emailView.setTextColor(getContext().getResources().getColor(R.color.bg_gray));
+ emailView.setTextColor(getContext().getResources().getColor(R.color.key_flag_gray));
} else {
- emailView.setTextColor(getContext().getResources().getColor(R.color.black));
+ emailView.setTextColor(FormattingUtils.getColorFromAttr(getContext(), R.attr.colorText));
}
holder.userIdsList.addView(emailView);
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysListCloudLoader.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysListCloudLoader.java
index 4781864dd..e77c92923 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysListCloudLoader.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/ImportKeysListCloudLoader.java
@@ -18,6 +18,7 @@
package org.sufficientlysecure.keychain.ui.adapter;
import android.content.Context;
+import android.support.annotation.Nullable;
import android.support.v4.content.AsyncTaskLoader;
import org.sufficientlysecure.keychain.Constants;
@@ -26,8 +27,12 @@ import org.sufficientlysecure.keychain.keyimport.ImportKeysListEntry;
import org.sufficientlysecure.keychain.keyimport.Keyserver;
import org.sufficientlysecure.keychain.operations.results.GetKeyResult;
import org.sufficientlysecure.keychain.operations.results.OperationResult;
+import org.sufficientlysecure.keychain.service.input.CryptoInputParcel;
+import org.sufficientlysecure.keychain.service.input.RequiredInputParcel;
import org.sufficientlysecure.keychain.util.Log;
+import org.sufficientlysecure.keychain.util.ParcelableProxy;
import org.sufficientlysecure.keychain.util.Preferences;
+import org.sufficientlysecure.keychain.util.orbot.OrbotHelper;
import java.util.ArrayList;
@@ -38,15 +43,27 @@ public class ImportKeysListCloudLoader
Preferences.CloudSearchPrefs mCloudPrefs;
String mServerQuery;
+ private ParcelableProxy mParcelableProxy;
private ArrayList<ImportKeysListEntry> mEntryList = new ArrayList<>();
private AsyncTaskResultWrapper<ArrayList<ImportKeysListEntry>> mEntryListWrapper;
- public ImportKeysListCloudLoader(Context context, String serverQuery, Preferences.CloudSearchPrefs cloudPrefs) {
+ /**
+ * Searches a keyserver as specified in cloudPrefs, using an explicit proxy if passed
+ *
+ * @param serverQuery string to search on servers for. If is a fingerprint,
+ * will enforce fingerprint check
+ * @param cloudPrefs contains keyserver to search on, whether to search on the keyserver,
+ * and whether to search keybase.io
+ * @param parcelableProxy explicit proxy to use. If null, will retrieve from preferences
+ */
+ public ImportKeysListCloudLoader(Context context, String serverQuery, Preferences.CloudSearchPrefs cloudPrefs,
+ @Nullable ParcelableProxy parcelableProxy) {
super(context);
mContext = context;
mServerQuery = serverQuery;
mCloudPrefs = cloudPrefs;
+ mParcelableProxy = parcelableProxy;
}
@Override
@@ -95,9 +112,32 @@ public class ImportKeysListCloudLoader
* Query keyserver
*/
private void queryServer(boolean enforceFingerprint) {
+ ParcelableProxy parcelableProxy;
+
+ if (mParcelableProxy == null) {
+ // no explicit proxy specified, fetch from preferences
+ if (OrbotHelper.isOrbotInRequiredState(mContext)) {
+ parcelableProxy = Preferences.getPreferences(mContext).getProxyPrefs()
+ .parcelableProxy;
+ } else {
+ // user needs to enable/install orbot
+ mEntryList.clear();
+ GetKeyResult pendingResult = new GetKeyResult(null,
+ RequiredInputParcel.createOrbotRequiredOperation(),
+ new CryptoInputParcel());
+ mEntryListWrapper = new AsyncTaskResultWrapper<>(mEntryList, pendingResult);
+ return;
+ }
+ } else {
+ parcelableProxy = mParcelableProxy;
+ }
+
try {
- ArrayList<ImportKeysListEntry> searchResult
- = CloudSearch.search(mServerQuery, mCloudPrefs);
+ ArrayList<ImportKeysListEntry> searchResult = CloudSearch.search(
+ mServerQuery,
+ mCloudPrefs,
+ parcelableProxy.getProxy()
+ );
mEntryList.clear();
// add result to data
@@ -109,7 +149,7 @@ public class ImportKeysListCloudLoader
ImportKeysListEntry uniqueEntry = searchResult.get(0);
/*
* set fingerprint explicitly after query
- * to enforce a check when the key is imported by KeychainIntentService
+ * to enforce a check when the key is imported by KeychainService
*/
uniqueEntry.setFingerprintHex(fingerprint);
uniqueEntry.setSelected(true);
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/KeyAdapter.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/KeyAdapter.java
index 3dbae09b6..56d273c7c 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/KeyAdapter.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/KeyAdapter.java
@@ -18,6 +18,11 @@
package org.sufficientlysecure.keychain.ui.adapter;
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Date;
+import java.util.List;
import java.util.Date;
import android.content.Context;
@@ -27,6 +32,7 @@ import android.support.v4.widget.CursorAdapter;
import android.text.format.DateUtils;
import android.view.LayoutInflater;
import android.view.View;
+import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.ImageButton;
import android.widget.ImageView;
@@ -38,6 +44,7 @@ import org.sufficientlysecure.keychain.pgp.CanonicalizedPublicKeyRing;
import org.sufficientlysecure.keychain.pgp.KeyRing;
import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
import org.sufficientlysecure.keychain.ui.util.Highlighter;
+import org.sufficientlysecure.keychain.ui.util.FormattingUtils;
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils.State;
@@ -45,6 +52,7 @@ public class KeyAdapter extends CursorAdapter {
protected String mQuery;
protected LayoutInflater mInflater;
+ protected Context mContext;
// These are the rows that we will retrieve.
public static final String[] PROJECTION = new String[]{
@@ -56,7 +64,6 @@ public class KeyAdapter extends CursorAdapter {
KeyRings.VERIFIED,
KeyRings.HAS_ANY_SECRET,
KeyRings.HAS_DUPLICATE_USER_ID,
- KeyRings.HAS_ENCRYPT,
KeyRings.FINGERPRINT,
KeyRings.CREATION,
};
@@ -68,13 +75,13 @@ public class KeyAdapter extends CursorAdapter {
public static final int INDEX_VERIFIED = 5;
public static final int INDEX_HAS_ANY_SECRET = 6;
public static final int INDEX_HAS_DUPLICATE_USER_ID = 7;
- public static final int INDEX_HAS_ENCRYPT = 8;
- public static final int INDEX_FINGERPRINT = 9;
- public static final int INDEX_CREATION = 10;
+ public static final int INDEX_FINGERPRINT = 8;
+ public static final int INDEX_CREATION = 9;
public KeyAdapter(Context context, Cursor c, int flags) {
super(context, c, flags);
+ mContext = context;
mInflater = LayoutInflater.from(context);
}
@@ -83,6 +90,9 @@ public class KeyAdapter extends CursorAdapter {
}
public static class KeyItemViewHolder {
+ public View mView;
+ public View mLayoutDummy;
+ public View mLayoutData;
public Long mMasterKeyId;
public TextView mMainUserId;
public TextView mMainUserIdRest;
@@ -91,7 +101,12 @@ public class KeyAdapter extends CursorAdapter {
public View mSlinger;
public ImageButton mSlingerButton;
+ public KeyItem mDisplayedItem;
+
public KeyItemViewHolder(View view) {
+ mView = view;
+ mLayoutData = view.findViewById(R.id.key_list_item_data);
+ mLayoutDummy = view.findViewById(R.id.key_list_item_dummy);
mMainUserId = (TextView) view.findViewById(R.id.key_list_item_name);
mMainUserIdRest = (TextView) view.findViewById(R.id.key_list_item_email);
mStatus = (ImageView) view.findViewById(R.id.key_list_item_status_icon);
@@ -100,11 +115,15 @@ public class KeyAdapter extends CursorAdapter {
mCreationDate = (TextView) view.findViewById(R.id.key_list_item_creation);
}
- public void setData(Context context, Cursor cursor, Highlighter highlighter) {
+ public void setData(Context context, KeyItem item, Highlighter highlighter, boolean enabled) {
+
+ mLayoutData.setVisibility(View.VISIBLE);
+ mLayoutDummy.setVisibility(View.GONE);
+
+ mDisplayedItem = item;
{ // set name and stuff, common to both key types
- String userId = cursor.getString(INDEX_USER_ID);
- KeyRing.UserId userIdSplit = KeyRing.splitUserId(userId);
+ KeyRing.UserId userIdSplit = item.mUserId;
if (userIdSplit.name != null) {
mMainUserId.setText(highlighter.highlight(userIdSplit.name));
} else {
@@ -118,43 +137,42 @@ public class KeyAdapter extends CursorAdapter {
}
}
+ // sort of a hack: if this item isn't enabled, we make it clickable
+ // to intercept its click events. either way, no listener!
+ mView.setClickable(!enabled);
+
{ // set edit button and status, specific by key type
- long masterKeyId = cursor.getLong(INDEX_MASTER_KEY_ID);
- boolean isSecret = cursor.getInt(INDEX_HAS_ANY_SECRET) != 0;
- boolean isRevoked = cursor.getInt(INDEX_IS_REVOKED) > 0;
- boolean isExpired = cursor.getInt(INDEX_IS_EXPIRED) != 0;
- boolean isVerified = cursor.getInt(INDEX_VERIFIED) > 0;
- boolean hasDuplicate = cursor.getInt(INDEX_HAS_DUPLICATE_USER_ID) != 0;
+ mMasterKeyId = item.mKeyId;
- mMasterKeyId = masterKeyId;
+ int textColor;
// Note: order is important!
- if (isRevoked) {
+ if (item.mIsRevoked) {
KeyFormattingUtils
- .setStatusImage(context, mStatus, null, State.REVOKED, R.color.bg_gray);
+ .setStatusImage(context, mStatus, null, State.REVOKED, R.color.key_flag_gray);
mStatus.setVisibility(View.VISIBLE);
mSlinger.setVisibility(View.GONE);
- mMainUserId.setTextColor(context.getResources().getColor(R.color.bg_gray));
- mMainUserIdRest.setTextColor(context.getResources().getColor(R.color.bg_gray));
- } else if (isExpired) {
- KeyFormattingUtils.setStatusImage(context, mStatus, null, State.EXPIRED, R.color.bg_gray);
+ textColor = context.getResources().getColor(R.color.key_flag_gray);
+ } else if (item.mIsExpired) {
+ KeyFormattingUtils.setStatusImage(context, mStatus, null, State.EXPIRED, R.color.key_flag_gray);
mStatus.setVisibility(View.VISIBLE);
mSlinger.setVisibility(View.GONE);
- mMainUserId.setTextColor(context.getResources().getColor(R.color.bg_gray));
- mMainUserIdRest.setTextColor(context.getResources().getColor(R.color.bg_gray));
- } else if (isSecret) {
+ textColor = context.getResources().getColor(R.color.key_flag_gray);
+ } else if (item.mIsSecret) {
mStatus.setVisibility(View.GONE);
if (mSlingerButton.hasOnClickListeners()) {
+ mSlingerButton.setColorFilter(
+ FormattingUtils.getColorFromAttr(context, R.attr.colorTertiaryText),
+ PorterDuff.Mode.SRC_IN);
mSlinger.setVisibility(View.VISIBLE);
} else {
mSlinger.setVisibility(View.GONE);
}
- mMainUserId.setTextColor(context.getResources().getColor(R.color.black));
- mMainUserIdRest.setTextColor(context.getResources().getColor(R.color.black));
+ textColor = FormattingUtils.getColorFromAttr(context, R.attr.colorText);
} else {
// this is a public key - show if it's verified
- if (isVerified) {
+ if (item.mIsVerified) {
KeyFormattingUtils.setStatusImage(context, mStatus, State.VERIFIED);
mStatus.setVisibility(View.VISIBLE);
} else {
@@ -162,19 +180,26 @@ public class KeyAdapter extends CursorAdapter {
mStatus.setVisibility(View.VISIBLE);
}
mSlinger.setVisibility(View.GONE);
- mMainUserId.setTextColor(context.getResources().getColor(R.color.black));
- mMainUserIdRest.setTextColor(context.getResources().getColor(R.color.black));
+ textColor = FormattingUtils.getColorFromAttr(context, R.attr.colorText);
}
- if (hasDuplicate) {
+ if (!enabled) {
+ textColor = context.getResources().getColor(R.color.key_flag_gray);
+ }
+
+ mMainUserId.setTextColor(textColor);
+ mMainUserIdRest.setTextColor(textColor);
+
+ if (item.mHasDuplicate) {
String dateTime = DateUtils.formatDateTime(context,
- cursor.getLong(INDEX_CREATION) * 1000,
+ item.mCreation.getTime(),
DateUtils.FORMAT_SHOW_DATE
| DateUtils.FORMAT_SHOW_TIME
| DateUtils.FORMAT_SHOW_YEAR
| DateUtils.FORMAT_ABBREV_MONTH);
mCreationDate.setText(context.getString(R.string.label_key_created,
- dateTime));
+ dateTime));
+ mCreationDate.setTextColor(textColor);
mCreationDate.setVisibility(View.VISIBLE);
} else {
mCreationDate.setVisibility(View.GONE);
@@ -184,6 +209,24 @@ public class KeyAdapter extends CursorAdapter {
}
+ /** Shows the "you have no keys yet" dummy view, and sets an OnClickListener. */
+ public void setDummy(OnClickListener listener) {
+
+ // just reset everything to display the dummy layout
+ mLayoutDummy.setVisibility(View.VISIBLE);
+ mLayoutData.setVisibility(View.GONE);
+ mSlinger.setVisibility(View.GONE);
+ mStatus.setVisibility(View.GONE);
+ mView.setClickable(false);
+
+ mLayoutDummy.setOnClickListener(listener);
+
+ }
+
+ }
+
+ public boolean isEnabled(Cursor cursor) {
+ return true;
}
@Override
@@ -191,16 +234,17 @@ public class KeyAdapter extends CursorAdapter {
View view = mInflater.inflate(R.layout.key_list_item, parent, false);
KeyItemViewHolder holder = new KeyItemViewHolder(view);
view.setTag(holder);
- holder.mSlingerButton.setColorFilter(context.getResources().getColor(R.color.tertiary_text_light),
- PorterDuff.Mode.SRC_IN);
return view;
}
@Override
public void bindView(View view, Context context, Cursor cursor) {
Highlighter highlighter = new Highlighter(context, mQuery);
+ KeyItem item = new KeyItem(cursor);
+ boolean isEnabled = isEnabled(cursor);
+
KeyItemViewHolder h = (KeyItemViewHolder) view.getTag();
- h.setData(context, cursor, highlighter);
+ h.setData(context, item, highlighter, isEnabled);
}
public boolean isSecretAvailable(int id) {
@@ -230,14 +274,16 @@ public class KeyAdapter extends CursorAdapter {
@Override
public long getItemId(int position) {
+ Cursor cursor = getCursor();
// prevent a crash on rapid cursor changes
- if (getCursor().isClosed()) {
+ if (cursor != null && getCursor().isClosed()) {
return 0L;
}
return super.getItemId(position);
}
- public static class KeyItem {
+ // must be serializable for TokenCompleTextView state
+ public static class KeyItem implements Serializable {
public final String mUserIdFull;
public final KeyRing.UserId mUserId;
@@ -245,6 +291,7 @@ public class KeyAdapter extends CursorAdapter {
public final boolean mHasDuplicate;
public final Date mCreation;
public final String mFingerprint;
+ public final boolean mIsSecret, mIsRevoked, mIsExpired, mIsVerified;
private KeyItem(Cursor cursor) {
String userId = cursor.getString(INDEX_USER_ID);
@@ -255,6 +302,10 @@ public class KeyAdapter extends CursorAdapter {
mCreation = new Date(cursor.getLong(INDEX_CREATION) * 1000);
mFingerprint = KeyFormattingUtils.convertFingerprintToHex(
cursor.getBlob(INDEX_FINGERPRINT));
+ mIsSecret = cursor.getInt(INDEX_HAS_ANY_SECRET) != 0;
+ mIsRevoked = cursor.getInt(INDEX_IS_REVOKED) > 0;
+ mIsExpired = cursor.getInt(INDEX_IS_EXPIRED) > 0;
+ mIsVerified = cursor.getInt(INDEX_VERIFIED) > 0;
}
public KeyItem(CanonicalizedPublicKeyRing ring) {
@@ -267,6 +318,12 @@ public class KeyAdapter extends CursorAdapter {
mCreation = key.getCreationTime();
mFingerprint = KeyFormattingUtils.convertFingerprintToHex(
ring.getFingerprint());
+ mIsRevoked = key.isRevoked();
+ mIsExpired = key.isExpired();
+
+ // these two are actually "don't know"s
+ mIsSecret = false;
+ mIsVerified = false;
}
public String getReadableName() {
@@ -279,4 +336,11 @@ public class KeyAdapter extends CursorAdapter {
}
+ public static String[] getProjectionWith(String[] projection) {
+ List<String> list = new ArrayList<>();
+ list.addAll(Arrays.asList(PROJECTION));
+ list.addAll(Arrays.asList(projection));
+ return list.toArray(new String[list.size()]);
+ }
+
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/KeySelectableAdapter.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/KeySelectableAdapter.java
new file mode 100644
index 000000000..471a20411
--- /dev/null
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/KeySelectableAdapter.java
@@ -0,0 +1,87 @@
+package org.sufficientlysecure.keychain.ui.adapter;
+
+
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
+import android.content.Context;
+import android.database.Cursor;
+import android.support.v7.internal.widget.AdapterViewCompat;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.AdapterView;
+import android.widget.AdapterView.OnItemClickListener;
+import android.widget.CheckBox;
+
+import org.sufficientlysecure.keychain.Constants;
+import org.sufficientlysecure.keychain.R;
+import org.sufficientlysecure.keychain.util.Log;
+
+
+public class KeySelectableAdapter extends KeyAdapter implements OnItemClickListener {
+
+ HashSet<Long> mSelectedItems = new HashSet<>();
+
+ public KeySelectableAdapter(Context context, Cursor c, int flags, Set<Long> initialChecked) {
+ super(context, c, flags);
+ if (initialChecked != null) {
+ mSelectedItems.addAll(initialChecked);
+ }
+ }
+
+ public static class KeySelectableItemViewHolder extends KeyItemViewHolder {
+
+ public CheckBox mCheckbox;
+
+ public KeySelectableItemViewHolder(View view) {
+ super(view);
+ mCheckbox = (CheckBox) view.findViewById(R.id.selected);
+ }
+
+ public void setCheckedState(boolean checked) {
+ mCheckbox.setChecked(checked);
+ }
+
+ }
+
+ @Override
+ public View newView(Context context, Cursor cursor, ViewGroup parent) {
+ View view = mInflater.inflate(R.layout.key_list_selectable_item, parent, false);
+ KeySelectableItemViewHolder holder = new KeySelectableItemViewHolder(view);
+ view.setTag(holder);
+ return view;
+ }
+
+ @Override
+ public void bindView(View view, Context context, Cursor cursor) {
+ super.bindView(view, context, cursor);
+
+ KeySelectableItemViewHolder h = (KeySelectableItemViewHolder) view.getTag();
+ h.setCheckedState(mSelectedItems.contains(h.mDisplayedItem.mKeyId));
+
+ }
+
+ public void setCheckedStates(Set<Long> checked) {
+ mSelectedItems.clear();
+ mSelectedItems.addAll(checked);
+ notifyDataSetChanged();
+ }
+
+ public Set<Long> getSelectedMasterKeyIds() {
+ return Collections.unmodifiableSet(mSelectedItems);
+ }
+
+ @Override
+ public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
+ Log.d(Constants.TAG, "clicked id: " + id);
+ long masterKeyId = getMasterKeyId(position);
+ if (mSelectedItems.contains(masterKeyId)) {
+ mSelectedItems.remove(masterKeyId);
+ } else {
+ mSelectedItems.add(masterKeyId);
+ }
+ notifyDataSetChanged();
+ }
+
+}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/MultiUserIdsAdapter.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/MultiUserIdsAdapter.java
index 5218273a0..b91abf076 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/MultiUserIdsAdapter.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/MultiUserIdsAdapter.java
@@ -40,20 +40,19 @@ public class MultiUserIdsAdapter extends CursorAdapter {
private LayoutInflater mInflater;
private final ArrayList<Boolean> mCheckStates;
- public MultiUserIdsAdapter(Context context, Cursor c, int flags) {
+ public MultiUserIdsAdapter(Context context, Cursor c, int flags, ArrayList<Boolean> preselectStates) {
super(context, c, flags);
mInflater = LayoutInflater.from(context);
- mCheckStates = new ArrayList<>();
+ mCheckStates = preselectStates == null ? new ArrayList<Boolean>() : preselectStates;
}
@Override
public Cursor swapCursor(Cursor newCursor) {
- mCheckStates.clear();
if (newCursor != null) {
int count = newCursor.getCount();
mCheckStates.ensureCapacity(count);
- // initialize to true (use case knowledge: we usually want to sign all uids)
- for (int i = 0; i < count; i++) {
+ // initialize new fields to true (use case knowledge: we usually want to sign all uids)
+ for (int i = mCheckStates.size(); i < count; i++) {
mCheckStates.add(true);
}
}
@@ -151,6 +150,10 @@ public class MultiUserIdsAdapter extends CursorAdapter {
}
+ public ArrayList<Boolean> getCheckStates() {
+ return mCheckStates;
+ }
+
public ArrayList<CertifyAction> getSelectedCertifyActions() {
LongSparseArray<CertifyAction> actions = new LongSparseArray<>();
for (int i = 0; i < mCheckStates.size(); i++) {
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/SelectKeyCursorAdapter.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/SelectKeyCursorAdapter.java
index 6bbf41a88..f01f25200 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/SelectKeyCursorAdapter.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/SelectKeyCursorAdapter.java
@@ -149,11 +149,11 @@ abstract public class SelectKeyCursorAdapter extends CursorAdapter {
boolean enabled;
if (cursor.getInt(mIndexIsRevoked) != 0) {
h.statusIcon.setVisibility(View.VISIBLE);
- KeyFormattingUtils.setStatusImage(mContext, h.statusIcon, null, State.REVOKED, R.color.bg_gray);
+ KeyFormattingUtils.setStatusImage(mContext, h.statusIcon, null, State.REVOKED, R.color.key_flag_gray);
enabled = false;
} else if (cursor.getInt(mIndexIsExpiry) != 0) {
h.statusIcon.setVisibility(View.VISIBLE);
- KeyFormattingUtils.setStatusImage(mContext, h.statusIcon, null, State.EXPIRED, R.color.bg_gray);
+ KeyFormattingUtils.setStatusImage(mContext, h.statusIcon, null, State.EXPIRED, R.color.key_flag_gray);
enabled = false;
} else {
h.statusIcon.setVisibility(View.GONE);
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/SubkeysAdapter.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/SubkeysAdapter.java
index 096dea51f..24f5f04a1 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/SubkeysAdapter.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/SubkeysAdapter.java
@@ -116,6 +116,21 @@ public class SubkeysAdapter extends CursorAdapter {
}
}
+ public int getAlgorithm(int position) {
+ mCursor.moveToPosition(position);
+ return mCursor.getInt(INDEX_ALGORITHM);
+ }
+
+ public int getKeySize(int position) {
+ mCursor.moveToPosition(position);
+ return mCursor.getInt(INDEX_KEY_SIZE);
+ }
+
+ public SecretKeyType getSecretKeyType(int position) {
+ mCursor.moveToPosition(position);
+ return SecretKeyType.fromNum(mCursor.getInt(INDEX_HAS_SECRET));
+ }
+
@Override
public Cursor swapCursor(Cursor newCursor) {
hasAnySecret = false;
@@ -164,13 +179,23 @@ public class SubkeysAdapter extends CursorAdapter {
? mSaveKeyringParcel.getSubkeyChange(keyId)
: null;
- if (change != null && change.mDummyStrip) {
- algorithmStr.append(", ");
- final SpannableString boldStripped = new SpannableString(
- context.getString(R.string.key_stripped)
- );
- boldStripped.setSpan(new StyleSpan(Typeface.BOLD), 0, boldStripped.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
- algorithmStr.append(boldStripped);
+ if (change != null && (change.mDummyStrip || change.mMoveKeyToCard)) {
+ if (change.mDummyStrip) {
+ algorithmStr.append(", ");
+ final SpannableString boldStripped = new SpannableString(
+ context.getString(R.string.key_stripped)
+ );
+ boldStripped.setSpan(new StyleSpan(Typeface.BOLD), 0, boldStripped.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
+ algorithmStr.append(boldStripped);
+ }
+ if (change.mMoveKeyToCard) {
+ algorithmStr.append(", ");
+ final SpannableString boldDivert = new SpannableString(
+ context.getString(R.string.key_divert)
+ );
+ boldDivert.setSpan(new StyleSpan(Typeface.BOLD), 0, boldDivert.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
+ algorithmStr.append(boldDivert);
+ }
} else {
switch (SecretKeyType.fromNum(cursor.getInt(INDEX_HAS_SECRET))) {
case GNU_DUMMY:
@@ -259,27 +284,27 @@ public class SubkeysAdapter extends CursorAdapter {
vStatus.setVisibility(View.VISIBLE);
vCertifyIcon.setColorFilter(
- mContext.getResources().getColor(R.color.bg_gray),
+ mContext.getResources().getColor(R.color.key_flag_gray),
PorterDuff.Mode.SRC_IN);
vSignIcon.setColorFilter(
- mContext.getResources().getColor(R.color.bg_gray),
+ mContext.getResources().getColor(R.color.key_flag_gray),
PorterDuff.Mode.SRC_IN);
vEncryptIcon.setColorFilter(
- mContext.getResources().getColor(R.color.bg_gray),
+ mContext.getResources().getColor(R.color.key_flag_gray),
PorterDuff.Mode.SRC_IN);
vAuthenticateIcon.setColorFilter(
- mContext.getResources().getColor(R.color.bg_gray),
+ mContext.getResources().getColor(R.color.key_flag_gray),
PorterDuff.Mode.SRC_IN);
if (isRevoked) {
vStatus.setImageResource(R.drawable.status_signature_revoked_cutout_24dp);
vStatus.setColorFilter(
- mContext.getResources().getColor(R.color.bg_gray),
+ mContext.getResources().getColor(R.color.key_flag_gray),
PorterDuff.Mode.SRC_IN);
} else if (isExpired) {
vStatus.setImageResource(R.drawable.status_signature_expired_cutout_24dp);
vStatus.setColorFilter(
- mContext.getResources().getColor(R.color.bg_gray),
+ mContext.getResources().getColor(R.color.key_flag_gray),
PorterDuff.Mode.SRC_IN);
}
} else {
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 c68c078ad..0f4312dad 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
@@ -128,7 +128,7 @@ public class UserIdsAdapter extends UserAttributesAdapter {
if (isRevoked) {
// set revocation icon (can this even be primary?)
- KeyFormattingUtils.setStatusImage(mContext, vVerified, null, State.REVOKED, R.color.bg_gray);
+ KeyFormattingUtils.setStatusImage(mContext, vVerified, null, State.REVOKED, R.color.key_flag_gray);
// disable revoked user ids
vName.setEnabled(false);