diff --git a/res/layout/message_list_item_touchable.xml b/res/layout/message_list_item_touchable.xml index 8a94d3a40..17b5c073e 100644 --- a/res/layout/message_list_item_touchable.xml +++ b/res/layout/message_list_item_touchable.xml @@ -77,7 +77,7 @@ android:singleLine="false" android:fadingEdge="vertical" android:bufferType="spannable" - android:textColor="?android:attr/textColorTertiary" + android:textColor="?android:attr/textColorPrimary" android:textAppearance="?android:attr/textAppearanceSmall" /> diff --git a/res/values-cs/strings.xml b/res/values-cs/strings.xml index acd9145f9..caf831c61 100644 --- a/res/values-cs/strings.xml +++ b/res/values-cs/strings.xml @@ -230,7 +230,7 @@ Vítejte v nastavení pošty K-9 Mail. K-9 je open source poštovní klient pro %s %s Načti více zpráv - Komu:%s + Komu: Smazat Označit jako přečtené Označit jako nepřečtené diff --git a/res/values-de/strings.xml b/res/values-de/strings.xml index 75bca9767..bf20f7d90 100644 --- a/res/values-de/strings.xml +++ b/res/values-de/strings.xml @@ -224,7 +224,7 @@ Willkommen zum \"K-9 Mail\"-Setup. K-9 ist eine quelloffene E-Mail-Anwendung fü %s %s Weitere Nachrichten abrufen - An: %s + An: Löschen Gelesen Nicht gelesen diff --git a/res/values-fr/strings.xml b/res/values-fr/strings.xml index 7d0c9c1b3..86a63008f 100644 --- a/res/values-fr/strings.xml +++ b/res/values-fr/strings.xml @@ -227,7 +227,7 @@ %s %s Charger plus de messages - Pour\u00A0: %s + Pour\u00A0: Supprimer Marquer comme lu Marquer comme non lu diff --git a/res/values-it/strings.xml b/res/values-it/strings.xml index 057075ddf..5a31044d5 100644 --- a/res/values-it/strings.xml +++ b/res/values-it/strings.xml @@ -62,7 +62,7 @@ Non vi sono altri messaggi K-9 per Android %s Testo del messaggio - A:%s + A: Da: %s <%s> Cc: Impossibile cancellare il messaggio diff --git a/res/values-ja/strings.xml b/res/values-ja/strings.xml index c80a6eab7..24de990e8 100644 --- a/res/values-ja/strings.xml +++ b/res/values-ja/strings.xml @@ -235,7 +235,7 @@ K-9 Mail セットアップにようこそ。\nK-9 はオープンソースで %s %s 他メールを読込 - 宛先:%s + 宛先: 削除 既読にする 未読にする diff --git a/res/values-pl/strings.xml b/res/values-pl/strings.xml index 04a4366a7..b036ba1d3 100644 --- a/res/values-pl/strings.xml +++ b/res/values-pl/strings.xml @@ -238,7 +238,7 @@ Witaj w K-9 Mail, darmowym programie pocztowym dla systemu Android. Najistotniej %s %s Pobierz więcej wiadomości - Do:%s + Do: Usuń Przecz. Nieprz. @@ -853,4 +853,4 @@ Witaj w K-9 Mail, darmowym programie pocztowym dla systemu Android. Najistotniej Obejdź błędy w Galerii Wyświetla przyciski dodawania zdjęć oraz filmów jako załączników - \ No newline at end of file + diff --git a/res/values-ru/strings.xml b/res/values-ru/strings.xml index 3b696188c..621825ab8 100644 --- a/res/values-ru/strings.xml +++ b/res/values-ru/strings.xml @@ -217,7 +217,7 @@ %s %s Загрузить болюше сообщений - Для:%s + Для: Удалить Отметить как прочитанное Отметить как непрочитанное diff --git a/res/values/strings.xml b/res/values/strings.xml index 3bd23073d..b4d645f00 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -240,7 +240,7 @@ Welcome to K-9 Mail setup. K-9 is an open source mail client for Android origin %s %s Load more messages - To:%s + To: Delete Mark read Mark unread diff --git a/src/com/fsck/k9/activity/MessageInfoHolder.java b/src/com/fsck/k9/activity/MessageInfoHolder.java index 8fe94873a..eabce1a18 100644 --- a/src/com/fsck/k9/activity/MessageInfoHolder.java +++ b/src/com/fsck/k9/activity/MessageInfoHolder.java @@ -1,74 +1,26 @@ package com.fsck.k9.activity; -import java.util.ArrayList; -import java.util.Collections; import java.util.Date; -import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; -import android.app.AlertDialog; -import android.app.Dialog; import android.content.Context; -import android.content.DialogInterface; -import android.content.Intent; -import android.graphics.Typeface; -import android.graphics.drawable.Drawable; -import android.os.Bundle; -import android.os.Handler; -import android.text.Spannable; -import android.text.style.TextAppearanceSpan; +import android.text.SpannableStringBuilder; import android.util.Config; import android.util.Log; -import android.util.TypedValue; -import android.view.ContextMenu; -import android.view.ContextMenu.ContextMenuInfo; -import android.view.GestureDetector; -import android.view.GestureDetector.SimpleOnGestureListener; -import android.view.KeyEvent; -import android.view.LayoutInflater; -import android.view.Menu; -import android.view.MenuItem; -import android.view.MotionEvent; -import android.view.View; -import android.view.View.OnClickListener; -import android.view.ViewGroup; -import android.view.Window; -import android.widget.AdapterView; -import android.widget.AdapterView.AdapterContextMenuInfo; -import android.widget.BaseAdapter; -import android.widget.CheckBox; -import android.widget.CompoundButton; -import android.widget.CompoundButton.OnCheckedChangeListener; -import android.widget.ImageButton; -import android.widget.ListView; -import android.widget.ProgressBar; -import android.widget.TextView; -import android.widget.Toast; -import android.text.format.DateFormat; import com.fsck.k9.Account; -import com.fsck.k9.AccountStats; -import com.fsck.k9.FontSizes; import com.fsck.k9.K9; -import com.fsck.k9.Preferences; import com.fsck.k9.R; -import com.fsck.k9.SearchSpecification; -import com.fsck.k9.activity.setup.AccountSettings; -import com.fsck.k9.activity.setup.FolderSettings; -import com.fsck.k9.activity.setup.Prefs; import com.fsck.k9.activity.FolderInfoHolder; import com.fsck.k9.controller.MessagingController; import com.fsck.k9.controller.MessagingController.SORT_TYPE; -import com.fsck.k9.controller.MessagingListener; +import com.fsck.k9.helper.Contacts; import com.fsck.k9.helper.Utility; import com.fsck.k9.mail.Address; import com.fsck.k9.mail.Flag; -import com.fsck.k9.mail.Folder; import com.fsck.k9.mail.Message; import com.fsck.k9.mail.Message.RecipientType; import com.fsck.k9.mail.MessagingException; -import com.fsck.k9.mail.store.LocalStore; -import com.fsck.k9.mail.store.LocalStore.LocalFolder; import com.fsck.k9.mail.store.LocalStore.LocalMessage; public class MessageInfoHolder implements Comparable @@ -78,7 +30,7 @@ public class MessageInfoHolder implements Comparable public String fullDate; public Date compareDate; public String compareSubject; - public String sender; + public CharSequence sender; public String senderAddress; public String compareCounterparty; public String preview; @@ -96,6 +48,8 @@ public class MessageInfoHolder implements Comparable public String account; public String uri; + private Contacts mContacts; + private SORT_TYPE sortType = SORT_TYPE.SORT_DATE; private boolean sortAscending = true; @@ -111,6 +65,9 @@ public class MessageInfoHolder implements Comparable public MessageInfoHolder(Context context, Message m) { this(); + + mContacts = Contacts.getInstance(context); + Account account = m.getFolder().getAccount(); mController = MessagingController.getInstance(K9.app); sortType = mController.getSortType(); @@ -122,6 +79,9 @@ public class MessageInfoHolder implements Comparable public MessageInfoHolder(Context context ,Message m, SORT_TYPE t_sort, boolean asc) { this(); + + mContacts = Contacts.getInstance(context); + Account account = m.getFolder().getAccount(); mController = MessagingController.getInstance(K9.app); sortType = t_sort; @@ -133,11 +93,15 @@ public class MessageInfoHolder implements Comparable public MessageInfoHolder(Context context, Message m, FolderInfoHolder folder, Account account) { this(); + + mContacts = Contacts.getInstance(context); + mController = MessagingController.getInstance(K9.app); sortType = mController.getSortType(); sortAscending = mController.isSortAscending(sortType); sortDateAscending = mController.isSortAscending(SORT_TYPE.SORT_DATE); populate(context, m, folder, account); + } public void populate(Context context, Message m, FolderInfoHolder folder, Account account) @@ -175,13 +139,13 @@ public class MessageInfoHolder implements Comparable if (addrs.length > 0 && account.isAnIdentity(addrs[0])) { - this.compareCounterparty = Address.toFriendly(message .getRecipients(RecipientType.TO)); - this.sender = String.format(context.getString(R.string.message_list_to_fmt), this.compareCounterparty); - } + CharSequence to = Address.toFriendly(message .getRecipients(RecipientType.TO), mContacts); + this.compareCounterparty = to.toString(); + this.sender = new SpannableStringBuilder(context.getString(R.string.message_list_to_fmt)).append(to); } else { - this.sender = Address.toFriendly(addrs); - this.compareCounterparty = this.sender; + this.sender = Address.toFriendly(addrs, mContacts); + this.compareCounterparty = this.sender.toString(); } if (addrs.length > 0) diff --git a/src/com/fsck/k9/activity/MessageList.java b/src/com/fsck/k9/activity/MessageList.java index 33e765f8d..ab433912a 100644 --- a/src/com/fsck/k9/activity/MessageList.java +++ b/src/com/fsck/k9/activity/MessageList.java @@ -12,11 +12,14 @@ import android.app.Dialog; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; +import android.graphics.Color; import android.graphics.Typeface; import android.graphics.drawable.Drawable; import android.os.Bundle; import android.text.Spannable; -import android.text.style.TextAppearanceSpan; +import android.text.SpannableStringBuilder; +import android.text.style.ForegroundColorSpan; +import android.text.style.StyleSpan; import android.util.Config; import android.util.Log; import android.util.TypedValue; @@ -59,6 +62,7 @@ import com.fsck.k9.activity.setup.Prefs; import com.fsck.k9.controller.MessagingController; import com.fsck.k9.controller.MessagingController.SORT_TYPE; import com.fsck.k9.controller.MessagingListener; +import com.fsck.k9.helper.Contacts; import com.fsck.k9.helper.Utility; import com.fsck.k9.mail.Address; import com.fsck.k9.mail.Flag; @@ -437,6 +441,7 @@ public class MessageList { context=this; super.onCreate(savedInstanceState); + mInflater = getLayoutInflater(); initializeLayout(); onNewIntent(getIntent()); @@ -2416,22 +2421,21 @@ public class MessageList * compose a custom view containing the preview and the * from. */ - holder.preview.setText(message.sender + " " + message.preview, + holder.preview.setText(new SpannableStringBuilder(message.sender).append(" ").append(message.preview), TextView.BufferType.SPANNABLE); Spannable str = (Spannable)holder.preview.getText(); // Create our span sections, and assign a format to each. - str.setSpan( - new TextAppearanceSpan( - null, - Typeface.BOLD, - -1, - holder.subject.getTextColors(), - holder.subject.getLinkTextColors()), + str.setSpan(new StyleSpan(Typeface.BOLD), 0, message.sender.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE ); + str.setSpan(new ForegroundColorSpan(Color.rgb(128,128,128)), // TODO: How do I can specify the android.R.attr.textColorTertiary + message.sender.length(), + str.length(), + Spannable.SPAN_EXCLUSIVE_EXCLUSIVE + ); } else { diff --git a/src/com/fsck/k9/activity/MessageView.java b/src/com/fsck/k9/activity/MessageView.java index ca3fe8504..cb4d3af98 100644 --- a/src/com/fsck/k9/activity/MessageView.java +++ b/src/com/fsck/k9/activity/MessageView.java @@ -428,11 +428,11 @@ public class MessageView extends K9Activity implements OnClickListener public void setHeaders( final String subject, - final String from, + final CharSequence from, final String date, final String time, - final String to, - final String cc, + final CharSequence to, + final CharSequence cc, final int accountColor, final boolean unread, final boolean hasAttachments, @@ -2093,11 +2093,11 @@ public class MessageView extends K9Activity implements OnClickListener final Message message) throws MessagingException { String subjectText = message.getSubject(); - String fromText = Address.toFriendly(message.getFrom()); + CharSequence fromText = Address.toFriendly(message.getFrom(), mContacts); String dateText = getDateFormat().format(message.getSentDate()); String timeText = getTimeFormat().format(message.getSentDate()); - String toText = Address.toFriendly(message.getRecipients(RecipientType.TO)); - String ccText = Address.toFriendly(message.getRecipients(RecipientType.CC)); + CharSequence toText = Address.toFriendly(message.getRecipients(RecipientType.TO), mContacts); + CharSequence ccText = Address.toFriendly(message.getRecipients(RecipientType.CC), mContacts); int color = mAccount.getChipColor(); boolean hasAttachments = ((LocalMessage) message).getAttachmentCount() > 0; diff --git a/src/com/fsck/k9/controller/MessagingController.java b/src/com/fsck/k9/controller/MessagingController.java index 8d66359de..44ba79120 100644 --- a/src/com/fsck/k9/controller/MessagingController.java +++ b/src/com/fsck/k9/controller/MessagingController.java @@ -4570,7 +4570,7 @@ public class MessagingController implements Runnable if (message != null && message.getFrom() != null) { Address[] fromAddrs = message.getFrom(); - String from = fromAddrs.length > 0 ? fromAddrs[0].toFriendly() : null; + String from = fromAddrs.length > 0 ? fromAddrs[0].toFriendly().toString() : null; String subject = message.getSubject(); if (subject == null) { @@ -4593,7 +4593,7 @@ public class MessagingController implements Runnable } Address[] rcpts = message.getRecipients(Message.RecipientType.TO); - String to = rcpts.length > 0 ? rcpts[0].toFriendly() : null; + String to = rcpts.length > 0 ? rcpts[0].toFriendly().toString() : null; if (to != null) { messageNotice.append(String.format(context.getString(R.string.message_list_to_fmt), to) +": "+subject); diff --git a/src/com/fsck/k9/helper/Contacts.java b/src/com/fsck/k9/helper/Contacts.java index 65df9aece..6f85bf7f5 100644 --- a/src/com/fsck/k9/helper/Contacts.java +++ b/src/com/fsck/k9/helper/Contacts.java @@ -147,6 +147,8 @@ public abstract class Contacts */ public abstract Cursor searchContacts(CharSequence filter); + public abstract Cursor searchByAddress(String address); + /** * Extract the name from a {@link Cursor} instance returned by * {@link #searchContacts(CharSequence)}. diff --git a/src/com/fsck/k9/helper/ContactsSdk3_4.java b/src/com/fsck/k9/helper/ContactsSdk3_4.java index 2538b578d..0ff17f531 100644 --- a/src/com/fsck/k9/helper/ContactsSdk3_4.java +++ b/src/com/fsck/k9/helper/ContactsSdk3_4.java @@ -173,6 +173,45 @@ public class ContactsSdk3_4 extends com.fsck.k9.helper.Contacts return c; } + @Override + public Cursor searchByAddress(String address) + { + final String where; + final String[] args; + if (address == null) + { + where = null; + args = null; + } + else + { + where = Contacts.ContactMethods.DATA + " = ?"; + args = new String[] {address}; + } + + final Cursor c = mContentResolver.query( + Contacts.ContactMethods.CONTENT_EMAIL_URI, + PROJECTION, + where, + args, + SORT_ORDER); + + if (c != null) + { + /* + * To prevent expensive execution in the UI thread: + * Cursors get lazily executed, so if you don't call anything on + * the cursor before returning it from the background thread you'll + * have a complied program for the cursor, but it won't have been + * executed to generate the data yet. Often the execution is more + * expensive than the compilation... + */ + c.getCount(); + } + + return c; + } + @Override public String getName(Cursor c) { diff --git a/src/com/fsck/k9/helper/ContactsSdk5.java b/src/com/fsck/k9/helper/ContactsSdk5.java index 728d9a4e1..e921391d3 100644 --- a/src/com/fsck/k9/helper/ContactsSdk5.java +++ b/src/com/fsck/k9/helper/ContactsSdk5.java @@ -149,6 +149,34 @@ public class ContactsSdk5 extends com.fsck.k9.helper.Contacts return c; } + @Override + public Cursor searchByAddress(String address) + { + final String filter = (address == null) ? "" : address; + final Uri uri = Uri.withAppendedPath(Email.CONTENT_FILTER_URI, Uri.encode(filter)); + final Cursor c = mContentResolver.query( + uri, + PROJECTION, + null, + null, + SORT_ORDER); + + if (c != null) + { + /* + * To prevent expensive execution in the UI thread: + * Cursors get lazily executed, so if you don't call anything on + * the cursor before returning it from the background thread you'll + * have a complied program for the cursor, but it won't have been + * executed to generate the data yet. Often the execution is more + * expensive than the compilation... + */ + c.getCount(); + } + + return c; + } + @Override public String getName(Cursor c) { diff --git a/src/com/fsck/k9/mail/Address.java b/src/com/fsck/k9/mail/Address.java index 3b20f430b..838cc3632 100644 --- a/src/com/fsck/k9/mail/Address.java +++ b/src/com/fsck/k9/mail/Address.java @@ -1,10 +1,15 @@ package com.fsck.k9.mail; +import android.database.Cursor; +import android.text.Html; +import android.text.SpannableStringBuilder; import android.text.util.Rfc822Token; import android.text.util.Rfc822Tokenizer; import android.util.Log; + import com.fsck.k9.K9; +import com.fsck.k9.helper.Contacts; import com.fsck.k9.helper.Utility; import org.apache.james.mime4j.codec.EncoderUtil; import org.apache.james.mime4j.field.address.AddressList; @@ -14,7 +19,11 @@ import org.apache.james.mime4j.field.address.NamedMailbox; import org.apache.james.mime4j.field.address.parser.ParseException; import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; public class Address { @@ -23,6 +32,8 @@ public class Address * Immutable empty {@link Address} array */ private static final Address[] EMPTY_ADDRESS_ARRAY = new Address[0]; + private static Map sContactsName = new ConcurrentHashMap(); + private static final String NO_ENTRY = ""; String mAddress; @@ -230,11 +241,43 @@ public class Address * is not available. * @return */ - public String toFriendly() + public CharSequence toFriendly() { + return toFriendly((Contacts)null); + } + + public CharSequence toFriendly(Contacts contacts) + { + if (contacts != null) { + String name = sContactsName.get(mAddress); + if (name != null && name != NO_ENTRY) { + return Html.fromHtml("" + name + ""); // TODO: use setSpan + } + if (name == null) { + Cursor cursor = contacts.searchByAddress(mAddress); + if (cursor != null) { + try { + if (cursor.getCount() > 0) { + cursor.moveToFirst(); + name = contacts.getName(cursor); + sContactsName.put(mAddress, name); + return Html.fromHtml("" + name + ""); // TODO: use setSpan + } + else { + sContactsName.put(mAddress, NO_ENTRY); + } + } + finally { + Log.i(K9.LOG_TAG, "cursor closed"); + // cursor.close(); // TODO: should close cursor. + } + } + } + } + if (mPersonal != null && mPersonal.length() > 0) { - return mPersonal; + return mPersonal; } else { @@ -242,22 +285,27 @@ public class Address } } - public static String toFriendly(Address[] addresses) + public static CharSequence toFriendly(Address[] addresses) + { + return toFriendly(addresses, null); + } + + public static CharSequence toFriendly(Address[] addresses, Contacts contacts) { if (addresses == null) { return null; } - StringBuffer sb = new StringBuffer(); + SpannableStringBuilder sb = new SpannableStringBuilder(); for (int i = 0; i < addresses.length; i++) { - sb.append(addresses[i].toFriendly()); + sb.append(addresses[i].toFriendly(contacts)); if (i < addresses.length - 1) { sb.append(','); } } - return sb.toString(); + return sb; } /**