diff --git a/app/src/main/java/eu/faircode/email/ActivityView.java b/app/src/main/java/eu/faircode/email/ActivityView.java index aa18921dcd..b334013e9b 100644 --- a/app/src/main/java/eu/faircode/email/ActivityView.java +++ b/app/src/main/java/eu/faircode/email/ActivityView.java @@ -1040,7 +1040,6 @@ public class ActivityView extends ActivityBilling implements FragmentManager.OnB Bundle args = new Bundle(); args.putLong("account", intent.getLongExtra("account", -1)); args.putLong("folder", intent.getLongExtra("folder", -1)); - args.putBoolean("outgoing", intent.getBooleanExtra("outgoing", false)); FragmentMessages fragment = new FragmentMessages(); fragment.setArguments(args); diff --git a/app/src/main/java/eu/faircode/email/AdapterFolder.java b/app/src/main/java/eu/faircode/email/AdapterFolder.java index beef9f2612..a9962d5bb2 100644 --- a/app/src/main/java/eu/faircode/email/AdapterFolder.java +++ b/app/src/main/java/eu/faircode/email/AdapterFolder.java @@ -214,8 +214,7 @@ public class AdapterFolder extends RecyclerView.Adapter 0) aargs.putString("from", message.from[0].toString()); - new SimpleTask() { + new SimpleTask() { @Override protected void onPreExecute(Bundle args) { ivAvatar.setTag(message.id); ivAvatar.setVisibility(View.INVISIBLE); + tvFrom.setTag(message.id); } @Override - protected Drawable onExecute(Context context, Bundle args) { + protected ContactInfo onExecute(Context context, Bundle args) { String uri = args.getString("uri"); - if (avatars && uri != null) + + ContactInfo info = new ContactInfo(); + ContentResolver resolver = context.getContentResolver(); + + if (contacts && avatars && uri != null) try { - ContentResolver resolver = context.getContentResolver(); InputStream is = ContactsContract.Contacts.openContactPhotoInputStream(resolver, Uri.parse(uri)); if (is != null) - return Drawable.createFromStream(is, "avatar"); + info.avatar = Drawable.createFromStream(is, "avatar"); } catch (SecurityException ex) { Log.e(ex); } String from = args.getString("from"); - if (identicons && from != null) - return new BitmapDrawable( + if (info.avatar == null && identicons && from != null) + info.avatar = new BitmapDrawable( context.getResources(), Identicon.generate(from, dp24, 5, "light".equals(theme))); - return null; + if (contacts && uri != null) { + Cursor cursor = null; + try { + cursor = resolver.query( + Uri.parse(uri), + new String[]{ContactsContract.Contacts.DISPLAY_NAME}, + null, null, null); + if (cursor != null && cursor.moveToNext()) + info.displayName = cursor.getString(0); + } finally { + if (cursor != null) + cursor.close(); + } + } + + return info; } @Override - protected void onExecuted(Bundle args, Drawable avatar) { - if ((long) ivAvatar.getTag() == args.getLong("id")) { - if (avatar == null) + protected void onExecuted(Bundle args, ContactInfo info) { + long id = args.getLong("id"); + + if ((long) ivAvatar.getTag() == id) { + if (info.avatar == null) ivAvatar.setImageResource(R.drawable.baseline_person_24); else - ivAvatar.setImageDrawable(avatar); + ivAvatar.setImageDrawable(info.avatar); ivAvatar.setVisibility(View.VISIBLE); } else Log.i("Skipping avatar"); + + if ((long) tvFrom.getTag() == id) { + if (info.displayName != null) { + Log.i("Using contact name=" + info.displayName); + tvFrom.setText(info.displayName); + } + } } @Override @@ -2003,12 +2032,11 @@ public class AdapterMessage extends RecyclerView.Adapter emailContactInfo = new HashMap<>(); - private static final long MAX_CACHED_CONTACTINFO_AGE = 20 * 60 * 1000L; // milliseconds + private static final Map emailLookupUri = new HashMap<>(); static String generateMessageId() { StringBuilder sb = new StringBuilder(); @@ -212,88 +210,58 @@ public class EntityMessage implements Serializable { return new File(dir, Long.toString(id)); } - private class ContactInfo { - Uri lookupUri; - String displayName; - long time; + static String getLookupUri(Context context, Address[] froms) { + if (froms == null) + return null; - ContactInfo(Uri lookupUri, String displayName) { - this.lookupUri = lookupUri; - this.displayName = displayName; - this.time = new Date().getTime(); - } - - boolean isValid() { - long age = new Date().getTime() - this.time; - return age < MAX_CACHED_CONTACTINFO_AGE; - } - } - - boolean setContactInfo(Context context) { if (ContextCompat.checkSelfPermission(context, Manifest.permission.READ_CONTACTS) - == PackageManager.PERMISSION_GRANTED) { - this.avatar = null; - - try { - if (this.from != null) - for (Address from : this.from) { - InternetAddress address = ((InternetAddress) from); - String email = address.getAddress(); - - synchronized (emailContactInfo) { - ContactInfo info = emailContactInfo.get(email); - if (info != null && info.isValid()) { - this.avatar = info.lookupUri.toString(); - if (!TextUtils.isEmpty(info.displayName)) - address.setPersonal(info.displayName); - return true; - } - } - + != PackageManager.PERMISSION_GRANTED) + return null; - Cursor cursor = null; - try { - ContentResolver resolver = context.getContentResolver(); - cursor = resolver.query(ContactsContract.CommonDataKinds.Email.CONTENT_URI, - new String[]{ - ContactsContract.CommonDataKinds.Photo.CONTACT_ID, - ContactsContract.Contacts.LOOKUP_KEY, - ContactsContract.Contacts.DISPLAY_NAME - }, - ContactsContract.CommonDataKinds.Email.ADDRESS + " = ?", - new String[]{email}, null); - if (cursor != null && cursor.moveToNext()) { - int colContactId = cursor.getColumnIndex(ContactsContract.CommonDataKinds.Photo.CONTACT_ID); - int colLookupKey = cursor.getColumnIndex(ContactsContract.Contacts.LOOKUP_KEY); - int colDisplayName = cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME); - - long contactId = cursor.getLong(colContactId); - String lookupKey = cursor.getString(colLookupKey); - String displayName = cursor.getString(colDisplayName); - Uri lookupUri = ContactsContract.Contacts.getLookupUri(contactId, lookupKey); - - this.avatar = lookupUri.toString(); - - if (!TextUtils.isEmpty(displayName)) - address.setPersonal(displayName); - - synchronized (emailContactInfo) { - emailContactInfo.put(email, new ContactInfo(lookupUri, displayName)); - } - - return true; - } - } finally { - if (cursor != null) - cursor.close(); + try { + for (Address from : froms) { + String email = ((InternetAddress) from).getAddress(); + + synchronized (emailLookupUri) { + Uri lookupUri = emailLookupUri.get(email); + if (lookupUri != null) + return lookupUri.toString(); + } + + Cursor cursor = null; + try { + ContentResolver resolver = context.getContentResolver(); + cursor = resolver.query(ContactsContract.CommonDataKinds.Email.CONTENT_URI, + new String[]{ + ContactsContract.CommonDataKinds.Photo.CONTACT_ID, + ContactsContract.Contacts.LOOKUP_KEY + }, + ContactsContract.CommonDataKinds.Email.ADDRESS + " = ?", + new String[]{email}, null); + if (cursor != null && cursor.moveToNext()) { + int colContactId = cursor.getColumnIndex(ContactsContract.CommonDataKinds.Photo.CONTACT_ID); + int colLookupKey = cursor.getColumnIndex(ContactsContract.Contacts.LOOKUP_KEY); + + long contactId = cursor.getLong(colContactId); + String lookupKey = cursor.getString(colLookupKey); + Uri lookupUri = ContactsContract.Contacts.getLookupUri(contactId, lookupKey); + + synchronized (emailLookupUri) { + emailLookupUri.put(email, lookupUri); } + + return lookupUri.toString(); } - } catch (Throwable ex) { - Log.e(ex); + } finally { + if (cursor != null) + cursor.close(); + } } + } catch (Throwable ex) { + Log.e(ex); } - return false; + return null; } static void snooze(Context context, long id, Long wakeup) { diff --git a/app/src/main/java/eu/faircode/email/EntityRule.java b/app/src/main/java/eu/faircode/email/EntityRule.java index fcc660691e..784a32ac49 100644 --- a/app/src/main/java/eu/faircode/email/EntityRule.java +++ b/app/src/main/java/eu/faircode/email/EntityRule.java @@ -214,7 +214,7 @@ public class EntityRule { reply.subject = context.getString(R.string.title_subject_reply, message.subject == null ? "" : message.subject); reply.sender = MessageHelper.getSortKey(reply.from); reply.received = new Date().getTime(); - reply.setContactInfo(context); + reply.avatar = EntityMessage.getLookupUri(context, reply.from); reply.id = db.message().insertMessage(reply); reply.write(context, body); db.message().setMessageContent(reply.id, true, HtmlHelper.getPreview(body)); diff --git a/app/src/main/java/eu/faircode/email/FragmentCompose.java b/app/src/main/java/eu/faircode/email/FragmentCompose.java index 084300eff5..c52f59eb2e 100644 --- a/app/src/main/java/eu/faircode/email/FragmentCompose.java +++ b/app/src/main/java/eu/faircode/email/FragmentCompose.java @@ -1551,7 +1551,7 @@ public class FragmentCompose extends FragmentBase { result.draft.sender = MessageHelper.getSortKey(result.draft.from); result.draft.received = new Date().getTime(); - result.draft.setContactInfo(context); + result.draft.avatar = EntityMessage.getLookupUri(context, result.draft.from); result.draft.id = db.message().insertMessage(result.draft); result.draft.write(context, body == null ? "" : body); diff --git a/app/src/main/java/eu/faircode/email/FragmentMessages.java b/app/src/main/java/eu/faircode/email/FragmentMessages.java index 69d1c1518f..808315f704 100644 --- a/app/src/main/java/eu/faircode/email/FragmentMessages.java +++ b/app/src/main/java/eu/faircode/email/FragmentMessages.java @@ -101,7 +101,6 @@ public class FragmentMessages extends FragmentBase { private long account; private long folder; - private boolean outgoing; private String thread; private long id; private String search; @@ -156,7 +155,6 @@ public class FragmentMessages extends FragmentBase { Bundle args = getArguments(); account = args.getLong("account", -1); folder = args.getLong("folder", -1); - outgoing = args.getBoolean("outgoing", false); thread = args.getString("thread"); id = args.getLong("id", -1); search = args.getString("search"); @@ -269,7 +267,7 @@ public class FragmentMessages extends FragmentBase { int zoom = prefs.getInt("zoom", compact ? 0 : 1); adapter = new AdapterMessage( getContext(), getViewLifecycleOwner(), - viewType, outgoing, compact, zoom, iProperties); + viewType, compact, zoom, iProperties); rvMessage.setAdapter(adapter); @@ -367,8 +365,7 @@ public class FragmentMessages extends FragmentBase { lbm.sendBroadcast( new Intent(ActivityView.ACTION_VIEW_MESSAGES) .putExtra("account", drafts.account) - .putExtra("folder", drafts.id) - .putExtra("outgoing", drafts.isOutgoing())); + .putExtra("folder", drafts.id)); return true; } diff --git a/app/src/main/java/eu/faircode/email/Helper.java b/app/src/main/java/eu/faircode/email/Helper.java index 3cd3e84703..0cd060ff4f 100644 --- a/app/src/main/java/eu/faircode/email/Helper.java +++ b/app/src/main/java/eu/faircode/email/Helper.java @@ -327,7 +327,6 @@ public class Helper { draft.to = new Address[]{Helper.myAddress()}; draft.subject = context.getString(R.string.app_name) + " " + BuildConfig.VERSION_NAME + " debug info"; draft.received = new Date().getTime(); - draft.setContactInfo(context); draft.id = db.message().insertMessage(draft); draft.write(context, body); db.message().setMessageContent(draft.id, true, HtmlHelper.getPreview(body)); diff --git a/app/src/main/java/eu/faircode/email/ServiceSynchronize.java b/app/src/main/java/eu/faircode/email/ServiceSynchronize.java index 320fbde7f8..11b0da36ef 100644 --- a/app/src/main/java/eu/faircode/email/ServiceSynchronize.java +++ b/app/src/main/java/eu/faircode/email/ServiceSynchronize.java @@ -2607,8 +2607,11 @@ public class ServiceSynchronize extends LifecycleService { if (message == null) return; - if (message.setContactInfo(context)) - db.message().updateMessage(message); + if (message.avatar == null && !folder.isOutgoing()) { + message.avatar = EntityMessage.getLookupUri(context, message.from); + if (message.avatar != null) + db.message().updateMessage(message); + } if (download) { SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);