Optionally show recipients in message headers

pull/178/head
M66B 5 years ago
parent 691c1c7813
commit 8c50b7f6f1

@ -226,6 +226,7 @@ public class AdapterMessage extends RecyclerView.Adapter<AdapterMessage.ViewHold
private boolean name_email;
private boolean prefer_contact;
private boolean distinguish_contacts;
private boolean show_recipients;
private Float font_size_sender;
private Float font_size_subject;
private boolean subject_top;
@ -823,7 +824,8 @@ public class AdapterMessage extends RecyclerView.Adapter<AdapterMessage.ViewHold
boolean inbox = EntityFolder.INBOX.equals(message.folderType);
boolean outbox = EntityFolder.OUTBOX.equals(message.folderType);
boolean outgoing = isOutgoing(message);
Address[] addresses = (outgoing && (viewType != ViewType.THREAD || !threading) ? message.to : message.senders);
Address[] senders = (outgoing && (viewType != ViewType.THREAD || !threading) ? message.to : message.senders);
Address[] recipients = (outgoing && (viewType != ViewType.THREAD || !threading) ? message.from : message.recipients);
boolean authenticated =
!(Boolean.FALSE.equals(message.dkim) ||
Boolean.FALSE.equals(message.spf) ||
@ -947,7 +949,12 @@ public class AdapterMessage extends RecyclerView.Adapter<AdapterMessage.ViewHold
? View.VISIBLE : View.GONE);
ivSigned.setVisibility(message.signed > 0 ? View.VISIBLE : View.GONE);
ivEncrypted.setVisibility(message.encrypted > 0 ? View.VISIBLE : View.GONE);
setFrom(message, addresses);
if (show_recipients && recipients != null && recipients.length > 0)
tvFrom.setText(context.getString(R.string.title_from_to,
MessageHelper.formatAddresses(senders, name_email, false),
MessageHelper.formatAddresses(recipients, name_email, false)));
else
tvFrom.setText(MessageHelper.formatAddresses(senders, name_email, false));
tvFrom.setPaintFlags(tvFrom.getPaintFlags() & ~Paint.UNDERLINE_TEXT_FLAG);
tvSize.setText(message.totalSize == null ? null : Helper.humanReadableByteCount(message.totalSize, true));
tvSize.setVisibility(
@ -1062,7 +1069,7 @@ public class AdapterMessage extends RecyclerView.Adapter<AdapterMessage.ViewHold
}
// Contact info
ContactInfo[] info = ContactInfo.getCached(context, message.account, addresses);
ContactInfo[] info = ContactInfo.getCached(context, message.account, senders);
if (info == null) {
if (taskContactInfo != null)
taskContactInfo.cancel(context);
@ -1070,15 +1077,31 @@ public class AdapterMessage extends RecyclerView.Adapter<AdapterMessage.ViewHold
Bundle aargs = new Bundle();
aargs.putLong("id", message.id);
aargs.putLong("account", message.account);
aargs.putSerializable("addresses", addresses);
aargs.putSerializable("senders", senders);
aargs.putSerializable("recipients", show_recipients ? recipients : null);
taskContactInfo = new SimpleTask<ContactInfo[]>() {
@Override
protected ContactInfo[] onExecute(Context context, Bundle args) {
long account = args.getLong("account");
Address[] addresses = (Address[]) args.getSerializable("addresses");
Address[] senders = (Address[]) args.getSerializable("senders");
Address[] recipients = (Address[]) args.getSerializable("recipients");
Map<String, Address> map = new HashMap<>();
if (senders != null)
for (Address a : senders) {
String email = ((InternetAddress) a).getAddress();
if (!TextUtils.isEmpty(email))
map.put(email, a);
}
if (recipients != null)
for (Address a : recipients) {
String email = ((InternetAddress) a).getAddress();
if (!TextUtils.isEmpty(email))
map.put(email, a);
}
return ContactInfo.get(context, account, addresses);
return ContactInfo.get(context, account, map.values().toArray(new Address[0]));
}
@Override
@ -1090,7 +1113,7 @@ public class AdapterMessage extends RecyclerView.Adapter<AdapterMessage.ViewHold
if (amessage == null || !amessage.id.equals(id))
return;
bindContactInfo(amessage, info, addresses, name_email);
bindContactInfo(amessage, info, senders, recipients);
}
@Override
@ -1100,7 +1123,7 @@ public class AdapterMessage extends RecyclerView.Adapter<AdapterMessage.ViewHold
}.setLog(false);
taskContactInfo.execute(context, owner, aargs, "message:avatar");
} else
bindContactInfo(message, info, addresses, name_email);
bindContactInfo(message, info, senders, show_recipients ? recipients : null);
if (viewType == ViewType.THREAD)
if (expanded)
@ -1260,63 +1283,88 @@ public class AdapterMessage extends RecyclerView.Adapter<AdapterMessage.ViewHold
ibFlagged.setVisibility(View.GONE);
}
private void bindContactInfo(TupleMessageEx message, ContactInfo[] info, Address[] addresses, boolean name_email) {
if (info[0].hasPhoto()) {
ibAvatar.setImageBitmap(info[0].getPhotoBitmap());
ibAvatar.setVisibility(View.VISIBLE);
} else {
ibAvatar.setImageDrawable(null);
ibAvatar.setVisibility(View.GONE);
}
private void bindContactInfo(TupleMessageEx message, ContactInfo[] info, Address[] senders, Address[] recipients) {
Map<String, ContactInfo> map = new HashMap<>();
for (ContactInfo c : info)
map.put(c.getEmailAddress(), c);
Uri lookupUri = info[0].getLookupUri();
ibAvatar.setTag(lookupUri);
ibAvatar.setEnabled(lookupUri != null);
ContactInfo main = null;
if (senders != null && senders.length > 0) {
String email = ((InternetAddress) senders[0]).getAddress();
if (!TextUtils.isEmpty(email))
main = map.get(email);
}
if (addresses == null)
return;
if (main == null) {
ibAvatar.setImageDrawable(null);
ibAvatar.setTag(null);
} else {
ibAvatar.setImageBitmap(main.getPhotoBitmap());
boolean known = false;
boolean updated = false;
Address[] modified = Arrays.copyOf(addresses, addresses.length);
for (int i = 0; i < info.length; i++) {
if (info[i].isKnown())
known = true;
String displayName = info[i].getDisplayName();
if (!TextUtils.isEmpty(displayName)) {
String email = ((InternetAddress) modified[i]).getAddress();
String personal = ((InternetAddress) modified[i]).getPersonal();
if (TextUtils.isEmpty(personal) ||
(prefer_contact && !personal.equals(displayName)))
try {
modified[i] = new InternetAddress(email, displayName, StandardCharsets.UTF_8.name());
updated = true;
} catch (UnsupportedEncodingException ex) {
Log.w(ex);
Uri lookupUri = main.getLookupUri();
ibAvatar.setTag(lookupUri);
ibAvatar.setEnabled(lookupUri != null);
}
ibAvatar.setVisibility(main == null ? View.GONE : View.VISIBLE);
Address[] _senders = fillIn(senders, map);
Address[] _recipients = fillIn(recipients, map);
if (_senders != null || _recipients != null)
if (show_recipients && _recipients != null && _recipients.length > 0)
tvFrom.setText(context.getString(R.string.title_from_to,
MessageHelper.formatAddresses(_senders, name_email, false),
MessageHelper.formatAddresses(_recipients, name_email, false)));
else
tvFrom.setText(MessageHelper.formatAddresses(senders, name_email, false));
if (distinguish_contacts) {
boolean known = false;
if (senders != null)
for (Address sender : senders) {
String email = ((InternetAddress) sender).getAddress();
if (!TextUtils.isEmpty(email) &&
map.containsKey(email) && map.get(email).isKnown()) {
known = true;
break;
}
}
}
if (known)
tvFrom.setPaintFlags(tvFrom.getPaintFlags() | Paint.UNDERLINE_TEXT_FLAG);
}
if (updated)
setFrom(message, modified);
if (distinguish_contacts && known)
tvFrom.setPaintFlags(tvFrom.getPaintFlags() | Paint.UNDERLINE_TEXT_FLAG);
}
private void setFrom(TupleMessageEx message, Address[] addresses) {
int recipients = 0;
if (viewType == ViewType.THREAD) {
recipients = (message.to == null ? 0 : message.to.length) +
(message.cc == null ? 0 : message.cc.length) + (message.bcc == null ? 0 : message.bcc.length);
if (message.to != null && message.to.length > 0)
recipients--;
private Address[] fillIn(Address[] addresses, Map<String, ContactInfo> map) {
if (addresses == null)
return null;
boolean updated = false;
List<Address> modified = new ArrayList<>();
for (Address a : addresses) {
String email = ((InternetAddress) a).getAddress();
if (TextUtils.isEmpty(email) || !map.containsKey(email))
modified.add(a);
else {
String displayName = map.get(email).getDisplayName();
if (TextUtils.isEmpty(displayName))
modified.add(a);
else {
String personal = ((InternetAddress) a).getPersonal();
if (TextUtils.isEmpty(personal) ||
(prefer_contact && !personal.equals(displayName)))
try {
modified.add(new InternetAddress(email, displayName, StandardCharsets.UTF_8.name()));
updated = true;
} catch (UnsupportedEncodingException ex) {
Log.w(ex);
modified.add(a);
}
else
modified.add(a);
}
}
}
if (recipients == 0)
tvFrom.setText(MessageHelper.formatAddresses(addresses, name_email, false));
else
tvFrom.setText(context.getString(R.string.title_name_plus,
MessageHelper.formatAddresses(addresses, name_email, false), recipients));
return (updated ? modified.toArray(new Address[0]) : null);
}
private void bindExpandWarning(TupleMessageEx message, boolean expanded) {
@ -4638,6 +4686,7 @@ public class AdapterMessage extends RecyclerView.Adapter<AdapterMessage.ViewHold
this.name_email = prefs.getBoolean("name_email", false);
this.prefer_contact = prefs.getBoolean("prefer_contact", false);
this.distinguish_contacts = prefs.getBoolean("distinguish_contacts", false);
this.show_recipients = prefs.getBoolean("show_recipients", true);
this.subject_top = prefs.getBoolean("subject_top", false);

@ -78,6 +78,10 @@ public class ContactInfo {
return bitmap;
}
String getEmailAddress() {
return email;
}
String getDisplayName() {
return displayName;
}

@ -60,7 +60,7 @@ public class FragmentOptions extends FragmentBase {
"landscape", "landscape3", "startup", "cards", "indentation", "date", "threading",
"highlight_unread", "color_stripe",
"avatars", "gravatars", "generated_icons", "identicons", "circular", "saturation", "brightness", "threshold",
"name_email", "prefer_contact", "distinguish_contacts", "authentication",
"name_email", "prefer_contact", "distinguish_contacts", "show_recipients", "authentication",
"subject_top", "font_size_sender", "font_size_subject", "subject_italic", "highlight_subject", "subject_ellipsize",
"keywords_header", "flags", "flags_background", "preview", "preview_italic", "preview_lines",
"addresses", "button_archive_trash", "button_move", "attachments_alt",

@ -86,6 +86,7 @@ public class FragmentOptionsDisplay extends FragmentBase implements SharedPrefer
private SwitchCompat swNameEmail;
private SwitchCompat swPreferContact;
private SwitchCompat swDistinguishContacts;
private SwitchCompat swShowRecipients;
private SwitchCompat swSubjectTop;
private Spinner spFontSizeSender;
private Spinner spFontSizeSubject;
@ -120,7 +121,7 @@ public class FragmentOptionsDisplay extends FragmentBase implements SharedPrefer
"threading", "indentation", "seekbar", "actionbar", "actionbar_color",
"highlight_unread", "color_stripe",
"avatars", "gravatars", "generated_icons", "identicons", "circular", "saturation", "brightness", "threshold",
"name_email", "prefer_contact", "distinguish_contacts",
"name_email", "prefer_contact", "distinguish_contacts", "show_recipients",
"subject_top", "font_size_sender", "font_size_subject", "subject_italic", "highlight_subject", "subject_ellipsize",
"keywords_header", "flags", "flags_background",
"preview", "preview_italic", "preview_lines",
@ -171,6 +172,7 @@ public class FragmentOptionsDisplay extends FragmentBase implements SharedPrefer
swNameEmail = view.findViewById(R.id.swNameEmail);
swPreferContact = view.findViewById(R.id.swPreferContact);
swDistinguishContacts = view.findViewById(R.id.swDistinguishContacts);
swShowRecipients = view.findViewById(R.id.swShowRecipients);
swSubjectTop = view.findViewById(R.id.swSubjectTop);
spFontSizeSender = view.findViewById(R.id.spFontSizeSender);
spFontSizeSubject = view.findViewById(R.id.spFontSizeSubject);
@ -444,6 +446,13 @@ public class FragmentOptionsDisplay extends FragmentBase implements SharedPrefer
}
});
swShowRecipients.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton compoundButton, boolean checked) {
prefs.edit().putBoolean("show_recipients", checked).apply();
}
});
swSubjectTop.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton compoundButton, boolean checked) {
@ -741,6 +750,7 @@ public class FragmentOptionsDisplay extends FragmentBase implements SharedPrefer
swNameEmail.setChecked(prefs.getBoolean("name_email", false));
swPreferContact.setChecked(prefs.getBoolean("prefer_contact", false));
swDistinguishContacts.setChecked(prefs.getBoolean("distinguish_contacts", false));
swShowRecipients.setChecked(prefs.getBoolean("show_recipients", true));
swSubjectTop.setChecked(prefs.getBoolean("subject_top", false));
int[] fontSizeValues = getResources().getIntArray(R.array.fontSizeValues);

@ -499,7 +499,6 @@
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
android:checked="true"
android:text="@string/title_advanced_replace_name"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
@ -511,7 +510,6 @@
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
android:checked="true"
android:text="@string/title_advanced_distinguish_contacts"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
@ -519,17 +517,28 @@
app:switchPadding="12dp" />
<androidx.appcompat.widget.SwitchCompat
android:id="@+id/swSubjectTop"
android:id="@+id/swShowRecipients"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
android:checked="true"
android:text="@string/title_advanced_subject_top"
android:text="@string/title_advanced_show_recipients"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/swDistinguishContacts"
app:switchPadding="12dp" />
<androidx.appcompat.widget.SwitchCompat
android:id="@+id/swSubjectTop"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
android:text="@string/title_advanced_subject_top"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/swShowRecipients"
app:switchPadding="12dp" />
<eu.faircode.email.FixedTextView
android:id="@+id/tvFontSizeSender"
android:layout_width="0dp"

@ -101,6 +101,7 @@
<string name="title_name_count">%1$s (%2$s)</string>
<string name="title_name_plus">%1$s +%2$d</string>
<string name="title_from_to">%1$s > %2$s</string>
<string name="title_factor_minutes">%1$d minutes</string>
<string name="menu_exit">Exit</string>
@ -329,6 +330,7 @@
<string name="title_advanced_name_email">Show names and email addresses</string>
<string name="title_advanced_replace_name">Prefer a contact name over a sent name</string>
<string name="title_advanced_distinguish_contacts">Underline the sender when the sender is known as local \'to\' contact</string>
<string name="title_advanced_show_recipients">Show recipients in message header</string>
<string name="title_advanced_font_size_sender">Font size sender</string>
<string name="title_advanced_font_size_subject">Font size subject</string>
<string name="title_advanced_subject_top">Show subject above sender</string>

Loading…
Cancel
Save