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