18eb43be8074acb4e09da1385225fbb41c97b1bd5Mindy Pereira/* 28eb43be8074acb4e09da1385225fbb41c97b1bd5Mindy Pereira * Copyright (C) 2012 Google Inc. 38eb43be8074acb4e09da1385225fbb41c97b1bd5Mindy Pereira * Licensed to The Android Open Source Project. 48eb43be8074acb4e09da1385225fbb41c97b1bd5Mindy Pereira * 58eb43be8074acb4e09da1385225fbb41c97b1bd5Mindy Pereira * Licensed under the Apache License, Version 2.0 (the "License"); 68eb43be8074acb4e09da1385225fbb41c97b1bd5Mindy Pereira * you may not use this file except in compliance with the License. 78eb43be8074acb4e09da1385225fbb41c97b1bd5Mindy Pereira * You may obtain a copy of the License at 88eb43be8074acb4e09da1385225fbb41c97b1bd5Mindy Pereira * 98eb43be8074acb4e09da1385225fbb41c97b1bd5Mindy Pereira * http://www.apache.org/licenses/LICENSE-2.0 108eb43be8074acb4e09da1385225fbb41c97b1bd5Mindy Pereira * 118eb43be8074acb4e09da1385225fbb41c97b1bd5Mindy Pereira * Unless required by applicable law or agreed to in writing, software 128eb43be8074acb4e09da1385225fbb41c97b1bd5Mindy Pereira * distributed under the License is distributed on an "AS IS" BASIS, 138eb43be8074acb4e09da1385225fbb41c97b1bd5Mindy Pereira * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 148eb43be8074acb4e09da1385225fbb41c97b1bd5Mindy Pereira * See the License for the specific language governing permissions and 158eb43be8074acb4e09da1385225fbb41c97b1bd5Mindy Pereira * limitations under the License. 168eb43be8074acb4e09da1385225fbb41c97b1bd5Mindy Pereira */ 178eb43be8074acb4e09da1385225fbb41c97b1bd5Mindy Pereira 188eb43be8074acb4e09da1385225fbb41c97b1bd5Mindy Pereirapackage com.android.mail.browse; 198eb43be8074acb4e09da1385225fbb41c97b1bd5Mindy Pereira 2077d7f3c3c8c82048b51025428a825f6ac71e8560Mindy Pereiraimport android.content.BroadcastReceiver; 218eb43be8074acb4e09da1385225fbb41c97b1bd5Mindy Pereiraimport android.content.Context; 2277d7f3c3c8c82048b51025428a825f6ac71e8560Mindy Pereiraimport android.content.Intent; 2377d7f3c3c8c82048b51025428a825f6ac71e8560Mindy Pereiraimport android.content.IntentFilter; 24b1cbb89f72631bb7e34822b98e8d0842ebd01b83Mindy Pereiraimport android.content.res.Resources; 258eb43be8074acb4e09da1385225fbb41c97b1bd5Mindy Pereiraimport android.graphics.Typeface; 268173cf41d2acf48c7b45ae3e7868fc391aae0359Andrew Sappersteinimport android.support.v4.text.BidiFormatter; 27b1207e3ec8fe3ce988996722e13b80a4dfdf1c72Mindy Pereiraimport android.text.SpannableString; 28b1cbb89f72631bb7e34822b98e8d0842ebd01b83Mindy Pereiraimport android.text.SpannableStringBuilder; 2942b362587928704ea17b0a09a5e4e16037d14491Jin Caoimport android.text.Spanned; 308eb43be8074acb4e09da1385225fbb41c97b1bd5Mindy Pereiraimport android.text.TextUtils; 318eb43be8074acb4e09da1385225fbb41c97b1bd5Mindy Pereiraimport android.text.style.CharacterStyle; 32172f56a81bba3b2589026c7cded795010e7678adMindy Pereiraimport android.text.style.TextAppearanceSpan; 338eb43be8074acb4e09da1385225fbb41c97b1bd5Mindy Pereira 34b9c036b36542924894f141e3ecd81381a12e94a9Mindy Pereiraimport com.android.mail.R; 35c9e00fcb05c5311633dc3a414b9bf685816b4350James Lemieuximport com.android.mail.providers.Account; 36b821e306583115e5fce8a8f0383019ae6268b1ccMindy Pereiraimport com.android.mail.providers.Conversation; 37571de2212f311cc4a514ffa74e7585a2df1fb907Mindy Pereiraimport com.android.mail.providers.ConversationInfo; 383b59b333ad0693f74f9a8cfb24a468a8acbaca8cJames Lemieuximport com.android.mail.providers.ParticipantInfo; 39b821e306583115e5fce8a8f0383019ae6268b1ccMindy Pereiraimport com.android.mail.providers.UIProvider; 40949ea2185d79e3e266662766cfa07cf748493e3aPaul Westbrookimport com.android.mail.utils.ObjectCache; 41c76ab94c69e09ade8036f47d370d56902f0e1f6emindypimport com.google.common.base.Objects; 423dbfbc210a607382ba9c150d7ae373ca0508267cJin Caoimport com.google.common.collect.Lists; 43b1cbb89f72631bb7e34822b98e8d0842ebd01b83Mindy Pereiraimport com.google.common.collect.Maps; 44b9c036b36542924894f141e3ecd81381a12e94a9Mindy Pereira 45d8e5ff44a8a7405bb8891fb46570782138babbd1Mindy Pereiraimport java.util.ArrayList; 463dbfbc210a607382ba9c150d7ae373ca0508267cJin Caoimport java.util.List; 47b1cbb89f72631bb7e34822b98e8d0842ebd01b83Mindy Pereiraimport java.util.Map; 488eb43be8074acb4e09da1385225fbb41c97b1bd5Mindy Pereira 4977d7f3c3c8c82048b51025428a825f6ac71e8560Mindy Pereirapublic class SendersView { 503dbfbc210a607382ba9c150d7ae373ca0508267cJin Cao /** The maximum number of senders to display for a given conversation */ 513dbfbc210a607382ba9c150d7ae373ca0508267cJin Cao private static final int MAX_SENDER_COUNT = 4; 523dbfbc210a607382ba9c150d7ae373ca0508267cJin Cao 5305448212df93567d8ba222b792dd90fd2225fd3dMindy Pereira private static final Integer DOES_NOT_EXIST = -5; 54bcab7611959549a955be8a30115d6a4c937afd24Andy Huang // FIXME(ath): make all of these statics instance variables, and have callers hold onto this 55bcab7611959549a955be8a30115d6a4c937afd24Andy Huang // instance as long as appropriate (e.g. activity lifetime). 56bcab7611959549a955be8a30115d6a4c937afd24Andy Huang // no need to listen for configuration changes. 57b1cbb89f72631bb7e34822b98e8d0842ebd01b83Mindy Pereira private static String sSendersSplitToken; 58b1cbb89f72631bb7e34822b98e8d0842ebd01b83Mindy Pereira private static CharSequence sDraftSingularString; 59b1cbb89f72631bb7e34822b98e8d0842ebd01b83Mindy Pereira private static CharSequence sDraftPluralString; 60b821e306583115e5fce8a8f0383019ae6268b1ccMindy Pereira private static CharSequence sSendingString; 616a2df258316b267151296556dbbdba20200ecb1fJin Cao private static CharSequence sRetryingString; 626a2df258316b267151296556dbbdba20200ecb1fJin Cao private static CharSequence sFailedString; 63b1cbb89f72631bb7e34822b98e8d0842ebd01b83Mindy Pereira private static String sDraftCountFormatString; 64172f56a81bba3b2589026c7cded795010e7678adMindy Pereira private static CharacterStyle sDraftsStyleSpan; 65b821e306583115e5fce8a8f0383019ae6268b1ccMindy Pereira private static CharacterStyle sSendingStyleSpan; 666a2df258316b267151296556dbbdba20200ecb1fJin Cao private static CharacterStyle sRetryingStyleSpan; 676a2df258316b267151296556dbbdba20200ecb1fJin Cao private static CharacterStyle sFailedStyleSpan; 686a4c4f62db0ddf6660d889bf1f21e37d25a99363mindyp private static TextAppearanceSpan sUnreadStyleSpan; 69172f56a81bba3b2589026c7cded795010e7678adMindy Pereira private static CharacterStyle sReadStyleSpan; 7010ea28ab588d8e922c0f78f0f47fe479739ec2cfJames Lemieux private static String sMeSubjectString; 7110ea28ab588d8e922c0f78f0f47fe479739ec2cfJames Lemieux private static String sMeObjectString; 7210ea28ab588d8e922c0f78f0f47fe479739ec2cfJames Lemieux private static String sToHeaderString; 730c2e567e792d557de1d80ef25f82aaf3c41c22b6Mindy Pereira private static String sMessageCountSpacerString; 74b1cbb89f72631bb7e34822b98e8d0842ebd01b83Mindy Pereira public static CharSequence sElidedString; 7577d7f3c3c8c82048b51025428a825f6ac71e8560Mindy Pereira private static BroadcastReceiver sConfigurationChangedReceiver; 7695f9e1b167f4945adfa4ca62f4b72a102b621794mindyp private static TextAppearanceSpan sMessageInfoReadStyleSpan; 7795f9e1b167f4945adfa4ca62f4b72a102b621794mindyp private static TextAppearanceSpan sMessageInfoUnreadStyleSpan; 788173cf41d2acf48c7b45ae3e7868fc391aae0359Andrew Sapperstein private static BidiFormatter sBidiFormatter; 798eb43be8074acb4e09da1385225fbb41c97b1bd5Mindy Pereira 80949ea2185d79e3e266662766cfa07cf748493e3aPaul Westbrook // We only want to have at most 2 Priority to length maps. This will handle the case where 81949ea2185d79e3e266662766cfa07cf748493e3aPaul Westbrook // there is a widget installed on the launcher while the user is scrolling in the app 82949ea2185d79e3e266662766cfa07cf748493e3aPaul Westbrook private static final int MAX_PRIORITY_LENGTH_MAP_LIST = 2; 83949ea2185d79e3e266662766cfa07cf748493e3aPaul Westbrook 84949ea2185d79e3e266662766cfa07cf748493e3aPaul Westbrook // Cache of priority to length maps. We can't just use a single instance as it may be 85949ea2185d79e3e266662766cfa07cf748493e3aPaul Westbrook // modified from different threads 86949ea2185d79e3e266662766cfa07cf748493e3aPaul Westbrook private static final ObjectCache<Map<Integer, Integer>> PRIORITY_LENGTH_MAP_CACHE = 87949ea2185d79e3e266662766cfa07cf748493e3aPaul Westbrook new ObjectCache<Map<Integer, Integer>>( 88949ea2185d79e3e266662766cfa07cf748493e3aPaul Westbrook new ObjectCache.Callback<Map<Integer, Integer>>() { 89949ea2185d79e3e266662766cfa07cf748493e3aPaul Westbrook @Override 90949ea2185d79e3e266662766cfa07cf748493e3aPaul Westbrook public Map<Integer, Integer> newInstance() { 91949ea2185d79e3e266662766cfa07cf748493e3aPaul Westbrook return Maps.newHashMap(); 92949ea2185d79e3e266662766cfa07cf748493e3aPaul Westbrook } 93949ea2185d79e3e266662766cfa07cf748493e3aPaul Westbrook @Override 94949ea2185d79e3e266662766cfa07cf748493e3aPaul Westbrook public void onObjectReleased(Map<Integer, Integer> object) { 95949ea2185d79e3e266662766cfa07cf748493e3aPaul Westbrook object.clear(); 96949ea2185d79e3e266662766cfa07cf748493e3aPaul Westbrook } 97949ea2185d79e3e266662766cfa07cf748493e3aPaul Westbrook }, MAX_PRIORITY_LENGTH_MAP_LIST); 98949ea2185d79e3e266662766cfa07cf748493e3aPaul Westbrook 9977d7f3c3c8c82048b51025428a825f6ac71e8560Mindy Pereira public static Typeface getTypeface(boolean isUnread) { 1007fad2fda87f86692fcba1314f01b56265de67f2eMindy Pereira return isUnread ? Typeface.DEFAULT_BOLD : Typeface.DEFAULT; 1018eb43be8074acb4e09da1385225fbb41c97b1bd5Mindy Pereira } 1028eb43be8074acb4e09da1385225fbb41c97b1bd5Mindy Pereira 103d5fd04656f364a209703a67debc33d91dabfb83fScott Kennedy private static synchronized void getSenderResources( 104d5fd04656f364a209703a67debc33d91dabfb83fScott Kennedy Context context, final boolean resourceCachingRequired) { 105d5fd04656f364a209703a67debc33d91dabfb83fScott Kennedy if (sConfigurationChangedReceiver == null && resourceCachingRequired) { 10677d7f3c3c8c82048b51025428a825f6ac71e8560Mindy Pereira sConfigurationChangedReceiver = new BroadcastReceiver() { 10777d7f3c3c8c82048b51025428a825f6ac71e8560Mindy Pereira @Override 10877d7f3c3c8c82048b51025428a825f6ac71e8560Mindy Pereira public void onReceive(Context context, Intent intent) { 10977d7f3c3c8c82048b51025428a825f6ac71e8560Mindy Pereira sDraftSingularString = null; 110d5fd04656f364a209703a67debc33d91dabfb83fScott Kennedy getSenderResources(context, true); 11177d7f3c3c8c82048b51025428a825f6ac71e8560Mindy Pereira } 11277d7f3c3c8c82048b51025428a825f6ac71e8560Mindy Pereira }; 11377d7f3c3c8c82048b51025428a825f6ac71e8560Mindy Pereira context.registerReceiver(sConfigurationChangedReceiver, new IntentFilter( 11477d7f3c3c8c82048b51025428a825f6ac71e8560Mindy Pereira Intent.ACTION_CONFIGURATION_CHANGED)); 11577d7f3c3c8c82048b51025428a825f6ac71e8560Mindy Pereira } 116b1cbb89f72631bb7e34822b98e8d0842ebd01b83Mindy Pereira if (sDraftSingularString == null) { 117b1cbb89f72631bb7e34822b98e8d0842ebd01b83Mindy Pereira Resources res = context.getResources(); 118b1cbb89f72631bb7e34822b98e8d0842ebd01b83Mindy Pereira sSendersSplitToken = res.getString(R.string.senders_split_token); 119b1cbb89f72631bb7e34822b98e8d0842ebd01b83Mindy Pereira sElidedString = res.getString(R.string.senders_elided); 120b1cbb89f72631bb7e34822b98e8d0842ebd01b83Mindy Pereira sDraftSingularString = res.getQuantityText(R.plurals.draft, 1); 121b1cbb89f72631bb7e34822b98e8d0842ebd01b83Mindy Pereira sDraftPluralString = res.getQuantityText(R.plurals.draft, 2); 122b1cbb89f72631bb7e34822b98e8d0842ebd01b83Mindy Pereira sDraftCountFormatString = res.getString(R.string.draft_count_format); 12310ea28ab588d8e922c0f78f0f47fe479739ec2cfJames Lemieux sMeSubjectString = res.getString(R.string.me_subject_pronoun); 12410ea28ab588d8e922c0f78f0f47fe479739ec2cfJames Lemieux sMeObjectString = res.getString(R.string.me_object_pronoun); 12510ea28ab588d8e922c0f78f0f47fe479739ec2cfJames Lemieux sToHeaderString = res.getString(R.string.to_heading); 12695f9e1b167f4945adfa4ca62f4b72a102b621794mindyp sMessageInfoUnreadStyleSpan = new TextAppearanceSpan(context, 12795f9e1b167f4945adfa4ca62f4b72a102b621794mindyp R.style.MessageInfoUnreadTextAppearance); 12895f9e1b167f4945adfa4ca62f4b72a102b621794mindyp sMessageInfoReadStyleSpan = new TextAppearanceSpan(context, 12995f9e1b167f4945adfa4ca62f4b72a102b621794mindyp R.style.MessageInfoReadTextAppearance); 130172f56a81bba3b2589026c7cded795010e7678adMindy Pereira sDraftsStyleSpan = new TextAppearanceSpan(context, R.style.DraftTextAppearance); 131f75cf1157b7168cd4c501b1b34ad473e2ab724f0James Lemieux sUnreadStyleSpan = new TextAppearanceSpan(context, R.style.SendersAppearanceUnreadStyle); 132b821e306583115e5fce8a8f0383019ae6268b1ccMindy Pereira sSendingStyleSpan = new TextAppearanceSpan(context, R.style.SendingTextAppearance); 1336a2df258316b267151296556dbbdba20200ecb1fJin Cao sRetryingStyleSpan = new TextAppearanceSpan(context, R.style.RetryingTextAppearance); 1346a2df258316b267151296556dbbdba20200ecb1fJin Cao sFailedStyleSpan = new TextAppearanceSpan(context, R.style.FailedTextAppearance); 135f75cf1157b7168cd4c501b1b34ad473e2ab724f0James Lemieux sReadStyleSpan = new TextAppearanceSpan(context, R.style.SendersAppearanceReadStyle); 1360c2e567e792d557de1d80ef25f82aaf3c41c22b6Mindy Pereira sMessageCountSpacerString = res.getString(R.string.message_count_spacer); 137b821e306583115e5fce8a8f0383019ae6268b1ccMindy Pereira sSendingString = res.getString(R.string.sending); 1386a2df258316b267151296556dbbdba20200ecb1fJin Cao sRetryingString = res.getString(R.string.message_retrying); 1396a2df258316b267151296556dbbdba20200ecb1fJin Cao sFailedString = res.getString(R.string.message_failed); 1408173cf41d2acf48c7b45ae3e7868fc391aae0359Andrew Sapperstein sBidiFormatter = BidiFormatter.getInstance(); 141b1cbb89f72631bb7e34822b98e8d0842ebd01b83Mindy Pereira } 142b1cbb89f72631bb7e34822b98e8d0842ebd01b83Mindy Pereira } 143b1cbb89f72631bb7e34822b98e8d0842ebd01b83Mindy Pereira 144d5fd04656f364a209703a67debc33d91dabfb83fScott Kennedy public static SpannableStringBuilder createMessageInfo(Context context, Conversation conv, 145d5fd04656f364a209703a67debc33d91dabfb83fScott Kennedy final boolean resourceCachingRequired) { 146b1cbb89f72631bb7e34822b98e8d0842ebd01b83Mindy Pereira SpannableStringBuilder messageInfo = new SpannableStringBuilder(); 147e22c41d168aebe3bba6781e0ef8f5a6cbe5e3686Scott Kennedy 148e22c41d168aebe3bba6781e0ef8f5a6cbe5e3686Scott Kennedy try { 14942b362587928704ea17b0a09a5e4e16037d14491Jin Cao final ConversationInfo conversationInfo = conv.conversationInfo; 15042b362587928704ea17b0a09a5e4e16037d14491Jin Cao final int sendingStatus = conv.sendingState; 151e22c41d168aebe3bba6781e0ef8f5a6cbe5e3686Scott Kennedy boolean hasSenders = false; 152e22c41d168aebe3bba6781e0ef8f5a6cbe5e3686Scott Kennedy // This covers the case where the sender is "me" and this is a draft 153e22c41d168aebe3bba6781e0ef8f5a6cbe5e3686Scott Kennedy // message, which means this will only run once most of the time. 1543b59b333ad0693f74f9a8cfb24a468a8acbaca8cJames Lemieux for (ParticipantInfo p : conversationInfo.participantInfos) { 1553b59b333ad0693f74f9a8cfb24a468a8acbaca8cJames Lemieux if (!TextUtils.isEmpty(p.name)) { 156e22c41d168aebe3bba6781e0ef8f5a6cbe5e3686Scott Kennedy hasSenders = true; 157e22c41d168aebe3bba6781e0ef8f5a6cbe5e3686Scott Kennedy break; 158e22c41d168aebe3bba6781e0ef8f5a6cbe5e3686Scott Kennedy } 159b1cbb89f72631bb7e34822b98e8d0842ebd01b83Mindy Pereira } 160e22c41d168aebe3bba6781e0ef8f5a6cbe5e3686Scott Kennedy getSenderResources(context, resourceCachingRequired); 16142b362587928704ea17b0a09a5e4e16037d14491Jin Cao final int count = conversationInfo.messageCount; 16242b362587928704ea17b0a09a5e4e16037d14491Jin Cao final int draftCount = conversationInfo.draftCount; 163edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler if (count > 1) { 16442b362587928704ea17b0a09a5e4e16037d14491Jin Cao appendMessageInfo(messageInfo, Integer.toString(count), CharacterStyle.wrap( 16542b362587928704ea17b0a09a5e4e16037d14491Jin Cao conv.read ? sMessageInfoReadStyleSpan : sMessageInfoUnreadStyleSpan), 16642b362587928704ea17b0a09a5e4e16037d14491Jin Cao false, conv.read); 167edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler } 16842b362587928704ea17b0a09a5e4e16037d14491Jin Cao 16942b362587928704ea17b0a09a5e4e16037d14491Jin Cao boolean appendSplitToken = hasSenders || count > 1; 170edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler if (draftCount > 0) { 17142b362587928704ea17b0a09a5e4e16037d14491Jin Cao final CharSequence draftText; 172edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler if (draftCount == 1) { 17342b362587928704ea17b0a09a5e4e16037d14491Jin Cao draftText = sDraftSingularString; 174edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler } else { 17542b362587928704ea17b0a09a5e4e16037d14491Jin Cao draftText = sDraftPluralString + 17642b362587928704ea17b0a09a5e4e16037d14491Jin Cao String.format(sDraftCountFormatString, draftCount); 177e22c41d168aebe3bba6781e0ef8f5a6cbe5e3686Scott Kennedy } 17842b362587928704ea17b0a09a5e4e16037d14491Jin Cao 17942b362587928704ea17b0a09a5e4e16037d14491Jin Cao appendMessageInfo(messageInfo, draftText, sDraftsStyleSpan, appendSplitToken, 18042b362587928704ea17b0a09a5e4e16037d14491Jin Cao conv.read); 181edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler } 1826a2df258316b267151296556dbbdba20200ecb1fJin Cao 18342b362587928704ea17b0a09a5e4e16037d14491Jin Cao final boolean showState = sendingStatus == UIProvider.ConversationSendingState.SENDING || 1846a2df258316b267151296556dbbdba20200ecb1fJin Cao sendingStatus == UIProvider.ConversationSendingState.RETRYING || 1856a2df258316b267151296556dbbdba20200ecb1fJin Cao sendingStatus == UIProvider.ConversationSendingState.SEND_ERROR; 1866a2df258316b267151296556dbbdba20200ecb1fJin Cao if (showState) { 18742b362587928704ea17b0a09a5e4e16037d14491Jin Cao appendSplitToken |= draftCount > 0; 1886a2df258316b267151296556dbbdba20200ecb1fJin Cao 18942b362587928704ea17b0a09a5e4e16037d14491Jin Cao final CharSequence statusText; 19042b362587928704ea17b0a09a5e4e16037d14491Jin Cao final Object span; 1916a2df258316b267151296556dbbdba20200ecb1fJin Cao if (sendingStatus == UIProvider.ConversationSendingState.SENDING) { 19242b362587928704ea17b0a09a5e4e16037d14491Jin Cao statusText = sSendingString; 19342b362587928704ea17b0a09a5e4e16037d14491Jin Cao span = sSendingStyleSpan; 1946a2df258316b267151296556dbbdba20200ecb1fJin Cao } else if (sendingStatus == UIProvider.ConversationSendingState.RETRYING) { 195ea61dab12099606a1d385e1003dde46bf0f47d4bJin Cao statusText = sSendingString; 196ea61dab12099606a1d385e1003dde46bf0f47d4bJin Cao span = sSendingStyleSpan; 19742b362587928704ea17b0a09a5e4e16037d14491Jin Cao } else { 19842b362587928704ea17b0a09a5e4e16037d14491Jin Cao statusText = sFailedString; 19942b362587928704ea17b0a09a5e4e16037d14491Jin Cao span = sFailedStyleSpan; 2006a2df258316b267151296556dbbdba20200ecb1fJin Cao } 20142b362587928704ea17b0a09a5e4e16037d14491Jin Cao 20242b362587928704ea17b0a09a5e4e16037d14491Jin Cao appendMessageInfo(messageInfo, statusText, span, appendSplitToken, conv.read); 203edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler } 2046a2df258316b267151296556dbbdba20200ecb1fJin Cao 205edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler // Prepend a space if we are showing other message info text. 2066a2df258316b267151296556dbbdba20200ecb1fJin Cao if (count > 1 || (draftCount > 0 && hasSenders) || showState) { 207edd6c1a2807d2ade930dfd4622707298dc470d64Tony Mantler messageInfo.insert(0, sMessageCountSpacerString); 208b821e306583115e5fce8a8f0383019ae6268b1ccMindy Pereira } 209e22c41d168aebe3bba6781e0ef8f5a6cbe5e3686Scott Kennedy } finally { 210e22c41d168aebe3bba6781e0ef8f5a6cbe5e3686Scott Kennedy if (!resourceCachingRequired) { 211e22c41d168aebe3bba6781e0ef8f5a6cbe5e3686Scott Kennedy clearResourceCache(); 212ae70f33c9db0e71e4ea67eaef892afb1546319a6mindyp } 213b1cbb89f72631bb7e34822b98e8d0842ebd01b83Mindy Pereira } 214d5fd04656f364a209703a67debc33d91dabfb83fScott Kennedy 215b1cbb89f72631bb7e34822b98e8d0842ebd01b83Mindy Pereira return messageInfo; 216b1cbb89f72631bb7e34822b98e8d0842ebd01b83Mindy Pereira } 21742b362587928704ea17b0a09a5e4e16037d14491Jin Cao 21842b362587928704ea17b0a09a5e4e16037d14491Jin Cao private static void appendMessageInfo(SpannableStringBuilder sb, CharSequence text, 21942b362587928704ea17b0a09a5e4e16037d14491Jin Cao Object span, boolean appendSplitToken, boolean convRead) { 22042b362587928704ea17b0a09a5e4e16037d14491Jin Cao int startIndex = sb.length(); 22142b362587928704ea17b0a09a5e4e16037d14491Jin Cao if (appendSplitToken) { 22242b362587928704ea17b0a09a5e4e16037d14491Jin Cao sb.append(sSendersSplitToken); 22342b362587928704ea17b0a09a5e4e16037d14491Jin Cao sb.setSpan(CharacterStyle.wrap(convRead ? 22442b362587928704ea17b0a09a5e4e16037d14491Jin Cao sMessageInfoReadStyleSpan : sMessageInfoUnreadStyleSpan), 22542b362587928704ea17b0a09a5e4e16037d14491Jin Cao startIndex, sb.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); 22642b362587928704ea17b0a09a5e4e16037d14491Jin Cao } 22742b362587928704ea17b0a09a5e4e16037d14491Jin Cao 22842b362587928704ea17b0a09a5e4e16037d14491Jin Cao startIndex = sb.length(); 22942b362587928704ea17b0a09a5e4e16037d14491Jin Cao sb.append(text); 23042b362587928704ea17b0a09a5e4e16037d14491Jin Cao sb.setSpan(span, startIndex, sb.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); 23142b362587928704ea17b0a09a5e4e16037d14491Jin Cao } 232b1cbb89f72631bb7e34822b98e8d0842ebd01b83Mindy Pereira 23388acafa03a87f5c84b959697d13b81df8f11a96emindyp public static void format(Context context, ConversationInfo conversationInfo, 23469495b0a5551aaf4b70b6b29348946b730cfc3e8mindyp String messageInfo, int maxChars, ArrayList<SpannableString> styledSenders, 2353dbfbc210a607382ba9c150d7ae373ca0508267cJin Cao ArrayList<String> displayableSenderNames, 2363dbfbc210a607382ba9c150d7ae373ca0508267cJin Cao ConversationItemViewModel.SenderAvatarModel senderAvatarModel, 237c9e00fcb05c5311633dc3a414b9bf685816b4350James Lemieux Account account, final boolean showToHeader, final boolean resourceCachingRequired) { 238e22c41d168aebe3bba6781e0ef8f5a6cbe5e3686Scott Kennedy try { 239e22c41d168aebe3bba6781e0ef8f5a6cbe5e3686Scott Kennedy getSenderResources(context, resourceCachingRequired); 240e22c41d168aebe3bba6781e0ef8f5a6cbe5e3686Scott Kennedy format(context, conversationInfo, messageInfo, maxChars, styledSenders, 2413dbfbc210a607382ba9c150d7ae373ca0508267cJin Cao displayableSenderNames, senderAvatarModel, account, 24210ea28ab588d8e922c0f78f0f47fe479739ec2cfJames Lemieux sUnreadStyleSpan, sReadStyleSpan, showToHeader, resourceCachingRequired); 243e22c41d168aebe3bba6781e0ef8f5a6cbe5e3686Scott Kennedy } finally { 244e22c41d168aebe3bba6781e0ef8f5a6cbe5e3686Scott Kennedy if (!resourceCachingRequired) { 245e22c41d168aebe3bba6781e0ef8f5a6cbe5e3686Scott Kennedy clearResourceCache(); 246e22c41d168aebe3bba6781e0ef8f5a6cbe5e3686Scott Kennedy } 247d5fd04656f364a209703a67debc33d91dabfb83fScott Kennedy } 248d25c753fd348cbd98a148e434134bbe2191aad7dScott Kennedy } 249d25c753fd348cbd98a148e434134bbe2191aad7dScott Kennedy 250d25c753fd348cbd98a148e434134bbe2191aad7dScott Kennedy public static void format(Context context, ConversationInfo conversationInfo, 251d25c753fd348cbd98a148e434134bbe2191aad7dScott Kennedy String messageInfo, int maxChars, ArrayList<SpannableString> styledSenders, 2523dbfbc210a607382ba9c150d7ae373ca0508267cJin Cao ArrayList<String> displayableSenderNames, 2533dbfbc210a607382ba9c150d7ae373ca0508267cJin Cao ConversationItemViewModel.SenderAvatarModel senderAvatarModel, 254c9e00fcb05c5311633dc3a414b9bf685816b4350James Lemieux Account account, final TextAppearanceSpan notificationUnreadStyleSpan, 25510ea28ab588d8e922c0f78f0f47fe479739ec2cfJames Lemieux final CharacterStyle notificationReadStyleSpan, final boolean showToHeader, 25610ea28ab588d8e922c0f78f0f47fe479739ec2cfJames Lemieux final boolean resourceCachingRequired) { 257e22c41d168aebe3bba6781e0ef8f5a6cbe5e3686Scott Kennedy try { 258e22c41d168aebe3bba6781e0ef8f5a6cbe5e3686Scott Kennedy getSenderResources(context, resourceCachingRequired); 25910ea28ab588d8e922c0f78f0f47fe479739ec2cfJames Lemieux handlePriority(maxChars, messageInfo, conversationInfo, styledSenders, 2603dbfbc210a607382ba9c150d7ae373ca0508267cJin Cao displayableSenderNames, senderAvatarModel, account, 26110ea28ab588d8e922c0f78f0f47fe479739ec2cfJames Lemieux notificationUnreadStyleSpan, notificationReadStyleSpan, showToHeader); 262e22c41d168aebe3bba6781e0ef8f5a6cbe5e3686Scott Kennedy } finally { 263e22c41d168aebe3bba6781e0ef8f5a6cbe5e3686Scott Kennedy if (!resourceCachingRequired) { 264e22c41d168aebe3bba6781e0ef8f5a6cbe5e3686Scott Kennedy clearResourceCache(); 265e22c41d168aebe3bba6781e0ef8f5a6cbe5e3686Scott Kennedy } 266d5fd04656f364a209703a67debc33d91dabfb83fScott Kennedy } 267b1cbb89f72631bb7e34822b98e8d0842ebd01b83Mindy Pereira } 268b1cbb89f72631bb7e34822b98e8d0842ebd01b83Mindy Pereira 26910ea28ab588d8e922c0f78f0f47fe479739ec2cfJames Lemieux private static void handlePriority(int maxChars, String messageInfoString, 27069495b0a5551aaf4b70b6b29348946b730cfc3e8mindyp ConversationInfo conversationInfo, ArrayList<SpannableString> styledSenders, 2713dbfbc210a607382ba9c150d7ae373ca0508267cJin Cao ArrayList<String> displayableSenderNames, 2723dbfbc210a607382ba9c150d7ae373ca0508267cJin Cao ConversationItemViewModel.SenderAvatarModel senderAvatarModel, 273c9e00fcb05c5311633dc3a414b9bf685816b4350James Lemieux Account account, final TextAppearanceSpan unreadStyleSpan, 27410ea28ab588d8e922c0f78f0f47fe479739ec2cfJames Lemieux final CharacterStyle readStyleSpan, final boolean showToHeader) { 2753dbfbc210a607382ba9c150d7ae373ca0508267cJin Cao final boolean shouldSelectSenders = displayableSenderNames != null; 2763dbfbc210a607382ba9c150d7ae373ca0508267cJin Cao final boolean shouldSelectAvatar = senderAvatarModel != null; 277b1cbb89f72631bb7e34822b98e8d0842ebd01b83Mindy Pereira int maxPriorityToInclude = -1; // inclusive 278b1cbb89f72631bb7e34822b98e8d0842ebd01b83Mindy Pereira int numCharsUsed = messageInfoString.length(); // draft, number drafts, 279b1cbb89f72631bb7e34822b98e8d0842ebd01b83Mindy Pereira // count 280b1cbb89f72631bb7e34822b98e8d0842ebd01b83Mindy Pereira int numSendersUsed = 0; 281b1cbb89f72631bb7e34822b98e8d0842ebd01b83Mindy Pereira int numCharsToRemovePerWord = 0; 282b1cbb89f72631bb7e34822b98e8d0842ebd01b83Mindy Pereira int maxFoundPriority = 0; 283b1cbb89f72631bb7e34822b98e8d0842ebd01b83Mindy Pereira if (numCharsUsed > maxChars) { 284beeec8d9688445b87ef4124e4fc5ccfe1c867574mindyp numCharsToRemovePerWord = numCharsUsed - maxChars; 285b1cbb89f72631bb7e34822b98e8d0842ebd01b83Mindy Pereira } 286949ea2185d79e3e266662766cfa07cf748493e3aPaul Westbrook 287949ea2185d79e3e266662766cfa07cf748493e3aPaul Westbrook final Map<Integer, Integer> priorityToLength = PRIORITY_LENGTH_MAP_CACHE.get(); 288949ea2185d79e3e266662766cfa07cf748493e3aPaul Westbrook try { 289949ea2185d79e3e266662766cfa07cf748493e3aPaul Westbrook priorityToLength.clear(); 290949ea2185d79e3e266662766cfa07cf748493e3aPaul Westbrook int senderLength; 2913b59b333ad0693f74f9a8cfb24a468a8acbaca8cJames Lemieux for (ParticipantInfo info : conversationInfo.participantInfos) { 2923b59b333ad0693f74f9a8cfb24a468a8acbaca8cJames Lemieux final String senderName = info.name; 2933b59b333ad0693f74f9a8cfb24a468a8acbaca8cJames Lemieux senderLength = !TextUtils.isEmpty(senderName) ? senderName.length() : 0; 294949ea2185d79e3e266662766cfa07cf748493e3aPaul Westbrook priorityToLength.put(info.priority, senderLength); 295949ea2185d79e3e266662766cfa07cf748493e3aPaul Westbrook maxFoundPriority = Math.max(maxFoundPriority, info.priority); 296949ea2185d79e3e266662766cfa07cf748493e3aPaul Westbrook } 297949ea2185d79e3e266662766cfa07cf748493e3aPaul Westbrook while (maxPriorityToInclude < maxFoundPriority) { 298949ea2185d79e3e266662766cfa07cf748493e3aPaul Westbrook if (priorityToLength.containsKey(maxPriorityToInclude + 1)) { 299949ea2185d79e3e266662766cfa07cf748493e3aPaul Westbrook int length = numCharsUsed + priorityToLength.get(maxPriorityToInclude + 1); 300949ea2185d79e3e266662766cfa07cf748493e3aPaul Westbrook if (numCharsUsed > 0) 301949ea2185d79e3e266662766cfa07cf748493e3aPaul Westbrook length += 2; 302949ea2185d79e3e266662766cfa07cf748493e3aPaul Westbrook // We must show at least two senders if they exist. If we don't 303949ea2185d79e3e266662766cfa07cf748493e3aPaul Westbrook // have space for both 304949ea2185d79e3e266662766cfa07cf748493e3aPaul Westbrook // then we will truncate names. 305949ea2185d79e3e266662766cfa07cf748493e3aPaul Westbrook if (length > maxChars && numSendersUsed >= 2) { 306949ea2185d79e3e266662766cfa07cf748493e3aPaul Westbrook break; 307949ea2185d79e3e266662766cfa07cf748493e3aPaul Westbrook } 308949ea2185d79e3e266662766cfa07cf748493e3aPaul Westbrook numCharsUsed = length; 309949ea2185d79e3e266662766cfa07cf748493e3aPaul Westbrook numSendersUsed++; 310b1cbb89f72631bb7e34822b98e8d0842ebd01b83Mindy Pereira } 311949ea2185d79e3e266662766cfa07cf748493e3aPaul Westbrook maxPriorityToInclude++; 312b1cbb89f72631bb7e34822b98e8d0842ebd01b83Mindy Pereira } 313949ea2185d79e3e266662766cfa07cf748493e3aPaul Westbrook } finally { 314949ea2185d79e3e266662766cfa07cf748493e3aPaul Westbrook PRIORITY_LENGTH_MAP_CACHE.release(priorityToLength); 315b1cbb89f72631bb7e34822b98e8d0842ebd01b83Mindy Pereira } 3163dbfbc210a607382ba9c150d7ae373ca0508267cJin Cao 317b1cbb89f72631bb7e34822b98e8d0842ebd01b83Mindy Pereira SpannableString spannableDisplay; 318b1cbb89f72631bb7e34822b98e8d0842ebd01b83Mindy Pereira boolean appendedElided = false; 3193dbfbc210a607382ba9c150d7ae373ca0508267cJin Cao final Map<String, Integer> displayHash = Maps.newHashMap(); 3203dbfbc210a607382ba9c150d7ae373ca0508267cJin Cao final List<String> senderEmails = Lists.newArrayListWithExpectedSize(MAX_SENDER_COUNT); 3213dbfbc210a607382ba9c150d7ae373ca0508267cJin Cao String firstSenderEmail = null; 3223dbfbc210a607382ba9c150d7ae373ca0508267cJin Cao String firstSenderName = null; 3233b59b333ad0693f74f9a8cfb24a468a8acbaca8cJames Lemieux for (int i = 0; i < conversationInfo.participantInfos.size(); i++) { 3243dbfbc210a607382ba9c150d7ae373ca0508267cJin Cao final ParticipantInfo currentParticipant = conversationInfo.participantInfos.get(i); 3253b59b333ad0693f74f9a8cfb24a468a8acbaca8cJames Lemieux final String currentEmail = currentParticipant.email; 3263b59b333ad0693f74f9a8cfb24a468a8acbaca8cJames Lemieux 3273b59b333ad0693f74f9a8cfb24a468a8acbaca8cJames Lemieux final String currentName = currentParticipant.name; 3283b59b333ad0693f74f9a8cfb24a468a8acbaca8cJames Lemieux String nameString = !TextUtils.isEmpty(currentName) ? currentName : ""; 329b1cbb89f72631bb7e34822b98e8d0842ebd01b83Mindy Pereira if (nameString.length() == 0) { 33010ea28ab588d8e922c0f78f0f47fe479739ec2cfJames Lemieux // if we're showing the To: header, show the object version of me. 33110ea28ab588d8e922c0f78f0f47fe479739ec2cfJames Lemieux nameString = getMe(showToHeader /* useObjectMe */); 332d97782206889a5508279b75cce19d7c0fb8a3bcaMindy Pereira } 333b1cbb89f72631bb7e34822b98e8d0842ebd01b83Mindy Pereira if (numCharsToRemovePerWord != 0) { 334b1cbb89f72631bb7e34822b98e8d0842ebd01b83Mindy Pereira nameString = nameString.substring(0, 335b1cbb89f72631bb7e34822b98e8d0842ebd01b83Mindy Pereira Math.max(nameString.length() - numCharsToRemovePerWord, 0)); 336b1cbb89f72631bb7e34822b98e8d0842ebd01b83Mindy Pereira } 3373b59b333ad0693f74f9a8cfb24a468a8acbaca8cJames Lemieux 3383b59b333ad0693f74f9a8cfb24a468a8acbaca8cJames Lemieux final int priority = currentParticipant.priority; 3393dbfbc210a607382ba9c150d7ae373ca0508267cJin Cao final CharacterStyle style = CharacterStyle.wrap(currentParticipant.readConversation ? 3403dbfbc210a607382ba9c150d7ae373ca0508267cJin Cao readStyleSpan : unreadStyleSpan); 341b1cbb89f72631bb7e34822b98e8d0842ebd01b83Mindy Pereira if (priority <= maxPriorityToInclude) { 3428173cf41d2acf48c7b45ae3e7868fc391aae0359Andrew Sapperstein spannableDisplay = new SpannableString(sBidiFormatter.unicodeWrap(nameString)); 34305448212df93567d8ba222b792dd90fd2225fd3dMindy Pereira // Don't duplicate senders; leave the first instance, unless the 34405448212df93567d8ba222b792dd90fd2225fd3dMindy Pereira // current instance is also unread. 3453b59b333ad0693f74f9a8cfb24a468a8acbaca8cJames Lemieux int oldPos = displayHash.containsKey(currentName) ? displayHash 3463b59b333ad0693f74f9a8cfb24a468a8acbaca8cJames Lemieux .get(currentName) : DOES_NOT_EXIST; 34705448212df93567d8ba222b792dd90fd2225fd3dMindy Pereira // If this sender doesn't exist OR the current message is 34805448212df93567d8ba222b792dd90fd2225fd3dMindy Pereira // unread, add the sender. 3493b59b333ad0693f74f9a8cfb24a468a8acbaca8cJames Lemieux if (oldPos == DOES_NOT_EXIST || !currentParticipant.readConversation) { 35005448212df93567d8ba222b792dd90fd2225fd3dMindy Pereira // If the sender entry already existed, and is right next to the 35105448212df93567d8ba222b792dd90fd2225fd3dMindy Pereira // current sender, remove the old entry. 352be95d004c24569a3cc8bb314997a94d5f8ab8b4fMindy Pereira if (oldPos != DOES_NOT_EXIST && i > 0 && oldPos == i - 1 35388acafa03a87f5c84b959697d13b81df8f11a96emindyp && oldPos < styledSenders.size()) { 35405448212df93567d8ba222b792dd90fd2225fd3dMindy Pereira // Remove the old one! 35588acafa03a87f5c84b959697d13b81df8f11a96emindyp styledSenders.set(oldPos, null); 3563dbfbc210a607382ba9c150d7ae373ca0508267cJin Cao if (shouldSelectSenders && !TextUtils.isEmpty(currentEmail)) { 3573dbfbc210a607382ba9c150d7ae373ca0508267cJin Cao senderEmails.remove(currentEmail); 3583b59b333ad0693f74f9a8cfb24a468a8acbaca8cJames Lemieux displayableSenderNames.remove(currentName); 35988acafa03a87f5c84b959697d13b81df8f11a96emindyp } 36005448212df93567d8ba222b792dd90fd2225fd3dMindy Pereira } 3613b59b333ad0693f74f9a8cfb24a468a8acbaca8cJames Lemieux displayHash.put(currentName, i); 36205448212df93567d8ba222b792dd90fd2225fd3dMindy Pereira spannableDisplay.setSpan(style, 0, spannableDisplay.length(), 0); 36388acafa03a87f5c84b959697d13b81df8f11a96emindyp styledSenders.add(spannableDisplay); 364b1cbb89f72631bb7e34822b98e8d0842ebd01b83Mindy Pereira } 365b1cbb89f72631bb7e34822b98e8d0842ebd01b83Mindy Pereira } else { 366b1cbb89f72631bb7e34822b98e8d0842ebd01b83Mindy Pereira if (!appendedElided) { 367b1cbb89f72631bb7e34822b98e8d0842ebd01b83Mindy Pereira spannableDisplay = new SpannableString(sElidedString); 368b1cbb89f72631bb7e34822b98e8d0842ebd01b83Mindy Pereira spannableDisplay.setSpan(style, 0, spannableDisplay.length(), 0); 369b1cbb89f72631bb7e34822b98e8d0842ebd01b83Mindy Pereira appendedElided = true; 37088acafa03a87f5c84b959697d13b81df8f11a96emindyp styledSenders.add(spannableDisplay); 371b1cbb89f72631bb7e34822b98e8d0842ebd01b83Mindy Pereira } 372b1207e3ec8fe3ce988996722e13b80a4dfdf1c72Mindy Pereira } 3733dbfbc210a607382ba9c150d7ae373ca0508267cJin Cao 374c9e00fcb05c5311633dc3a414b9bf685816b4350James Lemieux final String senderEmail = TextUtils.isEmpty(currentName) ? account.getEmailAddress() : 3753dbfbc210a607382ba9c150d7ae373ca0508267cJin Cao TextUtils.isEmpty(currentEmail) ? currentName : currentEmail; 3763dbfbc210a607382ba9c150d7ae373ca0508267cJin Cao 3773dbfbc210a607382ba9c150d7ae373ca0508267cJin Cao if (shouldSelectSenders) { 378c76ab94c69e09ade8036f47d370d56902f0e1f6emindyp if (i == 0) { 379c76ab94c69e09ade8036f47d370d56902f0e1f6emindyp // Always add the first sender! 3803dbfbc210a607382ba9c150d7ae373ca0508267cJin Cao firstSenderEmail = senderEmail; 3813dbfbc210a607382ba9c150d7ae373ca0508267cJin Cao firstSenderName = currentName; 382c76ab94c69e09ade8036f47d370d56902f0e1f6emindyp } else { 3833dbfbc210a607382ba9c150d7ae373ca0508267cJin Cao if (!Objects.equal(firstSenderEmail, senderEmail)) { 3843dbfbc210a607382ba9c150d7ae373ca0508267cJin Cao int indexOf = senderEmails.indexOf(senderEmail); 385c76ab94c69e09ade8036f47d370d56902f0e1f6emindyp if (indexOf > -1) { 3863dbfbc210a607382ba9c150d7ae373ca0508267cJin Cao senderEmails.remove(indexOf); 387c76ab94c69e09ade8036f47d370d56902f0e1f6emindyp displayableSenderNames.remove(indexOf); 388c76ab94c69e09ade8036f47d370d56902f0e1f6emindyp } 3893dbfbc210a607382ba9c150d7ae373ca0508267cJin Cao senderEmails.add(senderEmail); 3903b59b333ad0693f74f9a8cfb24a468a8acbaca8cJames Lemieux displayableSenderNames.add(currentName); 3913dbfbc210a607382ba9c150d7ae373ca0508267cJin Cao if (senderEmails.size() > MAX_SENDER_COUNT) { 3923dbfbc210a607382ba9c150d7ae373ca0508267cJin Cao senderEmails.remove(0); 393c76ab94c69e09ade8036f47d370d56902f0e1f6emindyp displayableSenderNames.remove(0); 394c76ab94c69e09ade8036f47d370d56902f0e1f6emindyp } 395c76ab94c69e09ade8036f47d370d56902f0e1f6emindyp } 396c76ab94c69e09ade8036f47d370d56902f0e1f6emindyp } 397c76ab94c69e09ade8036f47d370d56902f0e1f6emindyp } 3983dbfbc210a607382ba9c150d7ae373ca0508267cJin Cao 3993dbfbc210a607382ba9c150d7ae373ca0508267cJin Cao // if the corresponding message from this participant is unread and no sender avatar 4003dbfbc210a607382ba9c150d7ae373ca0508267cJin Cao // is yet chosen, choose this one 4013dbfbc210a607382ba9c150d7ae373ca0508267cJin Cao if (shouldSelectAvatar && senderAvatarModel.isNotPopulated() && 4023dbfbc210a607382ba9c150d7ae373ca0508267cJin Cao !currentParticipant.readConversation) { 4033dbfbc210a607382ba9c150d7ae373ca0508267cJin Cao senderAvatarModel.populate(currentName, senderEmail); 4043dbfbc210a607382ba9c150d7ae373ca0508267cJin Cao } 405c76ab94c69e09ade8036f47d370d56902f0e1f6emindyp } 4063dbfbc210a607382ba9c150d7ae373ca0508267cJin Cao 4073dbfbc210a607382ba9c150d7ae373ca0508267cJin Cao // always add the first sender to the display 4083dbfbc210a607382ba9c150d7ae373ca0508267cJin Cao if (shouldSelectSenders && !TextUtils.isEmpty(firstSenderEmail)) { 4093dbfbc210a607382ba9c150d7ae373ca0508267cJin Cao if (displayableSenderNames.size() < MAX_SENDER_COUNT) { 4103dbfbc210a607382ba9c150d7ae373ca0508267cJin Cao displayableSenderNames.add(0, firstSenderName); 411c76ab94c69e09ade8036f47d370d56902f0e1f6emindyp } else { 4123dbfbc210a607382ba9c150d7ae373ca0508267cJin Cao displayableSenderNames.set(0, firstSenderName); 4133dbfbc210a607382ba9c150d7ae373ca0508267cJin Cao } 4143dbfbc210a607382ba9c150d7ae373ca0508267cJin Cao } 4153dbfbc210a607382ba9c150d7ae373ca0508267cJin Cao 4163dbfbc210a607382ba9c150d7ae373ca0508267cJin Cao // if all messages in the thread were read, we must search for an appropriate avatar 417c9e00fcb05c5311633dc3a414b9bf685816b4350James Lemieux if (shouldSelectAvatar && senderAvatarModel.isNotPopulated()) { 4183dbfbc210a607382ba9c150d7ae373ca0508267cJin Cao // search for the last sender that is not the current account 4193dbfbc210a607382ba9c150d7ae373ca0508267cJin Cao for (int i = conversationInfo.participantInfos.size() - 1; i >= 0; i--) { 4203dbfbc210a607382ba9c150d7ae373ca0508267cJin Cao final ParticipantInfo participant = conversationInfo.participantInfos.get(i); 42149b72f2736de522c8479155d08742ae8e4ba3a91James Lemieux // empty name implies it is the current account and should not be chosen 4223dbfbc210a607382ba9c150d7ae373ca0508267cJin Cao if (!TextUtils.isEmpty(participant.name)) { 42349b72f2736de522c8479155d08742ae8e4ba3a91James Lemieux // use the participant name in place of unusable email addresses 42449b72f2736de522c8479155d08742ae8e4ba3a91James Lemieux final String senderEmail = TextUtils.isEmpty(participant.email) ? 42549b72f2736de522c8479155d08742ae8e4ba3a91James Lemieux participant.name : participant.email; 42649b72f2736de522c8479155d08742ae8e4ba3a91James Lemieux senderAvatarModel.populate(participant.name, senderEmail); 4273dbfbc210a607382ba9c150d7ae373ca0508267cJin Cao break; 4283dbfbc210a607382ba9c150d7ae373ca0508267cJin Cao } 4293dbfbc210a607382ba9c150d7ae373ca0508267cJin Cao } 4303dbfbc210a607382ba9c150d7ae373ca0508267cJin Cao 431c9e00fcb05c5311633dc3a414b9bf685816b4350James Lemieux // if we still don't have an avatar, the account is emailing itself 4323dbfbc210a607382ba9c150d7ae373ca0508267cJin Cao if (senderAvatarModel.isNotPopulated()) { 433c9e00fcb05c5311633dc3a414b9bf685816b4350James Lemieux senderAvatarModel.populate(account.getDisplayName(), account.getEmailAddress()); 434c76ab94c69e09ade8036f47d370d56902f0e1f6emindyp } 435b1207e3ec8fe3ce988996722e13b80a4dfdf1c72Mindy Pereira } 43658ef69ad99623fd8795a95227aa718d3d6177c5aMindy Pereira } 43758ef69ad99623fd8795a95227aa718d3d6177c5aMindy Pereira 43810ea28ab588d8e922c0f78f0f47fe479739ec2cfJames Lemieux static String getMe(boolean useObjectMe) { 43910ea28ab588d8e922c0f78f0f47fe479739ec2cfJames Lemieux return useObjectMe ? sMeObjectString : sMeSubjectString; 440571de2212f311cc4a514ffa74e7585a2df1fb907Mindy Pereira } 441571de2212f311cc4a514ffa74e7585a2df1fb907Mindy Pereira 44210ea28ab588d8e922c0f78f0f47fe479739ec2cfJames Lemieux public static SpannableString getFormattedToHeader() { 44310ea28ab588d8e922c0f78f0f47fe479739ec2cfJames Lemieux final SpannableString formattedToHeader = new SpannableString(sToHeaderString); 44410ea28ab588d8e922c0f78f0f47fe479739ec2cfJames Lemieux final CharacterStyle readStyle = CharacterStyle.wrap(sReadStyleSpan); 44510ea28ab588d8e922c0f78f0f47fe479739ec2cfJames Lemieux formattedToHeader.setSpan(readStyle, 0, formattedToHeader.length(), 0); 44610ea28ab588d8e922c0f78f0f47fe479739ec2cfJames Lemieux return formattedToHeader; 447d97782206889a5508279b75cce19d7c0fb8a3bcaMindy Pereira } 448d97782206889a5508279b75cce19d7c0fb8a3bcaMindy Pereira 4490fd4cba8db984955729871d15a7cfebd73e9cf9dAndrew Sapperstein public static SpannableString getSingularDraftString(Context context) { 4500fd4cba8db984955729871d15a7cfebd73e9cf9dAndrew Sapperstein getSenderResources(context, true /* resourceCachingRequired */); 451735a22a197215ec4787ad9f3cbaf465cce54f4d0Andrew Sapperstein final SpannableString formattedDraftString = new SpannableString(sDraftSingularString); 452735a22a197215ec4787ad9f3cbaf465cce54f4d0Andrew Sapperstein final CharacterStyle readStyle = CharacterStyle.wrap(sDraftsStyleSpan); 453735a22a197215ec4787ad9f3cbaf465cce54f4d0Andrew Sapperstein formattedDraftString.setSpan(readStyle, 0, formattedDraftString.length(), 0); 454735a22a197215ec4787ad9f3cbaf465cce54f4d0Andrew Sapperstein return formattedDraftString; 455735a22a197215ec4787ad9f3cbaf465cce54f4d0Andrew Sapperstein } 456735a22a197215ec4787ad9f3cbaf465cce54f4d0Andrew Sapperstein 457d5fd04656f364a209703a67debc33d91dabfb83fScott Kennedy private static void clearResourceCache() { 458d5fd04656f364a209703a67debc33d91dabfb83fScott Kennedy sDraftSingularString = null; 45977d7f3c3c8c82048b51025428a825f6ac71e8560Mindy Pereira } 4608eb43be8074acb4e09da1385225fbb41c97b1bd5Mindy Pereira} 461