Show revoked status in key list

This commit is contained in:
Dominik Schürmann 2014-02-04 15:01:50 +01:00
parent d75ea3f9e5
commit c434c426e7
6 changed files with 68 additions and 32 deletions

View File

@ -359,7 +359,9 @@ public class KeychainProvider extends ContentProvider {
projectionMap.put(KeyRingsColumns.MASTER_KEY_ID, Tables.KEY_RINGS + "." + KeyRingsColumns.MASTER_KEY_ID); projectionMap.put(KeyRingsColumns.MASTER_KEY_ID, Tables.KEY_RINGS + "." + KeyRingsColumns.MASTER_KEY_ID);
// TODO: deprecated master key id // TODO: deprecated master key id
//projectionMap.put(KeyRingsColumns.MASTER_KEY_ID, Tables.KEYS + "." + KeysColumns.KEY_ID); //projectionMap.put(KeyRingsColumns.MASTER_KEY_ID, Tables.KEYS + "." + KeysColumns.KEY_ID);
projectionMap.put(KeysColumns.FINGERPRINT, Tables.KEYS + "." + KeysColumns.FINGERPRINT); projectionMap.put(KeysColumns.FINGERPRINT, Tables.KEYS + "." + KeysColumns.FINGERPRINT);
projectionMap.put(KeysColumns.IS_REVOKED, Tables.KEYS + "." + KeysColumns.IS_REVOKED);
projectionMap.put(UserIdsColumns.USER_ID, Tables.USER_IDS + "." + UserIdsColumns.USER_ID); projectionMap.put(UserIdsColumns.USER_ID, Tables.USER_IDS + "." + UserIdsColumns.USER_ID);

View File

@ -30,6 +30,7 @@ import org.sufficientlysecure.keychain.ui.dialog.DeleteKeyDialogFragment;
import se.emilsjolander.stickylistheaders.ApiLevelTooLowException; import se.emilsjolander.stickylistheaders.ApiLevelTooLowException;
import se.emilsjolander.stickylistheaders.StickyListHeadersListView; import se.emilsjolander.stickylistheaders.StickyListHeadersListView;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
import android.content.Intent; import android.content.Intent;
import android.database.Cursor; import android.database.Cursor;
@ -63,7 +64,7 @@ public class KeyListPublicFragment extends Fragment implements AdapterView.OnIte
private KeyListPublicAdapter mAdapter; private KeyListPublicAdapter mAdapter;
private StickyListHeadersListView mStickyList; private StickyListHeadersListView mStickyList;
// empty layout // empty list layout
private BootstrapButton mButtonEmptyCreate; private BootstrapButton mButtonEmptyCreate;
private BootstrapButton mButtonEmptyImport; private BootstrapButton mButtonEmptyImport;
@ -92,9 +93,9 @@ public class KeyListPublicFragment extends Fragment implements AdapterView.OnIte
@Override @Override
public void onClick(View v) { public void onClick(View v) {
Intent intentImportFromFile = new Intent(getActivity(), ImportKeysActivity.class); Intent intent = new Intent(getActivity(), ImportKeysActivity.class);
intentImportFromFile.setAction(ImportKeysActivity.ACTION_IMPORT_KEY_FROM_FILE); intent.setAction(ImportKeysActivity.ACTION_IMPORT_KEY_FROM_FILE);
startActivityForResult(intentImportFromFile, 0); startActivityForResult(intent, 0);
} }
}); });
@ -109,7 +110,6 @@ public class KeyListPublicFragment extends Fragment implements AdapterView.OnIte
public void onActivityCreated(Bundle savedInstanceState) { public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState); super.onActivityCreated(savedInstanceState);
// mKeyListPublicActivity = (KeyListPublicActivity) getActivity();
mStickyList = (StickyListHeadersListView) getActivity().findViewById(R.id.list); mStickyList = (StickyListHeadersListView) getActivity().findViewById(R.id.list);
mStickyList.setOnItemClickListener(this); mStickyList.setOnItemClickListener(this);
@ -159,16 +159,16 @@ public class KeyListPublicFragment extends Fragment implements AdapterView.OnIte
} }
switch (item.getItemId()) { switch (item.getItemId()) {
case R.id.menu_key_list_public_multi_encrypt: { case R.id.menu_key_list_public_multi_encrypt: {
encrypt(ids); encrypt(ids);
break; break;
} }
case R.id.menu_key_list_public_multi_delete: { case R.id.menu_key_list_public_multi_delete: {
showDeleteKeyDialog(ids); showDeleteKeyDialog(ids);
break; break;
} }
} }
return false; return false;
} }
@ -181,7 +181,7 @@ public class KeyListPublicFragment extends Fragment implements AdapterView.OnIte
@Override @Override
public void onItemCheckedStateChanged(ActionMode mode, int position, long id, public void onItemCheckedStateChanged(ActionMode mode, int position, long id,
boolean checked) { boolean checked) {
if (checked) { if (checked) {
count++; count++;
mAdapter.setNewSelection(position, checked); mAdapter.setNewSelection(position, checked);
@ -212,8 +212,12 @@ public class KeyListPublicFragment extends Fragment implements AdapterView.OnIte
} }
// These are the rows that we will retrieve. // These are the rows that we will retrieve.
static final String[] PROJECTION = new String[] { KeyRings._ID, KeyRings.MASTER_KEY_ID, static final String[] PROJECTION = new String[]{
UserIds.USER_ID }; KeychainContract.KeyRings._ID,
KeychainContract.KeyRings.MASTER_KEY_ID,
KeychainContract.UserIds.USER_ID,
KeychainContract.Keys.IS_REVOKED
};
static final int USER_ID_INDEX = 2; static final int USER_ID_INDEX = 2;
@ -286,7 +290,7 @@ public class KeyListPublicFragment extends Fragment implements AdapterView.OnIte
/** /**
* Show dialog to delete key * Show dialog to delete key
* *
* @param keyRingRowIds * @param keyRingRowIds
*/ */
public void showDeleteKeyDialog(long[] keyRingRowIds) { public void showDeleteKeyDialog(long[] keyRingRowIds) {

View File

@ -129,7 +129,7 @@ public class ImportKeysAdapter extends ArrayAdapter<ImportKeysListEntry> {
algorithm.setText("" + entry.bitStrength + "/" + entry.algorithm); algorithm.setText("" + entry.bitStrength + "/" + entry.algorithm);
if (entry.revoked) { if (entry.revoked) {
status.setText("revoked"); status.setText(R.string.revoked);
} else { } else {
status.setVisibility(View.GONE); status.setVisibility(View.GONE);
} }

View File

@ -23,10 +23,12 @@ import java.util.Set;
import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.pgp.PgpKeyHelper; import org.sufficientlysecure.keychain.pgp.PgpKeyHelper;
import org.sufficientlysecure.keychain.provider.KeychainContract;
import org.sufficientlysecure.keychain.provider.KeychainContract.UserIds; import org.sufficientlysecure.keychain.provider.KeychainContract.UserIds;
import org.sufficientlysecure.keychain.util.Log; import org.sufficientlysecure.keychain.util.Log;
import se.emilsjolander.stickylistheaders.StickyListHeadersAdapter; import se.emilsjolander.stickylistheaders.StickyListHeadersAdapter;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
import android.content.Context; import android.content.Context;
import android.database.Cursor; import android.database.Cursor;
@ -44,6 +46,7 @@ public class KeyListPublicAdapter extends CursorAdapter implements StickyListHea
private LayoutInflater mInflater; private LayoutInflater mInflater;
private int mSectionColumnIndex; private int mSectionColumnIndex;
private int mIndexUserId; private int mIndexUserId;
private int mIndexIsRevoked;
@SuppressLint("UseSparseArrays") @SuppressLint("UseSparseArrays")
private HashMap<Integer, Boolean> mSelection = new HashMap<Integer, Boolean>(); private HashMap<Integer, Boolean> mSelection = new HashMap<Integer, Boolean>();
@ -66,27 +69,31 @@ public class KeyListPublicAdapter extends CursorAdapter implements StickyListHea
/** /**
* Get column indexes for performance reasons just once in constructor and swapCursor. For a * Get column indexes for performance reasons just once in constructor and swapCursor. For a
* performance comparison see http://stackoverflow.com/a/17999582 * performance comparison see http://stackoverflow.com/a/17999582
* *
* @param cursor * @param cursor
*/ */
private void initIndex(Cursor cursor) { private void initIndex(Cursor cursor) {
if (cursor != null) { if (cursor != null) {
mIndexUserId = cursor.getColumnIndexOrThrow(UserIds.USER_ID); mIndexUserId = cursor.getColumnIndexOrThrow(KeychainContract.UserIds.USER_ID);
mIndexIsRevoked = cursor.getColumnIndexOrThrow(KeychainContract.Keys.IS_REVOKED);
} }
} }
/** /**
* Bind cursor data to the item list view * Bind cursor data to the item list view
* * <p/>
* NOTE: CursorAdapter already implements the ViewHolder pattern in its getView() method. Thus * NOTE: CursorAdapter already implements the ViewHolder pattern in its getView() method. Thus
* no ViewHolder is required here. * no ViewHolder is required here.
*/ */
@Override @Override
public void bindView(View view, Context context, Cursor cursor) { public void bindView(View view, Context context, Cursor cursor) {
TextView mainUserId = (TextView) view.findViewById(R.id.mainUserId); TextView mainUserId = (TextView) view.findViewById(R.id.mainUserId);
mainUserId.setText(R.string.user_id_no_name);
TextView mainUserIdRest = (TextView) view.findViewById(R.id.mainUserIdRest); TextView mainUserIdRest = (TextView) view.findViewById(R.id.mainUserIdRest);
TextView revoked = (TextView) view.findViewById(R.id.revoked);
mainUserId.setText(R.string.user_id_no_name);
mainUserIdRest.setText(""); mainUserIdRest.setText("");
revoked.setVisibility(View.GONE);
String userId = cursor.getString(mIndexUserId); String userId = cursor.getString(mIndexUserId);
String[] userIdSplit = PgpKeyHelper.splitUserId(userId); String[] userIdSplit = PgpKeyHelper.splitUserId(userId);
@ -97,6 +104,11 @@ public class KeyListPublicAdapter extends CursorAdapter implements StickyListHea
if (userIdSplit[1] != null) { if (userIdSplit[1] != null) {
mainUserIdRest.setText(userIdSplit[1]); mainUserIdRest.setText(userIdSplit[1]);
} }
boolean isRevoked = cursor.getInt(mIndexIsRevoked) > 0;
if (isRevoked) {
revoked.setVisibility(View.VISIBLE);
}
} }
@Override @Override
@ -107,7 +119,7 @@ public class KeyListPublicAdapter extends CursorAdapter implements StickyListHea
/** /**
* Creates a new header view and binds the section headers to it. It uses the ViewHolder * Creates a new header view and binds the section headers to it. It uses the ViewHolder
* pattern. Most functionality is similar to getView() from Android's CursorAdapter. * pattern. Most functionality is similar to getView() from Android's CursorAdapter.
* * <p/>
* NOTE: The variables mDataValid and mCursor are available due to the super class * NOTE: The variables mDataValid and mCursor are available due to the super class
* CursorAdapter. * CursorAdapter.
*/ */
@ -159,8 +171,7 @@ public class KeyListPublicAdapter extends CursorAdapter implements StickyListHea
} }
// return the first character of the name as ID because this is what // return the first character of the name as ID because this is what
// headers private HashMap<Integer, Boolean> mSelection = new HashMap<Integer, // headers are based upon
// Boolean>();are based upon
String userId = mCursor.getString(mSectionColumnIndex); String userId = mCursor.getString(mSectionColumnIndex);
if (userId != null && userId.length() > 0) { if (userId != null && userId.length() > 0) {
return userId.subSequence(0, 1).charAt(0); return userId.subSequence(0, 1).charAt(0);
@ -173,7 +184,9 @@ public class KeyListPublicAdapter extends CursorAdapter implements StickyListHea
TextView text; TextView text;
} }
/** -------------------------- MULTI-SELECTION METHODS -------------- */ /**
* -------------------------- MULTI-SELECTION METHODS --------------
*/
public void setNewSelection(int position, boolean value) { public void setNewSelection(int position, boolean value) {
mSelection.put(position, value); mSelection.put(position, value);
notifyDataSetChanged(); notifyDataSetChanged();

View File

@ -1,24 +1,40 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="?android:attr/listPreferredItemHeight" android:layout_height="?android:attr/listPreferredItemHeight"
android:layout_marginRight="?android:attr/scrollbarSize" android:layout_marginRight="?android:attr/scrollbarSize"
android:orientation="vertical"
android:paddingLeft="8dp" android:paddingLeft="8dp"
android:singleLine="true" > android:singleLine="true">
<TextView <TextView
android:id="@+id/mainUserId" android:id="@+id/mainUserId"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="Main User ID" android:text="Main User ID"
android:textAppearance="?android:attr/textAppearanceMedium" /> android:textAppearance="?android:attr/textAppearanceMedium"
android:layout_alignParentTop="true"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true" />
<TextView <TextView
android:id="@+id/mainUserIdRest" android:id="@+id/mainUserIdRest"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="&lt;user@example.com>" android:text="&lt;user@example.com>"
android:textAppearance="?android:attr/textAppearanceSmall" /> android:textAppearance="?android:attr/textAppearanceSmall"
android:layout_below="@+id/mainUserId"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true" />
</LinearLayout> <TextView
android:id="@+id/revoked"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceSmall"
android:text="@string/revoked"
android:textColor="#e00"
android:layout_alignParentTop="true"
android:layout_alignParentRight="true"
android:layout_alignParentEnd="true" />
</RelativeLayout>

View File

@ -143,6 +143,7 @@
<string name="can_encrypt">can encrypt</string> <string name="can_encrypt">can encrypt</string>
<string name="can_sign">can sign</string> <string name="can_sign">can sign</string>
<string name="expired">expired</string> <string name="expired">expired</string>
<string name="revoked">revoked</string>
<plurals name="n_key_servers"> <plurals name="n_key_servers">
<item quantity="one">%d key server</item> <item quantity="one">%d key server</item>