summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJames Lemieux <jplemieux@google.com>2014-04-02 22:57:00 +0000
committerAndroid Git Automerger <android-git-automerger@android.com>2014-04-02 22:57:00 +0000
commit0653f9f2cf6424bbd274a2016b8d72d5431f2125 (patch)
treed4a0f8eb33da93e09830c685a3a8674fb86a3bc8
parent487f79d103753a3eaa51f8c2bd8b6a219534fdf5 (diff)
parent10ea28ab588d8e922c0f78f0f47fe479739ec2cf (diff)
downloadandroid_packages_apps_UnifiedEmail-0653f9f2cf6424bbd274a2016b8d72d5431f2125.tar.gz
android_packages_apps_UnifiedEmail-0653f9f2cf6424bbd274a2016b8d72d5431f2125.tar.bz2
android_packages_apps_UnifiedEmail-0653f9f2cf6424bbd274a2016b8d72d5431f2125.zip
am 10ea28ab: Show "To:<Names>" in sent and outbox index views
* commit '10ea28ab588d8e922c0f78f0f47fe479739ec2cf': Show "To:<Names>" in sent and outbox index views
-rw-r--r--res/values/strings.xml8
-rw-r--r--src/com/android/mail/browse/ConversationItemView.java50
-rw-r--r--src/com/android/mail/browse/ConversationItemViewModel.java16
-rw-r--r--src/com/android/mail/browse/MessageHeaderView.java2
-rw-r--r--src/com/android/mail/browse/SendersView.java53
-rw-r--r--src/com/android/mail/providers/Folder.java14
-rw-r--r--src/com/android/mail/providers/UIProvider.java6
-rw-r--r--src/com/android/mail/ui/FolderSelectionActivity.java4
-rw-r--r--src/com/android/mail/utils/NotificationUtils.java3
-rw-r--r--src/com/android/mail/widget/BaseWidgetProvider.java34
-rw-r--r--src/com/android/mail/widget/WidgetService.java74
-rw-r--r--tests/src/com/android/mail/browse/SendersFormattingTests.java8
12 files changed, 169 insertions, 103 deletions
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 54304cd14..838354c9d 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -291,9 +291,9 @@
<item quantity="other">Move <xliff:g>%1$d</xliff:g> conversations</item>
</plurals>
<!-- Formatting string for the content description field of a conversation list item when device is in accessibility mode. [CHAR LIMIT=250] -->
- <string name="content_description"><xliff:g id="sender">%1$s</xliff:g> about <xliff:g id="subject">%2$s</xliff:g>, <xliff:g id="snippet">%3$s</xliff:g> on <xliff:g id="date">%4$s</xliff:g>, <xliff:g id="readstate">%5$s</xliff:g></string>
+ <string name="content_description"><xliff:g id="toHeader">%1$s</xliff:g><xliff:g id="participant">%2$s</xliff:g> about <xliff:g id="subject">%3$s</xliff:g>, <xliff:g id="snippet">%4$s</xliff:g> on <xliff:g id="date">%5$s</xliff:g>, <xliff:g id="readstate">%6$s</xliff:g></string>
<!-- Formatting string for the content description field of a conversation list item when device is in accessibility mode and the message was received today. [CHAR LIMI=250] -->
- <string name="content_description_today"><xliff:g id="sender">%1$s</xliff:g> about <xliff:g id="subject">%2$s</xliff:g>, <xliff:g id="snippet">%3$s</xliff:g> at <xliff:g id="time">%4$s</xliff:g>, <xliff:g id="readstate">%5$s</xliff:g></string>
+ <string name="content_description_today"><xliff:g id="toHeader">%1$s</xliff:g><xliff:g id="participant">%2$s</xliff:g> about <xliff:g id="subject">%3$s</xliff:g>, <xliff:g id="snippet">%4$s</xliff:g> at <xliff:g id="time">%5$s</xliff:g>, <xliff:g id="readstate">%6$s</xliff:g></string>
<!-- String used in content description field of a conversation list item when device is in accessibility mode and the conversation was read [CHAR LIMIT=250] -->
<string name="read_string">conversation read</string>
<!-- String used in content description field of a conversation list item when device is in accessibility mode and the conversation was not read [CHAR LIMIT=250] -->
@@ -318,10 +318,10 @@
<string name="send_failed">Message wasn\'t sent.</string>
<!-- String used to represent "me" when used as an object pronoun. This string is used when
showing the list of recipients of a message [CHAR LIMIT=15] -->
- <string name="me_object_pronun">me</string>
+ <string name="me_object_pronoun">me</string>
<!-- String used to represent "me"/"I" when used as an subject pronoun. This string is use when
showing the list of senders for a conversation list item. [CHAR LIMIT=15] -->
- <string name="me_subject_pronun">me</string>
+ <string name="me_subject_pronoun">me</string>
<!-- Header for list of inboxes in the drawer (Inbox, Priority) [CHAR LIMIT=50] -->
<string name="inbox_folders_heading">Inbox</string>
diff --git a/src/com/android/mail/browse/ConversationItemView.java b/src/com/android/mail/browse/ConversationItemView.java
index 8ab84b1e9..e0613fa7a 100644
--- a/src/com/android/mail/browse/ConversationItemView.java
+++ b/src/com/android/mail/browse/ConversationItemView.java
@@ -100,8 +100,8 @@ import com.android.mail.utils.ViewUtils;
import com.google.common.annotations.VisibleForTesting;
import java.util.ArrayList;
-import java.util.List;
import java.util.Iterator;
+import java.util.List;
public class ConversationItemView extends View
implements SwipeableItemView, ToggleableItem, InvalidateCallback, OnScrollListener,
@@ -795,7 +795,8 @@ public class ConversationItemView extends View
private void setContentDescription() {
if (mActivity.isAccessibilityEnabled()) {
mHeader.resetContentDescription();
- setContentDescription(mHeader.getContentDescription(mContext));
+ setContentDescription(
+ mHeader.getContentDescription(mContext, mDisplayedFolder.shouldShowRecipients()));
}
}
@@ -849,7 +850,8 @@ public class ConversationItemView extends View
SendersView.format(context, mHeader.conversation.conversationInfo,
mHeader.messageInfoString.toString(), maxChars, mHeader.styledNames,
- mHeader.displayableNames, mHeader.displayableEmails, mAccount, true);
+ mHeader.displayableNames, mHeader.displayableEmails, mAccount,
+ mDisplayedFolder.shouldShowRecipients(), true);
if (mHeader.displayableEmails.isEmpty() && mHeader.hasDraftMessage) {
mHeader.displayableEmails.add(mAccount);
@@ -1035,13 +1037,13 @@ public class ConversationItemView extends View
v.layout(0, 0, w, h);
}
- private void layoutParticipantLine(SpannableStringBuilder topLine) {
- if (topLine != null) {
+ private void layoutParticipantText(SpannableStringBuilder participantText) {
+ if (participantText != null) {
if (isActivated() && showActivatedText()) {
- topLine.setSpan(sActivatedTextSpan, 0,
+ participantText.setSpan(sActivatedTextSpan, 0,
mHeader.styledMessageInfoStringOffset, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
} else {
- topLine.removeSpan(sActivatedTextSpan);
+ participantText.removeSpan(sActivatedTextSpan);
}
final int w = mSendersWidth;
@@ -1051,7 +1053,7 @@ public class ConversationItemView extends View
mSendersTextView.setTextSize(TypedValue.COMPLEX_UNIT_PX, mCoordinates.sendersFontSize);
layoutViewExactly(mSendersTextView, w, h);
- mSendersTextView.setText(topLine);
+ mSendersTextView.setText(participantText);
}
}
@@ -1234,8 +1236,8 @@ public class ConversationItemView extends View
sPaint.setTypeface(Typeface.DEFAULT);
if (mHeader.styledNames != null) {
- final SpannableStringBuilder topLine = ellipsize(mHeader.styledNames);
- layoutParticipantLine(topLine);
+ final SpannableStringBuilder participantText = elideParticipants(mHeader.styledNames);
+ layoutParticipantText(participantText);
} else {
// First pass to calculate width of each fragment.
if (mSendersWidth < 0) {
@@ -1253,16 +1255,33 @@ public class ConversationItemView extends View
pauseTimer(PERF_TAG_CALCULATE_COORDINATES);
}
- // The rules for displaying ellipsized senders are as follows:
+ // The rules for displaying elided participants are as follows:
// 1) If there is message info (either a COUNT or DRAFT info to display), it MUST be shown
// 2) If senders do not fit, ellipsize the last one that does fit, and stop
// appending new senders
- private SpannableStringBuilder ellipsize(List<SpannableString> parts) {
- SpannableStringBuilder builder = new SpannableStringBuilder();
+ SpannableStringBuilder elideParticipants(List<SpannableString> parts) {
+ final SpannableStringBuilder builder = new SpannableStringBuilder();
float totalWidth = 0;
boolean ellipsize = false;
float width;
- SpannableStringBuilder messageInfoString = mHeader.messageInfoString;
+ boolean skipToHeader = false;
+
+ // start with "To: " if we're showing recipients
+ if (mDisplayedFolder.shouldShowRecipients() && !parts.isEmpty()) {
+ final SpannableString toHeader = SendersView.getFormattedToHeader();
+ CharacterStyle[] spans = toHeader.getSpans(0, toHeader.length(),
+ CharacterStyle.class);
+ // There is only 1 character style span; make sure we apply all the
+ // styles to the paint object before measuring.
+ if (spans.length > 0) {
+ spans[0].updateDrawState(sPaint);
+ }
+ totalWidth += sPaint.measureText(toHeader.toString());
+ builder.append(toHeader);
+ skipToHeader = true;
+ }
+
+ final SpannableStringBuilder messageInfoString = mHeader.messageInfoString;
if (messageInfoString.length() > 0) {
CharacterStyle[] spans = messageInfoString.getSpans(0, messageInfoString.length(),
CharacterStyle.class);
@@ -1296,13 +1315,14 @@ public class ConversationItemView extends View
if (SendersView.sElidedString.equals(sender.toString())) {
prevSender = sender;
sender = copyStyles(spans, sElidedPaddingToken + sender + sElidedPaddingToken);
- } else if (builder.length() > 0
+ } else if (!skipToHeader && builder.length() > 0
&& (prevSender == null || !SendersView.sElidedString.equals(prevSender
.toString()))) {
prevSender = sender;
sender = copyStyles(spans, sSendersSplitToken + sender);
} else {
prevSender = sender;
+ skipToHeader = false;
}
if (spans.length > 0) {
spans[0].updateDrawState(sPaint);
diff --git a/src/com/android/mail/browse/ConversationItemViewModel.java b/src/com/android/mail/browse/ConversationItemViewModel.java
index a016519e5..eaea1e339 100644
--- a/src/com/android/mail/browse/ConversationItemViewModel.java
+++ b/src/com/android/mail/browse/ConversationItemViewModel.java
@@ -48,7 +48,6 @@ import java.util.List;
public class ConversationItemViewModel {
private static final int MAX_CACHE_SIZE = 100;
- int fontColor;
@VisibleForTesting
static LruCache<Pair<String, Long>, ConversationItemViewModel> sConversationHeaderMap
= new LruCache<Pair<String, Long>, ConversationItemViewModel>(MAX_CACHE_SIZE);
@@ -286,7 +285,7 @@ public class ConversationItemViewModel {
/**
* Get conversation information to use for accessibility.
*/
- public CharSequence getContentDescription(Context context) {
+ public CharSequence getContentDescription(Context context, boolean showToHeader) {
if (mContentDescription == null) {
// If any are unread, get the first unread sender.
// If all are unread, get the first sender.
@@ -300,7 +299,7 @@ public class ConversationItemViewModel {
}
if (conversation.read) {
participant = TextUtils.isEmpty(lastParticipant) ?
- SendersView.getMe(context) : lastParticipant;
+ SendersView.getMe(showToHeader /* useObjectMe */) : lastParticipant;
} else {
ParticipantInfo firstUnread = null;
for (ParticipantInfo p : conversation.conversationInfo.participantInfos) {
@@ -311,20 +310,27 @@ public class ConversationItemViewModel {
}
if (firstUnread != null) {
participant = TextUtils.isEmpty(firstUnread.name) ?
- SendersView.getMe(context) : firstUnread.name;
+ SendersView.getMe(showToHeader /* useObjectMe */) : firstUnread.name;
}
}
if (TextUtils.isEmpty(participant)) {
// Just take the last sender
participant = lastParticipant;
}
+
+ // the toHeader should read "To: " if requested
+ String toHeader = "";
+ if (showToHeader && !TextUtils.isEmpty(participant)) {
+ toHeader = SendersView.getFormattedToHeader().toString();
+ }
+
boolean isToday = DateUtils.isToday(conversation.dateMs);
String date = DateUtils.getRelativeTimeSpanString(context, conversation.dateMs)
.toString();
String readString = context.getString(
conversation.read ? R.string.read_string : R.string.unread_string);
int res = isToday ? R.string.content_description_today : R.string.content_description;
- mContentDescription = context.getString(res, participant,
+ mContentDescription = context.getString(res, toHeader, participant,
conversation.subject, conversation.getSnippet(), date, readString);
}
return mContentDescription;
diff --git a/src/com/android/mail/browse/MessageHeaderView.java b/src/com/android/mail/browse/MessageHeaderView.java
index 07ec19310..7881f07f8 100644
--- a/src/com/android/mail/browse/MessageHeaderView.java
+++ b/src/com/android/mail/browse/MessageHeaderView.java
@@ -246,7 +246,7 @@ public class MessageHeaderView extends SnapHeader implements OnClickListener,
mIsSnappy = false;
mEmailCopyMenu = new EmailCopyContextMenu(getContext());
mInflater = LayoutInflater.from(context);
- mMyName = context.getString(R.string.me_object_pronun);
+ mMyName = context.getString(R.string.me_object_pronoun);
final Resources resources = getResources();
mContactPhotoWidth = resources.getDimensionPixelSize(
diff --git a/src/com/android/mail/browse/SendersView.java b/src/com/android/mail/browse/SendersView.java
index 608b4f3db..2d7657ecb 100644
--- a/src/com/android/mail/browse/SendersView.java
+++ b/src/com/android/mail/browse/SendersView.java
@@ -31,7 +31,6 @@ import android.text.TextUtils;
import android.text.style.CharacterStyle;
import android.text.style.TextAppearanceSpan;
-import com.android.emailcommon.mail.Address;
import com.android.mail.R;
import com.android.mail.providers.Conversation;
import com.android.mail.providers.ConversationInfo;
@@ -43,20 +42,14 @@ import com.google.common.base.Objects;
import com.google.common.collect.Maps;
import java.util.ArrayList;
-import java.util.Locale;
import java.util.Map;
-import java.util.regex.Pattern;
public class SendersView {
- public static final int DEFAULT_FORMATTING = 0;
- public static final int MERGED_FORMATTING = 1;
private static final Integer DOES_NOT_EXIST = -5;
// FIXME(ath): make all of these statics instance variables, and have callers hold onto this
// instance as long as appropriate (e.g. activity lifetime).
// no need to listen for configuration changes.
private static String sSendersSplitToken;
- public static String SENDERS_VERSION_SEPARATOR = "^**^";
- public static Pattern SENDERS_VERSION_SEPARATOR_PATTERN = Pattern.compile("\\^\\*\\*\\^");
private static CharSequence sDraftSingularString;
private static CharSequence sDraftPluralString;
private static CharSequence sSendingString;
@@ -65,8 +58,9 @@ public class SendersView {
private static CharacterStyle sSendingStyleSpan;
private static TextAppearanceSpan sUnreadStyleSpan;
private static CharacterStyle sReadStyleSpan;
- private static String sMeString;
- private static Locale sMeStringLocale;
+ private static String sMeSubjectString;
+ private static String sMeObjectString;
+ private static String sToHeaderString;
private static String sMessageCountSpacerString;
public static CharSequence sElidedString;
private static BroadcastReceiver sConfigurationChangedReceiver;
@@ -117,6 +111,9 @@ public class SendersView {
sDraftSingularString = res.getQuantityText(R.plurals.draft, 1);
sDraftPluralString = res.getQuantityText(R.plurals.draft, 2);
sDraftCountFormatString = res.getString(R.string.draft_count_format);
+ sMeSubjectString = res.getString(R.string.me_subject_pronoun);
+ sMeObjectString = res.getString(R.string.me_object_pronoun);
+ sToHeaderString = res.getString(R.string.to_heading);
sMessageInfoUnreadStyleSpan = new TextAppearanceSpan(context,
R.style.MessageInfoUnreadTextAppearance);
sMessageInfoReadStyleSpan = new TextAppearanceSpan(context,
@@ -202,12 +199,12 @@ public class SendersView {
public static void format(Context context, ConversationInfo conversationInfo,
String messageInfo, int maxChars, ArrayList<SpannableString> styledSenders,
ArrayList<String> displayableSenderNames, ArrayList<String> displayableSenderEmails,
- String account, final boolean resourceCachingRequired) {
+ String account, final boolean showToHeader, final boolean resourceCachingRequired) {
try {
getSenderResources(context, resourceCachingRequired);
format(context, conversationInfo, messageInfo, maxChars, styledSenders,
displayableSenderNames, displayableSenderEmails, account,
- sUnreadStyleSpan, sReadStyleSpan, resourceCachingRequired);
+ sUnreadStyleSpan, sReadStyleSpan, showToHeader, resourceCachingRequired);
} finally {
if (!resourceCachingRequired) {
clearResourceCache();
@@ -219,12 +216,13 @@ public class SendersView {
String messageInfo, int maxChars, ArrayList<SpannableString> styledSenders,
ArrayList<String> displayableSenderNames, ArrayList<String> displayableSenderEmails,
String account, final TextAppearanceSpan notificationUnreadStyleSpan,
- final CharacterStyle notificationReadStyleSpan, final boolean resourceCachingRequired) {
+ final CharacterStyle notificationReadStyleSpan, final boolean showToHeader,
+ final boolean resourceCachingRequired) {
try {
getSenderResources(context, resourceCachingRequired);
- handlePriority(context, maxChars, messageInfo, conversationInfo, styledSenders,
+ handlePriority(maxChars, messageInfo, conversationInfo, styledSenders,
displayableSenderNames, displayableSenderEmails, account,
- notificationUnreadStyleSpan, notificationReadStyleSpan);
+ notificationUnreadStyleSpan, notificationReadStyleSpan, showToHeader);
} finally {
if (!resourceCachingRequired) {
clearResourceCache();
@@ -232,11 +230,11 @@ public class SendersView {
}
}
- public static void handlePriority(Context context, int maxChars, String messageInfoString,
+ private static void handlePriority(int maxChars, String messageInfoString,
ConversationInfo conversationInfo, ArrayList<SpannableString> styledSenders,
ArrayList<String> displayableSenderNames, ArrayList<String> displayableSenderEmails,
String account, final TextAppearanceSpan unreadStyleSpan,
- final CharacterStyle readStyleSpan) {
+ final CharacterStyle readStyleSpan, final boolean showToHeader) {
boolean shouldAddPhotos = displayableSenderEmails != null;
int maxPriorityToInclude = -1; // inclusive
int numCharsUsed = messageInfoString.length(); // draft, number drafts,
@@ -294,7 +292,8 @@ public class SendersView {
final String currentName = currentParticipant.name;
String nameString = !TextUtils.isEmpty(currentName) ? currentName : "";
if (nameString.length() == 0) {
- nameString = getMe(context);
+ // if we're showing the To: header, show the object version of me.
+ nameString = getMe(showToHeader /* useObjectMe */);
}
if (numCharsToRemovePerWord != 0) {
nameString = nameString.substring(0,
@@ -302,7 +301,7 @@ public class SendersView {
}
final int priority = currentParticipant.priority;
- style = getWrappedStyleSpan(currentParticipant.readConversation ? readStyleSpan :
+ style = CharacterStyle.wrap(currentParticipant.readConversation ? readStyleSpan :
unreadStyleSpan);
if (priority <= maxPriorityToInclude) {
spannableDisplay = new SpannableString(sBidiFormatter.unicodeWrap(nameString));
@@ -372,19 +371,15 @@ public class SendersView {
}
}
- private static CharacterStyle getWrappedStyleSpan(final CharacterStyle characterStyle) {
- return CharacterStyle.wrap(characterStyle);
+ static String getMe(boolean useObjectMe) {
+ return useObjectMe ? sMeObjectString : sMeSubjectString;
}
- static String getMe(Context context) {
- final Resources resources = context.getResources();
- final Locale locale = resources.getConfiguration().locale;
-
- if (sMeString == null || !locale.equals(sMeStringLocale)) {
- sMeString = resources.getString(R.string.me_subject_pronun);
- sMeStringLocale = locale;
- }
- return sMeString;
+ public static SpannableString getFormattedToHeader() {
+ final SpannableString formattedToHeader = new SpannableString(sToHeaderString);
+ final CharacterStyle readStyle = CharacterStyle.wrap(sReadStyleSpan);
+ formattedToHeader.setSpan(readStyle, 0, formattedToHeader.length(), 0);
+ return formattedToHeader;
}
private static void clearResourceCache() {
diff --git a/src/com/android/mail/providers/Folder.java b/src/com/android/mail/providers/Folder.java
index 6d620d6de..57cfa451f 100644
--- a/src/com/android/mail/providers/Folder.java
+++ b/src/com/android/mail/providers/Folder.java
@@ -760,6 +760,20 @@ public class Folder implements Parcelable, Comparable<Folder> {
}
/**
+ * Return true if this folder prefers to display recipients over senders.
+ */
+ public boolean shouldShowRecipients() {
+ return supportsCapability(UIProvider.FolderCapabilities.SHOW_RECIPIENTS);
+ }
+
+ /**
+ * Return true if this folder prefers to display recipients over senders.
+ */
+ public static boolean shouldShowRecipients(final int folderCapabilities) {
+ return (folderCapabilities & UIProvider.FolderCapabilities.SHOW_RECIPIENTS) != 0;
+ }
+
+ /**
* @return a non-user facing English string describing this folder's type
*/
public String getTypeDescription() {
diff --git a/src/com/android/mail/providers/UIProvider.java b/src/com/android/mail/providers/UIProvider.java
index d37a083e1..9bcacccbd 100644
--- a/src/com/android/mail/providers/UIProvider.java
+++ b/src/com/android/mail/providers/UIProvider.java
@@ -857,6 +857,12 @@ public class UIProvider {
* inbox.
*/
public static final int ALLOWS_MOVE_TO_INBOX = 0x10000;
+
+ /**
+ * For folders that typically represent outgoing mail, this indicates the client should
+ * display recipients rather than the standard list of senders.
+ */
+ public static final int SHOW_RECIPIENTS = 0x20000;
}
public static final class FolderColumns implements BaseColumns {
diff --git a/src/com/android/mail/ui/FolderSelectionActivity.java b/src/com/android/mail/ui/FolderSelectionActivity.java
index 06bf6ab71..76e2af356 100644
--- a/src/com/android/mail/ui/FolderSelectionActivity.java
+++ b/src/com/android/mail/ui/FolderSelectionActivity.java
@@ -247,8 +247,8 @@ public class FolderSelectionActivity extends Activity implements OnClickListener
*/
protected void createWidget(int id, Account account, Folder selectedFolder) {
WidgetProvider.updateWidget(this, id, account, selectedFolder.type,
- selectedFolder.folderUri.fullUri, selectedFolder.conversationListUri,
- selectedFolder.name);
+ selectedFolder.capabilities, selectedFolder.folderUri.fullUri,
+ selectedFolder.conversationListUri, selectedFolder.name);
final Intent result = new Intent();
result.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, id);
setResult(RESULT_OK, result);
diff --git a/src/com/android/mail/utils/NotificationUtils.java b/src/com/android/mail/utils/NotificationUtils.java
index 09879b0e5..8f9498c4c 100644
--- a/src/com/android/mail/utils/NotificationUtils.java
+++ b/src/com/android/mail/utils/NotificationUtils.java
@@ -1171,7 +1171,8 @@ public class NotificationUtils {
new TextAppearanceSpan(context, R.style.NotificationSendersReadTextAppearance);
}
SendersView.format(context, conversationInfo, "", maxLength, senders, null, null, account,
- sNotificationUnreadStyleSpan, sNotificationReadStyleSpan, false);
+ sNotificationUnreadStyleSpan, sNotificationReadStyleSpan,
+ false /* showToHeader */, false /* resourceCachingRequired */);
return ellipsizeStyledSenders(context, senders);
}
diff --git a/src/com/android/mail/widget/BaseWidgetProvider.java b/src/com/android/mail/widget/BaseWidgetProvider.java
index d53256703..6b969d2ba 100644
--- a/src/com/android/mail/widget/BaseWidgetProvider.java
+++ b/src/com/android/mail/widget/BaseWidgetProvider.java
@@ -49,6 +49,7 @@ import java.util.Set;
public abstract class BaseWidgetProvider extends AppWidgetProvider {
public static final String EXTRA_FOLDER_TYPE = "folder-type";
+ public static final String EXTRA_FOLDER_CAPABILITIES = "folder-capabilities";
public static final String EXTRA_FOLDER_URI = "folder-uri";
public static final String EXTRA_FOLDER_CONVERSATION_LIST_URI = "folder-conversation-list-uri";
public static final String EXTRA_FOLDER_DISPLAY_NAME = "folder-display-name";
@@ -129,14 +130,15 @@ public abstract class BaseWidgetProvider extends AppWidgetProvider {
final int widgetId = intent.getIntExtra(EXTRA_WIDGET_ID, -1);
final Account account = Account.newInstance(intent.getStringExtra(Utils.EXTRA_ACCOUNT));
final int folderType = intent.getIntExtra(EXTRA_FOLDER_TYPE, FolderType.DEFAULT);
+ final int folderCapabilities = intent.getIntExtra(EXTRA_FOLDER_CAPABILITIES, 0);
final Uri folderUri = intent.getParcelableExtra(EXTRA_FOLDER_URI);
final Uri folderConversationListUri =
intent.getParcelableExtra(EXTRA_FOLDER_CONVERSATION_LIST_URI);
final String folderDisplayName = intent.getStringExtra(EXTRA_FOLDER_DISPLAY_NAME);
if (widgetId != -1 && account != null && folderUri != null) {
- updateWidgetInternal(context, widgetId, account, folderType, folderUri,
- folderConversationListUri, folderDisplayName);
+ updateWidgetInternal(context, widgetId, account, folderType, folderCapabilities,
+ folderUri, folderConversationListUri, folderDisplayName);
}
} else if (ACTION_VALIDATE_ALL_WIDGETS.equals(action)) {
validateAllWidgetInformation(context);
@@ -253,9 +255,11 @@ public abstract class BaseWidgetProvider extends AppWidgetProvider {
}
updateWidgetInternal(mContext, mAppWidgetIds[i], account,
- folder == null ? FolderType.DEFAULT : folder.type, folderUri,
- folder == null ? null : folder.conversationListUri, folder == null ? null
- : folder.name);
+ folder == null ? FolderType.DEFAULT : folder.type,
+ folder == null ? 0 : folder.capabilities,
+ folderUri,
+ folder == null ? null : folder.conversationListUri,
+ folder == null ? null : folder.name);
}
return null;
@@ -287,8 +291,8 @@ public abstract class BaseWidgetProvider extends AppWidgetProvider {
* Update the widget appWidgetId with the given account and folder
*/
public static void updateWidget(Context context, int appWidgetId, Account account,
- final int folderType, final Uri folderUri, final Uri folderConversationListUri,
- final String folderDisplayName) {
+ final int folderType, final int folderCapabilities, final Uri folderUri,
+ final Uri folderConversationListUri, final String folderDisplayName) {
if (account == null || folderUri == null) {
LogUtils.e(LOG_TAG,
"Missing account or folder. account: %s folder %s", account, folderUri);
@@ -300,6 +304,7 @@ public abstract class BaseWidgetProvider extends AppWidgetProvider {
updateWidgetIntent.putExtra(EXTRA_WIDGET_ID, appWidgetId);
updateWidgetIntent.putExtra(Utils.EXTRA_ACCOUNT, account.serialize());
updateWidgetIntent.putExtra(EXTRA_FOLDER_TYPE, folderType);
+ updateWidgetIntent.putExtra(EXTRA_FOLDER_CAPABILITIES, folderCapabilities);
updateWidgetIntent.putExtra(EXTRA_FOLDER_URI, folderUri);
updateWidgetIntent.putExtra(EXTRA_FOLDER_CONVERSATION_LIST_URI, folderConversationListUri);
updateWidgetIntent.putExtra(EXTRA_FOLDER_DISPLAY_NAME, folderDisplayName);
@@ -314,8 +319,8 @@ public abstract class BaseWidgetProvider extends AppWidgetProvider {
}
protected void updateWidgetInternal(Context context, int appWidgetId, Account account,
- final int folderType, final Uri folderUri, final Uri folderConversationListUri,
- final String folderDisplayName) {
+ final int folderType, final int folderCapabilities, final Uri folderUri,
+ final Uri folderConversationListUri, final String folderDisplayName) {
final RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.widget);
if (!isAccountValid(context, account) || !isFolderValid(context, folderUri)) {
@@ -342,7 +347,7 @@ public abstract class BaseWidgetProvider extends AppWidgetProvider {
} else {
// Set folder to a space here to avoid flicker.
configureValidAccountWidget(context, remoteViews, appWidgetId, account, folderType,
- folderUri, folderConversationListUri,
+ folderCapabilities, folderUri, folderConversationListUri,
folderDisplayName == null ? " " : folderDisplayName);
}
@@ -379,10 +384,10 @@ public abstract class BaseWidgetProvider extends AppWidgetProvider {
}
protected void configureValidAccountWidget(Context context, RemoteViews remoteViews,
- int appWidgetId, Account account, final int folderType, final Uri folderUri,
- final Uri folderConversationListUri, String folderDisplayName) {
+ int appWidgetId, Account account, final int folderType, final int folderCapabilities,
+ final Uri folderUri, final Uri folderConversationListUri, String folderDisplayName) {
WidgetService.configureValidAccountWidget(context, remoteViews, appWidgetId, account,
- folderType, folderUri, folderConversationListUri, folderDisplayName,
+ folderType, folderCapabilities, folderUri, folderConversationListUri, folderDisplayName,
WidgetService.class);
}
@@ -426,7 +431,8 @@ public abstract class BaseWidgetProvider extends AppWidgetProvider {
// unconfigure the widget if it is not valid
if (!isAccountValid(context, account) || !isFolderValid(context, folderUri)) {
- updateWidgetInternal(context, widgetId, null, FolderType.DEFAULT, null, null, null);
+ updateWidgetInternal(context, widgetId, null, FolderType.DEFAULT, 0, null, null,
+ null);
}
}
}
diff --git a/src/com/android/mail/widget/WidgetService.java b/src/com/android/mail/widget/WidgetService.java
index fab5efaa6..f0624ad28 100644
--- a/src/com/android/mail/widget/WidgetService.java
+++ b/src/com/android/mail/widget/WidgetService.java
@@ -32,7 +32,6 @@ import android.text.SpannableStringBuilder;
import android.text.TextUtils;
import android.text.format.DateUtils;
import android.text.style.CharacterStyle;
-import android.text.style.TextAppearanceSpan;
import android.view.View;
import android.widget.RemoteViews;
import android.widget.RemoteViewsService;
@@ -48,13 +47,14 @@ import com.android.mail.providers.UIProvider;
import com.android.mail.providers.UIProvider.ConversationListQueryParameters;
import com.android.mail.providers.UIProvider.FolderType;
import com.android.mail.utils.AccountUtils;
-import com.android.mail.utils.FolderUri;
import com.android.mail.utils.DelayedTaskHandler;
+import com.android.mail.utils.FolderUri;
import com.android.mail.utils.LogTag;
import com.android.mail.utils.LogUtils;
import com.android.mail.utils.Utils;
import java.util.ArrayList;
+import java.util.List;
public class WidgetService extends RemoteViewsService {
/**
@@ -70,18 +70,20 @@ public class WidgetService extends RemoteViewsService {
}
protected void configureValidAccountWidget(Context context, RemoteViews remoteViews,
- int appWidgetId, Account account, final int folderType, final Uri folderUri,
- final Uri folderConversationListUri, String folderName) {
+ int appWidgetId, Account account, final int folderType, final int folderCapabilities,
+ final Uri folderUri, final Uri folderConversationListUri, String folderName) {
configureValidAccountWidget(context, remoteViews, appWidgetId, account, folderType,
- folderUri, folderConversationListUri, folderName, WidgetService.class);
+ folderCapabilities, folderUri, folderConversationListUri, folderName,
+ WidgetService.class);
}
/**
* Modifies the remoteView for the given account and folder.
*/
public static void configureValidAccountWidget(Context context, RemoteViews remoteViews,
- int appWidgetId, Account account, final int folderType, final Uri folderUri,
- final Uri folderConversationListUri, String folderDisplayName, Class<?> widgetService) {
+ int appWidgetId, Account account, final int folderType, final int folderCapabilities,
+ final Uri folderUri, final Uri folderConversationListUri, String folderDisplayName,
+ Class<?> widgetService) {
remoteViews.setViewVisibility(R.id.widget_folder, View.VISIBLE);
// If the folder or account name are empty, we don't want to overwrite the valid data that
@@ -111,13 +113,14 @@ public class WidgetService extends RemoteViewsService {
remoteViews.setEmptyView(R.id.conversation_list, R.id.empty_conversation_list);
WidgetService.configureValidWidgetIntents(context, remoteViews, appWidgetId, account,
- folderType, folderUri, folderConversationListUri, folderDisplayName, widgetService);
+ folderType, folderCapabilities, folderUri, folderConversationListUri,
+ folderDisplayName, widgetService);
}
public static void configureValidWidgetIntents(Context context, RemoteViews remoteViews,
- int appWidgetId, Account account, final int folderType, final Uri folderUri,
- final Uri folderConversationListUri, final String folderDisplayName,
- Class<?> serviceClass) {
+ int appWidgetId, Account account, final int folderType, final int folderCapabilities,
+ final Uri folderUri, final Uri folderConversationListUri,
+ final String folderDisplayName, Class<?> serviceClass) {
remoteViews.setViewVisibility(R.id.widget_configuration, View.GONE);
@@ -126,6 +129,7 @@ public class WidgetService extends RemoteViewsService {
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
intent.putExtra(Utils.EXTRA_ACCOUNT, account.serialize());
intent.putExtra(BaseWidgetProvider.EXTRA_FOLDER_TYPE, folderType);
+ intent.putExtra(BaseWidgetProvider.EXTRA_FOLDER_CAPABILITIES, folderCapabilities);
intent.putExtra(BaseWidgetProvider.EXTRA_FOLDER_URI, folderUri);
intent.putExtra(BaseWidgetProvider.EXTRA_FOLDER_CONVERSATION_LIST_URI,
folderConversationListUri);
@@ -208,6 +212,7 @@ public class WidgetService extends RemoteViewsService {
private final int mAppWidgetId;
private final Account mAccount;
private final int mFolderType;
+ private final int mFolderCapabilities;
private final Uri mFolderUri;
private final Uri mFolderConversationListUri;
private final String mFolderDisplayName;
@@ -223,8 +228,6 @@ public class WidgetService extends RemoteViewsService {
private final WidgetService mService;
private String mSendersSplitToken;
private String mElidedPaddingToken;
- private TextAppearanceSpan mUnreadStyle;
- private TextAppearanceSpan mReadStyle;
public MailFactory(Context context, Intent intent, WidgetService service) {
mContext = context;
@@ -232,6 +235,7 @@ public class WidgetService extends RemoteViewsService {
AppWidgetManager.EXTRA_APPWIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID);
mAccount = Account.newInstance(intent.getStringExtra(Utils.EXTRA_ACCOUNT));
mFolderType = intent.getIntExtra(WidgetProvider.EXTRA_FOLDER_TYPE, FolderType.DEFAULT);
+ mFolderCapabilities = intent.getIntExtra(WidgetProvider.EXTRA_FOLDER_CAPABILITIES, 0);
mFolderDisplayName = intent.getStringExtra(WidgetProvider.EXTRA_FOLDER_DISPLAY_NAME);
final Uri folderUri = intent.getParcelableExtra(WidgetProvider.EXTRA_FOLDER_URI);
@@ -253,7 +257,8 @@ public class WidgetService extends RemoteViewsService {
mFolderConversationListUri = Uri.EMPTY;
// this will mark the widget as unconfigured
BaseWidgetProvider.updateWidget(mContext, mAppWidgetId, mAccount, mFolderType,
- mFolderUri, mFolderConversationListUri, mFolderDisplayName);
+ mFolderCapabilities, mFolderUri, mFolderConversationListUri,
+ mFolderDisplayName);
}
}
@@ -271,7 +276,8 @@ public class WidgetService extends RemoteViewsService {
// "Tap to configure" mode.
if (!mService.isWidgetConfigured(mContext, mAppWidgetId, mAccount)) {
BaseWidgetProvider.updateWidget(mContext, mAppWidgetId, mAccount, mFolderType,
- mFolderUri, mFolderConversationListUri, mFolderDisplayName);
+ mFolderCapabilities, mFolderUri, mFolderConversationListUri,
+ mFolderDisplayName);
}
mFolderInformationShown = false;
@@ -405,12 +411,12 @@ public class WidgetService extends RemoteViewsService {
Conversation conversation = new Conversation(mConversationCursor);
// Split the senders and status from the instructions.
- SpannableStringBuilder senderBuilder = new SpannableStringBuilder();
ArrayList<SpannableString> senders = new ArrayList<SpannableString>();
SendersView.format(mContext, conversation.conversationInfo, "",
- MAX_SENDERS_LENGTH, senders, null, null, mAccount.getEmailAddress(), true);
- senderBuilder = ellipsizeStyledSenders(senders);
+ MAX_SENDERS_LENGTH, senders, null, null, mAccount.getEmailAddress(),
+ Folder.shouldShowRecipients(mFolderCapabilities), true);
+ final SpannableStringBuilder senderBuilder = elideParticipants(senders);
// Get styled date.
CharSequence date = DateUtils.getRelativeTimeSpanString(mContext,
@@ -437,11 +443,19 @@ public class WidgetService extends RemoteViewsService {
}
}
- private SpannableStringBuilder ellipsizeStyledSenders(
- ArrayList<SpannableString> styledSenders) {
- SpannableStringBuilder builder = new SpannableStringBuilder();
+ private SpannableStringBuilder elideParticipants(List<SpannableString> parts) {
+ final SpannableStringBuilder builder = new SpannableStringBuilder();
SpannableString prevSender = null;
- for (SpannableString sender : styledSenders) {
+
+ boolean skipToHeader = false;
+
+ // start with "To: " if we're showing recipients
+ if (Folder.shouldShowRecipients(mFolderCapabilities)) {
+ builder.append(SendersView.getFormattedToHeader());
+ skipToHeader = true;
+ }
+
+ for (SpannableString sender : parts) {
if (sender == null) {
LogUtils.e(LOG_TAG, "null sender while iterating over styledSenders");
continue;
@@ -450,13 +464,14 @@ public class WidgetService extends RemoteViewsService {
if (SendersView.sElidedString.equals(sender.toString())) {
prevSender = sender;
sender = copyStyles(spans, mElidedPaddingToken + sender + mElidedPaddingToken);
- } else if (builder.length() > 0
+ } else if (!skipToHeader && builder.length() > 0
&& (prevSender == null || !SendersView.sElidedString.equals(prevSender
.toString()))) {
prevSender = sender;
sender = copyStyles(spans, mSendersSplitToken + sender);
} else {
prevSender = sender;
+ skipToHeader = false;
}
builder.append(sender);
}
@@ -514,14 +529,16 @@ public class WidgetService extends RemoteViewsService {
if (!mService.isWidgetConfigured(mContext, mAppWidgetId, mAccount)) {
BaseWidgetProvider.updateWidget(mContext, mAppWidgetId, mAccount, mFolderType,
- mFolderUri, mFolderConversationListUri, mFolderDisplayName);
+ mFolderCapabilities, mFolderUri, mFolderConversationListUri,
+ mFolderDisplayName);
}
if (loader == mFolderLoader) {
if (!isDataValid(data)) {
// Our folder may have disappeared on us
BaseWidgetProvider.updateWidget(mContext, mAppWidgetId, mAccount, mFolderType,
- mFolderUri, mFolderConversationListUri, mFolderDisplayName);
+ mFolderCapabilities, mFolderUri, mFolderConversationListUri,
+ mFolderDisplayName);
return;
}
@@ -537,8 +554,8 @@ public class WidgetService extends RemoteViewsService {
// widget update. This causes the folder name to be shown as blank if the state
// of the widget is restored.
mService.configureValidAccountWidget(mContext, remoteViews, mAppWidgetId,
- mAccount, mFolderType, mFolderUri, mFolderConversationListUri,
- folderName);
+ mAccount, mFolderType, mFolderCapabilities, mFolderUri,
+ mFolderConversationListUri, folderName);
appWidgetManager.updateAppWidget(mAppWidgetId, remoteViews);
mFolderInformationShown = true;
}
@@ -591,7 +608,8 @@ public class WidgetService extends RemoteViewsService {
}
} else if (loader == mAccountLoader) {
BaseWidgetProvider.updateWidget(mContext, mAppWidgetId, mAccount, mFolderType,
- mFolderUri, mFolderConversationListUri, mFolderDisplayName);
+ mFolderCapabilities, mFolderUri, mFolderConversationListUri,
+ mFolderDisplayName);
}
}
diff --git a/tests/src/com/android/mail/browse/SendersFormattingTests.java b/tests/src/com/android/mail/browse/SendersFormattingTests.java
index 4a072c3fa..ecec4dfac 100644
--- a/tests/src/com/android/mail/browse/SendersFormattingTests.java
+++ b/tests/src/com/android/mail/browse/SendersFormattingTests.java
@@ -40,7 +40,7 @@ public class SendersFormattingTests extends AndroidTestCase {
final ArrayList<SpannableString> strings = Lists.newArrayList();
assertEquals(0, strings.size());
- SendersView.format(getContext(), conv, "", 100, strings, null, null, null, false);
+ SendersView.format(getContext(), conv, "", 100, strings, null, null, null, false, false);
assertEquals(1, strings.size());
assertEquals("me", strings.get(0).toString());
}
@@ -51,7 +51,7 @@ public class SendersFormattingTests extends AndroidTestCase {
final ArrayList<SpannableString> strings = Lists.newArrayList();
assertEquals(0, strings.size());
- SendersView.format(getContext(), conv, "", 100, strings, null, null, null, false);
+ SendersView.format(getContext(), conv, "", 100, strings, null, null, null, false, false);
assertEquals(1, strings.size());
assertEquals("me", strings.get(0).toString());
}
@@ -63,7 +63,7 @@ public class SendersFormattingTests extends AndroidTestCase {
final ArrayList<SpannableString> strings = Lists.newArrayList();
assertEquals(0, strings.size());
- SendersView.format(getContext(), conv, "", 100, strings, null, null, null, false);
+ SendersView.format(getContext(), conv, "", 100, strings, null, null, null, false, false);
assertEquals(2, strings.size());
assertNull(strings.get(0));
assertEquals("me", strings.get(1).toString());
@@ -77,7 +77,7 @@ public class SendersFormattingTests extends AndroidTestCase {
final ArrayList<SpannableString> strings = Lists.newArrayList();
assertEquals(0, strings.size());
- SendersView.format(getContext(), conv, "", 100, strings, null, null, null, false);
+ SendersView.format(getContext(), conv, "", 100, strings, null, null, null, false, false);
assertEquals(2, strings.size());
assertNull(strings.get(0));
assertEquals("Something", strings.get(1).toString());