aboutsummaryrefslogtreecommitdiffstats
path: root/OpenKeychain
diff options
context:
space:
mode:
authorDominik Schürmann <dominik@dominikschuermann.de>2015-04-13 23:33:23 +0200
committerDominik Schürmann <dominik@dominikschuermann.de>2015-04-13 23:33:23 +0200
commitf12c7b64d8b78b5927d8c5a76f9c16a0272a44c5 (patch)
treeee13ef64b968d90238647c7fab07207c2bdb9e1d /OpenKeychain
parent256d644d03f989132e9db01e15f75aaee2f76157 (diff)
parent083cd100cebbbfdca3a0df76e050b817d8711cd8 (diff)
downloadopen-keychain-f12c7b64d8b78b5927d8c5a76f9c16a0272a44c5.tar.gz
open-keychain-f12c7b64d8b78b5927d8c5a76f9c16a0272a44c5.tar.bz2
open-keychain-f12c7b64d8b78b5927d8c5a76f9c16a0272a44c5.zip
Merge pull request #1193 from adithyaphilip/auto-refresh-contacts
Immediate display of contact card, fixed contact picture display issue, hides card if no contact
Diffstat (limited to 'OpenKeychain')
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyFragment.java106
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/ContactHelper.java51
-rw-r--r--OpenKeychain/src/main/res/layout/view_key_fragment.xml1
3 files changed, 119 insertions, 39 deletions
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 c3a8d60f8..1e02ca450 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/ViewKeyFragment.java
@@ -29,6 +29,7 @@ import android.provider.ContactsContract;
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.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@@ -37,7 +38,6 @@ import android.widget.*;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.compatibility.DialogFragmentWorkaround;
-import org.sufficientlysecure.keychain.pgp.KeyRing;
import org.sufficientlysecure.keychain.provider.KeychainContract;
import org.sufficientlysecure.keychain.ui.adapter.UserIdsAdapter;
import org.sufficientlysecure.keychain.ui.dialog.UserIdInfoDialogFragment;
@@ -55,14 +55,20 @@ public class ViewKeyFragment extends LoaderFragment implements
//private ListView mLinkedSystemContact;
boolean mIsSecret = false;
- boolean mSystemContactLoaded = false;
+ CardView mSystemContactCard;
LinearLayout mSystemContactLayout;
ImageView mSystemContactPicture;
TextView mSystemContactName;
private static final int LOADER_ID_UNIFIED = 0;
private static final int LOADER_ID_USER_IDS = 1;
+ private static final int LOADER_ID_LINKED_CONTACT = 2;
+
+ private static final String LOADER_EXTRA_LINKED_CONTACT_MASTER_KEY_ID
+ = "loader_linked_contact_master_key_id";
+ private static final String LOADER_EXTRA_LINKED_CONTACT_IS_SECRET
+ = "loader_linked_contact_is_secret";
private UserIdsAdapter mUserIdsAdapter;
@@ -95,6 +101,7 @@ public class ViewKeyFragment extends LoaderFragment implements
}
});
+ mSystemContactCard = (CardView) view.findViewById(R.id.linked_system_contact_card);
mSystemContactLayout = (LinearLayout) view.findViewById(R.id.system_contact_layout);
mSystemContactName = (TextView) view.findViewById(R.id.system_contact_name);
mSystemContactPicture = (ImageView) view.findViewById(R.id.system_contact_picture);
@@ -119,53 +126,60 @@ public class ViewKeyFragment extends LoaderFragment implements
}
/**
- * Checks if a system contact exists for given masterKeyId, and if it does, sets name, picture
- * and onClickListener for the linked system contact's layout
- * In the case of a secret key, "me" contact details are loaded
+ * Hides card if no linked system contact exists. Sets name, picture
+ * and onClickListener for the linked system contact's layout.
+ * In the case of a secret key, "me" (own profile) contact details are loaded.
*
- * @param masterKeyId
+ * @param contactId
*/
- private void loadLinkedSystemContact(final long masterKeyId) {
+ private void loadLinkedSystemContact(final long contactId) {
+
final Context context = mSystemContactName.getContext();
final ContentResolver resolver = context.getContentResolver();
- long contactId;
String contactName = null;
if (mIsSecret) {//all secret keys are linked to "me" profile in contacts
- contactId = ContactHelper.getMainProfileContactId(resolver);
List<String> mainProfileNames = ContactHelper.getMainProfileContactName(context);
if (mainProfileNames != null && mainProfileNames.size() > 0) {
contactName = mainProfileNames.get(0);
}
-
} else {
- contactId = ContactHelper.findContactId(resolver, masterKeyId);
contactName = ContactHelper.getContactName(resolver, contactId);
}
if (contactName != null) {//contact name exists for given master key
+ showLinkedSystemContact();
+
mSystemContactName.setText(contactName);
Bitmap picture;
if (mIsSecret) {
picture = ContactHelper.loadMainProfilePhoto(resolver, false);
} else {
- picture = ContactHelper.loadPhotoByMasterKeyId(resolver, masterKeyId, false);
+ picture = ContactHelper.loadPhotoByContactId(resolver, contactId, false);
}
if (picture != null) mSystemContactPicture.setImageBitmap(picture);
- final long finalContactId = contactId;
mSystemContactLayout.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
- launchContactActivity(finalContactId, context);
+ launchContactActivity(contactId, context);
}
});
- mSystemContactLoaded = true;
+ } else {
+ hideLinkedSystemContact();
}
}
+ private void hideLinkedSystemContact() {
+ mSystemContactCard.setVisibility(View.GONE);
+ }
+
+ private void showLinkedSystemContact() {
+ mSystemContactCard.setVisibility(View.VISIBLE);
+ }
+
/**
* launches the default android Contacts app to view a contact with the passed
* contactId (CONTACT_ID column from ContactsContract.RawContact table which is _ID column in
@@ -195,7 +209,6 @@ public class ViewKeyFragment extends LoaderFragment implements
loadData(dataUri);
}
-
// These are the rows that we will retrieve.
static final String[] UNIFIED_PROJECTION = new String[]{
KeychainContract.KeyRings._ID,
@@ -218,6 +231,12 @@ public class ViewKeyFragment extends LoaderFragment implements
static final int INDEX_FINGERPRINT = 7;
static final int INDEX_HAS_ENCRYPT = 8;
+ private static final String[] RAWCONTACT_PROJECTION = {
+ ContactsContract.RawContacts.CONTACT_ID
+ };
+
+ private static final int INDEX_CONTACT_ID = 0;
+
private void loadData(Uri dataUri) {
mDataUri = dataUri;
@@ -241,6 +260,33 @@ public class ViewKeyFragment extends LoaderFragment implements
case LOADER_ID_USER_IDS:
return UserIdsAdapter.createLoader(getActivity(), mDataUri);
+ //we need a separate loader for linked contact to ensure refreshing on verification
+ case LOADER_ID_LINKED_CONTACT: {
+ //passed in args to explicitly specify their need
+ long masterKeyId = args.getLong(LOADER_EXTRA_LINKED_CONTACT_MASTER_KEY_ID);
+ boolean isSecret = args.getBoolean(LOADER_EXTRA_LINKED_CONTACT_IS_SECRET);
+
+ Uri baseUri;
+ if (isSecret)
+ baseUri = ContactsContract.Profile.CONTENT_RAW_CONTACTS_URI;
+ else
+ baseUri = ContactsContract.RawContacts.CONTENT_URI;
+
+ return new CursorLoader(
+ getActivity(),
+ baseUri,
+ RAWCONTACT_PROJECTION,
+ ContactsContract.RawContacts.ACCOUNT_TYPE + "=? AND " +
+ ContactsContract.RawContacts.SOURCE_ID + "=? AND " +
+ ContactsContract.RawContacts.DELETED + "=?",
+ new String[]{//"0" for "not deleted"
+ Constants.ACCOUNT_TYPE,
+ Long.toString(masterKeyId),
+ "0"
+ },
+ null);
+ }
+
default:
return null;
}
@@ -263,16 +309,26 @@ public class ViewKeyFragment extends LoaderFragment implements
mIsSecret = data.getInt(INDEX_HAS_ANY_SECRET) != 0;
- //TODO system to allow immediate refreshing of system contact on verification
- if (!mSystemContactLoaded) {//ensure we load linked system contact only once
- long masterKeyId = data.getLong(INDEX_MASTER_KEY_ID);
- loadLinkedSystemContact(masterKeyId);
- }
// 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);
+ long masterKeyId = data.getLong(INDEX_MASTER_KEY_ID);
+ // we need to load linked contact here to prevent lag introduced by loader
+ // for the linked contact
+ long contactId = ContactHelper.findContactId(
+ getActivity().getContentResolver(),
+ masterKeyId);
+ loadLinkedSystemContact(contactId);
+
+ Bundle linkedContactData = new Bundle();
+ linkedContactData.putLong(LOADER_EXTRA_LINKED_CONTACT_MASTER_KEY_ID, masterKeyId);
+ linkedContactData.putBoolean(LOADER_EXTRA_LINKED_CONTACT_IS_SECRET, mIsSecret);
+
+ // initialises loader for contact query so we can listen to any updates
+ getLoaderManager().initLoader(LOADER_ID_LINKED_CONTACT, linkedContactData, this);
+
break;
}
}
@@ -282,6 +338,14 @@ public class ViewKeyFragment extends LoaderFragment implements
break;
}
+ case LOADER_ID_LINKED_CONTACT: {
+ if (data.moveToFirst()) {// if we have a linked contact
+ long contactId = data.getLong(INDEX_CONTACT_ID);
+ loadLinkedSystemContact(contactId);
+ }
+ break;
+ }
+
}
setContentShown(true);
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/ContactHelper.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/ContactHelper.java
index c782d2507..609288bf1 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/ContactHelper.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/util/ContactHelper.java
@@ -220,15 +220,14 @@ public class ContactHelper {
*/
public static long getMainProfileContactId(ContentResolver resolver) {
Cursor profileCursor = resolver.query(ContactsContract.Profile.CONTENT_URI,
- new String[]{ ContactsContract.Profile._ID}, null, null, null);
+ new String[]{ContactsContract.Profile._ID}, null, null, null);
- if(profileCursor != null && profileCursor.getCount() != 0 && profileCursor.moveToNext()) {
+ if (profileCursor != null && profileCursor.getCount() != 0 && profileCursor.moveToNext()) {
long contactId = profileCursor.getLong(0);
profileCursor.close();
return contactId;
- }
- else {
- if(profileCursor != null) {
+ } else {
+ if (profileCursor != null) {
profileCursor.close();
}
return -1;
@@ -330,7 +329,9 @@ public class ContactHelper {
ContactsContract.RawContacts.SOURCE_ID + "=? AND " +
ContactsContract.RawContacts.DELETED + "=?",
new String[]{//"0" for "not deleted"
- Constants.ACCOUNT_TYPE, Long.toString(masterKeyId), "0"
+ Constants.ACCOUNT_TYPE,
+ Long.toString(masterKeyId),
+ "0"
}, null);
if (raw != null) {
if (raw.moveToNext()) {
@@ -385,23 +386,37 @@ public class ContactHelper {
return null;
}
try {
- long rawContactId = findRawContactId(contentResolver, masterKeyId);
- if (rawContactId == -1) {
- return null;
- }
- Uri rawContactUri = ContentUris.withAppendedId(ContactsContract.RawContacts.CONTENT_URI, rawContactId);
- Uri contactUri = ContactsContract.RawContacts.getContactLookupUri(contentResolver, rawContactUri);
- InputStream photoInputStream =
- ContactsContract.Contacts.openContactPhotoInputStream(contentResolver, contactUri, highRes);
- if (photoInputStream == null) {
- return null;
- }
- return BitmapFactory.decodeStream(photoInputStream);
+ long contactId = findContactId(contentResolver, masterKeyId);
+ return loadPhotoByContactId(contentResolver, contactId, highRes);
+
} catch (Throwable ignored) {
return null;
}
}
+ public static Bitmap loadPhotoByContactId(ContentResolver contentResolver, long contactId,
+ boolean highRes) {
+ if (contactId == -1) {
+ return null;
+ }
+ Uri contactUri = ContentUris.withAppendedId(ContactsContract.Contacts.CONTENT_URI, contactId);
+ // older android versions (tested on API level 15) fail on lookupuris being passed to
+ // openContactPhotoInputStream
+ // http://stackoverflow.com/a/21214524/3000919
+ // Uri lookupUri = ContactsContract.Contacts.getLookupUri(contentResolver, contactUri);
+ // Also, we don't need a permanent shortcut to the contact since we load it afresh each time
+
+ InputStream photoInputStream = ContactsContract.Contacts.openContactPhotoInputStream(
+ contentResolver,
+ contactUri,
+ highRes);
+
+ if (photoInputStream == null) {
+ return null;
+ }
+ return BitmapFactory.decodeStream(photoInputStream);
+ }
+
public static final String[] KEYS_TO_CONTACT_PROJECTION = new String[]{
KeychainContract.KeyRings.MASTER_KEY_ID,
KeychainContract.KeyRings.USER_ID,
diff --git a/OpenKeychain/src/main/res/layout/view_key_fragment.xml b/OpenKeychain/src/main/res/layout/view_key_fragment.xml
index 454d5f9c7..a71eb5880 100644
--- a/OpenKeychain/src/main/res/layout/view_key_fragment.xml
+++ b/OpenKeychain/src/main/res/layout/view_key_fragment.xml
@@ -46,6 +46,7 @@
android:layout_gravity="center"
android:layout_width="match_parent"
android:layout_height="wrap_content"
+ android:visibility="gone"
card_view:cardBackgroundColor="@android:color/white"
card_view:cardElevation="2dp"
card_view:cardUseCompatPadding="true"