1326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira/** 2326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira * Copyright (c) 2011, Google Inc. 3326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira * 4326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira * Licensed under the Apache License, Version 2.0 (the "License"); 5326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira * you may not use this file except in compliance with the License. 6326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira * You may obtain a copy of the License at 7326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira * 8326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira * http://www.apache.org/licenses/LICENSE-2.0 9326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira * 10326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira * Unless required by applicable law or agreed to in writing, software 11326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira * distributed under the License is distributed on an "AS IS" BASIS, 12326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira * See the License for the specific language governing permissions and 14326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira * limitations under the License. 15326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira */ 16326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira 1730e2c24b056542f3b1b438aeb798305d1226d0c8Andy Huangpackage com.android.mail.browse; 18326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira 1921a6ed2bdd46ccfdf9aa3e8aecd4cb1af6c2539fAndrew Sappersteinimport android.app.DialogFragment; 2021a6ed2bdd46ccfdf9aa3e8aecd4cb1af6c2539fAndrew Sappersteinimport android.app.FragmentManager; 213233bff8ae08a56543c9f5abf1bc6ab38f0574ceAndy Huangimport android.content.AsyncQueryHandler; 22326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereiraimport android.content.Context; 23a8dc86faac4d1ac07901be75dc92b7a877ca46ffVikram Aggarwalimport android.content.res.Resources; 24b8331b4565566ca733997398e8c07a26cd2bee98Andy Huangimport android.database.DataSetObserver; 25c5499cdd4627df39b935c3569c2b8e6e4b6ed38eAndrew Sappersteinimport android.graphics.Bitmap; 26326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereiraimport android.graphics.Typeface; 27c5499cdd4627df39b935c3569c2b8e6e4b6ed38eAndrew Sappersteinimport android.os.Build; 28326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereiraimport android.text.Spannable; 29326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereiraimport android.text.SpannableStringBuilder; 303de76eca03ed7ec1d40f2cce23cbbbe8e5e6d70fAndrew Sappersteinimport android.text.Spanned; 31326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereiraimport android.text.TextUtils; 32326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereiraimport android.text.style.StyleSpan; 333de76eca03ed7ec1d40f2cce23cbbbe8e5e6d70fAndrew Sappersteinimport android.text.style.URLSpan; 34326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereiraimport android.util.AttributeSet; 35326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereiraimport android.view.LayoutInflater; 3675b52a50a7b8382d9046d48ea8cda97b5471cbc8Andy Huangimport android.view.Menu; 37326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereiraimport android.view.MenuItem; 38326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereiraimport android.view.View; 39326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereiraimport android.view.View.OnClickListener; 40bb56a1512559a5f024ba213c4bdcfe3d9d9387deAndy Huangimport android.view.ViewGroup; 41326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereiraimport android.widget.ImageView; 42326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereiraimport android.widget.LinearLayout; 43326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereiraimport android.widget.PopupMenu; 44bb56a1512559a5f024ba213c4bdcfe3d9d9387deAndy Huangimport android.widget.PopupMenu.OnMenuItemClickListener; 45326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereiraimport android.widget.QuickContactBadge; 46326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereiraimport android.widget.TextView; 47326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereiraimport android.widget.Toast; 48326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira 49b8331b4565566ca733997398e8c07a26cd2bee98Andy Huangimport com.android.mail.ContactInfo; 5030e2c24b056542f3b1b438aeb798305d1226d0c8Andy Huangimport com.android.mail.ContactInfoSource; 51bb56a1512559a5f024ba213c4bdcfe3d9d9387deAndy Huangimport com.android.mail.R; 52cee3c90574b48ccaa0f8b9f9341383c231ed41d2Andrew Sappersteinimport com.android.mail.browse.ConversationViewAdapter.BorderItem; 53c7543579c6a97c0ae3341578332f56d4d226f34cAndy Huangimport com.android.mail.browse.ConversationViewAdapter.MessageHeaderItem; 5430e2c24b056542f3b1b438aeb798305d1226d0c8Andy Huangimport com.android.mail.compose.ComposeActivity; 5530e2c24b056542f3b1b438aeb798305d1226d0c8Andy Huangimport com.android.mail.perf.Timer; 56c5499cdd4627df39b935c3569c2b8e6e4b6ed38eAndrew Sappersteinimport com.android.mail.photomanager.LetterTileProvider; 5733fe908589dca6a7f58aa9f56d73f74a48ac42f6Mindy Pereiraimport com.android.mail.providers.Account; 5830e2c24b056542f3b1b438aeb798305d1226d0c8Andy Huangimport com.android.mail.providers.Address; 594ddda2f0a4ee5381a90779a6939b05b064ce5d11Andrew Sappersteinimport com.android.mail.providers.Conversation; 600a135884c7452225bc0c86c5f768d581c0ce6c04Mark Weiimport com.android.mail.providers.Folder; 613ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereiraimport com.android.mail.providers.Message; 6230e2c24b056542f3b1b438aeb798305d1226d0c8Andy Huangimport com.android.mail.providers.UIProvider; 63c5499cdd4627df39b935c3569c2b8e6e4b6ed38eAndrew Sappersteinimport com.android.mail.ui.ImageCanvas; 64b334c9035e9b7a38766bb66c29da2208525d1e11Paul Westbrookimport com.android.mail.utils.LogTag; 6530e2c24b056542f3b1b438aeb798305d1226d0c8Andy Huangimport com.android.mail.utils.LogUtils; 6630e2c24b056542f3b1b438aeb798305d1226d0c8Andy Huangimport com.android.mail.utils.Utils; 67a8dc86faac4d1ac07901be75dc92b7a877ca46ffVikram Aggarwalimport com.android.mail.utils.VeiledAddressMatcher; 68bec5115726f24733a0a1577caaf05fb6e9ef9c6fMarc Blankimport com.google.common.annotations.VisibleForTesting; 69326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira 70326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereiraimport java.io.IOException; 71326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereiraimport java.io.StringReader; 7265fe28fa88daad08f3be4c084ca5b4eaa366d1a7Andy Huangimport java.util.Map; 73326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira 74326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereirapublic class MessageHeaderView extends LinearLayout implements OnClickListener, 752b7bbb53344b1e2c1d970a8da051a7431565db1fRohan Shah OnMenuItemClickListener, ConversationContainer.DetachListener { 76326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira 77326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira /** 78326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira * Cap very long recipient lists during summary construction for efficiency. 79326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira */ 80326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira private static final int SUMMARY_MAX_RECIPIENTS = 50; 81326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira 82326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira private static final int MAX_SNIPPET_LENGTH = 100; 83326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira 84326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira private static final int SHOW_IMAGE_PROMPT_ONCE = 1; 85326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira private static final int SHOW_IMAGE_PROMPT_ALWAYS = 2; 86326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira 87326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira private static final String HEADER_INFLATE_TAG = "message header inflate"; 88326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira private static final String HEADER_ADDVIEW_TAG = "message header addView"; 89326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira private static final String HEADER_RENDER_TAG = "message header render"; 90326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira private static final String PREMEASURE_TAG = "message header pre-measure"; 91326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira private static final String LAYOUT_TAG = "message header layout"; 92326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira private static final String MEASURE_TAG = "message header measure"; 93326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira 94326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira private static final String RECIPIENT_HEADING_DELIMITER = " "; 95326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira 96b334c9035e9b7a38766bb66c29da2208525d1e11Paul Westbrook private static final String LOG_TAG = LogTag.getLogTag(); 97326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira 9877a4605e6fbc368b2b87b4888f2ffd6329620807mindyp public static final int DEFAULT_MODE = 0; 9977a4605e6fbc368b2b87b4888f2ffd6329620807mindyp public static final int POPUP_MODE = 1; 10077a4605e6fbc368b2b87b4888f2ffd6329620807mindyp 1011ebc2db723ed29093d724eb5da906a496ee57224Alice Yang // This is a debug only feature 102ce03eaa2663f543bbd49819515a5835dfb4ea77eAlice Yang public static final boolean ENABLE_REPORT_RENDERING_PROBLEM = false; 1031ebc2db723ed29093d724eb5da906a496ee57224Alice Yang 10421a6ed2bdd46ccfdf9aa3e8aecd4cb1af6c2539fAndrew Sapperstein private static final String DETAILS_DIALOG_TAG = "details-dialog"; 10521a6ed2bdd46ccfdf9aa3e8aecd4cb1af6c2539fAndrew Sapperstein 106326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira private MessageHeaderViewCallbacks mCallbacks; 107326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira 1089f369596f1dc59184cdabe683c2ebfc19ead4f83Andy Huang private ViewGroup mUpperHeaderView; 1096a187d5113518435d13c60e2f1cabc418238c600Andrew Sapperstein private View mSnapHeaderBottomBorder; 110326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira private TextView mSenderNameView; 111326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira private TextView mSenderEmailView; 11235c3bb793ac3ea8f63ff73d282c0dabfee5a49ceAndrew Sapperstein private TextView mDateView; 11335c3bb793ac3ea8f63ff73d282c0dabfee5a49ceAndrew Sapperstein private TextView mSnippetView; 114326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira private QuickContactBadge mPhotoView; 115326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira private ImageView mStarView; 116326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira private ViewGroup mTitleContainerView; 1172862cba002c7805a8f8e28146c6d5504831dcec7Andrew Sapperstein private ViewGroup mExtraContentView; 118326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira private ViewGroup mCollapsedDetailsView; 119326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira private ViewGroup mExpandedDetailsView; 1203b08c51ec46794b3c22c8649eb86bf77c72e0d9aAndrew Sapperstein private SpamWarningView mSpamWarningView; 12114f937408fe2451a91b44d3cd7d141347e716775Andrew Sapperstein private TextView mImagePromptView; 122a71f1f3368f26b6627512298f64484611fd6b0e8Andy Huang private MessageInviteView mInviteView; 12365fe28fa88daad08f3be4c084ca5b4eaa366d1a7Andy Huang private View mForwardButton; 12465fe28fa88daad08f3be4c084ca5b4eaa366d1a7Andy Huang private View mOverflowButton; 12565fe28fa88daad08f3be4c084ca5b4eaa366d1a7Andy Huang private View mDraftIcon; 12665fe28fa88daad08f3be4c084ca5b4eaa366d1a7Andy Huang private View mEditDraftButton; 12765fe28fa88daad08f3be4c084ca5b4eaa366d1a7Andy Huang private TextView mUpperDateView; 12865fe28fa88daad08f3be4c084ca5b4eaa366d1a7Andy Huang private View mReplyButton; 12965fe28fa88daad08f3be4c084ca5b4eaa366d1a7Andy Huang private View mReplyAllButton; 13065fe28fa88daad08f3be4c084ca5b4eaa366d1a7Andy Huang private View mAttachmentIcon; 1312b7bbb53344b1e2c1d970a8da051a7431565db1fRohan Shah private final EmailCopyContextMenu mEmailCopyMenu; 132326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira 133326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira // temporary fields to reference raw data between initial render and details 134326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira // expansion 135d5b369b324a22d28b63def902eefaf6591edf004Andrew Sapperstein private String[] mFrom; 136326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira private String[] mTo; 137326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira private String[] mCc; 138326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira private String[] mBcc; 139326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira private String[] mReplyTo; 140326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira 141326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira private boolean mIsDraft = false; 142326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira 143326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira private boolean mIsSending; 144326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira 145326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira /** 146326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira * The snappy header has special visibility rules (i.e. no details header, 147326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira * even though it has an expanded appearance) 148326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira */ 149326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira private boolean mIsSnappy; 150326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira 151326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira private String mSnippet; 152326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira 153326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira private Address mSender; 154326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira 155326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira private ContactInfoSource mContactInfoSource; 156326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira 157326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira private boolean mPreMeasuring; 158326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira 15928b7aee7fa1f7d096d33fc823a88a64f7a3fa79dAndy Huang private ConversationAccountController mAccountController; 160326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira 16165fe28fa88daad08f3be4c084ca5b4eaa366d1a7Andy Huang private Map<String, Address> mAddressCache; 16265fe28fa88daad08f3be4c084ca5b4eaa366d1a7Andy Huang 163326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira private boolean mShowImagePrompt; 164326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira 165326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira /** 166326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira * Take the initial visibility of the star view to mean its collapsed 167326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira * visibility. Star is always visible when expanded, but sometimes, like on 168326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira * phones, there isn't enough room to warrant showing star when collapsed. 169326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira */ 1700a135884c7452225bc0c86c5f768d581c0ce6c04Mark Wei private boolean mCollapsedStarVisible; 1710a135884c7452225bc0c86c5f768d581c0ce6c04Mark Wei private boolean mStarShown; 172326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira 173326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira /** 174c5499cdd4627df39b935c3569c2b8e6e4b6ed38eAndrew Sapperstein * End margin of the text when collapsed. When expanded, the margin is 0. 175326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira */ 176c5499cdd4627df39b935c3569c2b8e6e4b6ed38eAndrew Sapperstein private int mTitleContainerCollapsedMarginEnd; 177326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira 178326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira private PopupMenu mPopup; 179326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira 180c7543579c6a97c0ae3341578332f56d4d226f34cAndy Huang private MessageHeaderItem mMessageHeaderItem; 181839ada22ea84251dde3305003d2f8fc5bf14914eAndy Huang private ConversationMessage mMessage; 1823ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereira 183f70fc4052b72a850bbb9be585d0f5a4877ee9448Andy Huang private boolean mCollapsedDetailsValid; 184f70fc4052b72a850bbb9be585d0f5a4877ee9448Andy Huang private boolean mExpandedDetailsValid; 185f70fc4052b72a850bbb9be585d0f5a4877ee9448Andy Huang 18688fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang private final LayoutInflater mInflater; 18788fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang 1883233bff8ae08a56543c9f5abf1bc6ab38f0574ceAndy Huang private AsyncQueryHandler mQueryHandler; 1893233bff8ae08a56543c9f5abf1bc6ab38f0574ceAndy Huang 19059e0b18db1bd06cfb74693d7dbb0cb48112a69b1Andy Huang private boolean mObservingContactInfo; 19159e0b18db1bd06cfb74693d7dbb0cb48112a69b1Andy Huang 1927faa4d0a0ee25200f4fdc6dee30bb98b8e18b24aVikram Aggarwal /** 1937faa4d0a0ee25200f4fdc6dee30bb98b8e18b24aVikram Aggarwal * What I call myself? "me" in English, and internationalized correctly. 1947faa4d0a0ee25200f4fdc6dee30bb98b8e18b24aVikram Aggarwal */ 1957faa4d0a0ee25200f4fdc6dee30bb98b8e18b24aVikram Aggarwal private final String mMyName; 1967faa4d0a0ee25200f4fdc6dee30bb98b8e18b24aVikram Aggarwal 197b8331b4565566ca733997398e8c07a26cd2bee98Andy Huang private final DataSetObserver mContactInfoObserver = new DataSetObserver() { 198b8331b4565566ca733997398e8c07a26cd2bee98Andy Huang @Override 199b8331b4565566ca733997398e8c07a26cd2bee98Andy Huang public void onChanged() { 200b8331b4565566ca733997398e8c07a26cd2bee98Andy Huang updateContactInfo(); 201b8331b4565566ca733997398e8c07a26cd2bee98Andy Huang } 202b8331b4565566ca733997398e8c07a26cd2bee98Andy Huang }; 203b8331b4565566ca733997398e8c07a26cd2bee98Andy Huang 204f4fce1227d8b49f45e6569f1590565f2df9e8d6emindyp private boolean mExpandable = true; 205f4fce1227d8b49f45e6569f1590565f2df9e8d6emindyp 20677a4605e6fbc368b2b87b4888f2ffd6329620807mindyp private int mExpandMode = DEFAULT_MODE; 20777a4605e6fbc368b2b87b4888f2ffd6329620807mindyp 20821a6ed2bdd46ccfdf9aa3e8aecd4cb1af6c2539fAndrew Sapperstein private DialogFragment mDetailsPopup; 20977a4605e6fbc368b2b87b4888f2ffd6329620807mindyp 21069a6cdff8afde77ec9bcd75a5651ee212344019eVikram Aggarwal private VeiledAddressMatcher mVeiledMatcher; 211a8dc86faac4d1ac07901be75dc92b7a877ca46ffVikram Aggarwal 2124ddda2f0a4ee5381a90779a6939b05b064ce5d11Andrew Sapperstein private boolean mIsViewOnlyMode = false; 2134ddda2f0a4ee5381a90779a6939b05b064ce5d11Andrew Sapperstein 2145fbc58bc22df9642385e35da34f0ba8e218620b4Andrew Sapperstein private LetterTileProvider mLetterTileProvider; 2155fbc58bc22df9642385e35da34f0ba8e218620b4Andrew Sapperstein private final int mContactPhotoWidth; 2165fbc58bc22df9642385e35da34f0ba8e218620b4Andrew Sapperstein private final int mContactPhotoHeight; 217c5499cdd4627df39b935c3569c2b8e6e4b6ed38eAndrew Sapperstein 2183233bff8ae08a56543c9f5abf1bc6ab38f0574ceAndy Huang public interface MessageHeaderViewCallbacks { 219c7543579c6a97c0ae3341578332f56d4d226f34cAndy Huang void setMessageSpacerHeight(MessageHeaderItem item, int newSpacerHeight); 2203233bff8ae08a56543c9f5abf1bc6ab38f0574ceAndy Huang 221cee3c90574b48ccaa0f8b9f9341383c231ed41d2Andrew Sapperstein void setMessageExpanded(MessageHeaderItem item, int newSpacerHeight, 222cee3c90574b48ccaa0f8b9f9341383c231ed41d2Andrew Sapperstein int topBorderHeight, int bottomBorderHeight); 2233233bff8ae08a56543c9f5abf1bc6ab38f0574ceAndy Huang 2241b3cc47f54072105c161d6ed557550e0e149b8bbmindyp void setMessageDetailsExpanded(MessageHeaderItem messageHeaderItem, boolean expanded, 2251b3cc47f54072105c161d6ed557550e0e149b8bbmindyp int previousMessageHeaderItemHeight); 2261b3cc47f54072105c161d6ed557550e0e149b8bbmindyp 2273233bff8ae08a56543c9f5abf1bc6ab38f0574ceAndy Huang void showExternalResources(Message msg); 228eb9a4bdc53269ee05fe11870b9ebf03f18196585Scott Kennedy 229eb9a4bdc53269ee05fe11870b9ebf03f18196585Scott Kennedy void showExternalResources(String senderRawAddress); 2301ebc2db723ed29093d724eb5da906a496ee57224Alice Yang 23175b52a50a7b8382d9046d48ea8cda97b5471cbc8Andy Huang boolean supportsMessageTransforms(); 2324ddda2f0a4ee5381a90779a6939b05b064ce5d11Andrew Sapperstein 2331ebc2db723ed29093d724eb5da906a496ee57224Alice Yang String getMessageTransforms(Message msg); 23421a6ed2bdd46ccfdf9aa3e8aecd4cb1af6c2539fAndrew Sapperstein 23521a6ed2bdd46ccfdf9aa3e8aecd4cb1af6c2539fAndrew Sapperstein FragmentManager getFragmentManager(); 2363233bff8ae08a56543c9f5abf1bc6ab38f0574ceAndy Huang } 2373233bff8ae08a56543c9f5abf1bc6ab38f0574ceAndy Huang 238326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira public MessageHeaderView(Context context) { 239326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira this(context, null); 240326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } 241326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira 242326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira public MessageHeaderView(Context context, AttributeSet attrs) { 243326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira this(context, attrs, -1); 244326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } 245326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira 246326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira public MessageHeaderView(Context context, AttributeSet attrs, int defStyle) { 247326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira super(context, attrs, defStyle); 24888fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang 2492b7bbb53344b1e2c1d970a8da051a7431565db1fRohan Shah mEmailCopyMenu = new EmailCopyContextMenu(getContext()); 25088fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang mInflater = LayoutInflater.from(context); 251d4de4aa5c73a9e68e1887c2b3de233acd0c51761Paul Westbrook mMyName = context.getString(R.string.me_object_pronun); 2525fbc58bc22df9642385e35da34f0ba8e218620b4Andrew Sapperstein 2535fbc58bc22df9642385e35da34f0ba8e218620b4Andrew Sapperstein final Resources resources = getResources(); 2546a187d5113518435d13c60e2f1cabc418238c600Andrew Sapperstein mContactPhotoWidth = resources.getDimensionPixelSize( 2556a187d5113518435d13c60e2f1cabc418238c600Andrew Sapperstein R.dimen.message_header_contact_photo_width); 2566a187d5113518435d13c60e2f1cabc418238c600Andrew Sapperstein mContactPhotoHeight = resources.getDimensionPixelSize( 2576a187d5113518435d13c60e2f1cabc418238c600Andrew Sapperstein R.dimen.message_header_contact_photo_height); 258326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } 259326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira 26077a4605e6fbc368b2b87b4888f2ffd6329620807mindyp /** 26177a4605e6fbc368b2b87b4888f2ffd6329620807mindyp * Expand mode is DEFAULT_MODE by default. 26277a4605e6fbc368b2b87b4888f2ffd6329620807mindyp */ 26377a4605e6fbc368b2b87b4888f2ffd6329620807mindyp public void setExpandMode(int mode) { 26477a4605e6fbc368b2b87b4888f2ffd6329620807mindyp mExpandMode = mode; 26577a4605e6fbc368b2b87b4888f2ffd6329620807mindyp } 26677a4605e6fbc368b2b87b4888f2ffd6329620807mindyp 267326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira @Override 268326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira protected void onFinishInflate() { 269326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira super.onFinishInflate(); 2709f369596f1dc59184cdabe683c2ebfc19ead4f83Andy Huang mUpperHeaderView = (ViewGroup) findViewById(R.id.upper_header); 2716a187d5113518435d13c60e2f1cabc418238c600Andrew Sapperstein mSnapHeaderBottomBorder = findViewById(R.id.snap_header_bottom_border); 272326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira mSenderNameView = (TextView) findViewById(R.id.sender_name); 273326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira mSenderEmailView = (TextView) findViewById(R.id.sender_email); 27435c3bb793ac3ea8f63ff73d282c0dabfee5a49ceAndrew Sapperstein mDateView = (TextView) findViewById(R.id.send_date); 27535c3bb793ac3ea8f63ff73d282c0dabfee5a49ceAndrew Sapperstein mSnippetView = (TextView) findViewById(R.id.email_snippet); 276326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira mPhotoView = (QuickContactBadge) findViewById(R.id.photo); 27765fe28fa88daad08f3be4c084ca5b4eaa366d1a7Andy Huang mReplyButton = findViewById(R.id.reply); 27865fe28fa88daad08f3be4c084ca5b4eaa366d1a7Andy Huang mReplyAllButton = findViewById(R.id.reply_all); 27965fe28fa88daad08f3be4c084ca5b4eaa366d1a7Andy Huang mForwardButton = findViewById(R.id.forward); 280326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira mStarView = (ImageView) findViewById(R.id.star); 281326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira mTitleContainerView = (ViewGroup) findViewById(R.id.title_container); 28265fe28fa88daad08f3be4c084ca5b4eaa366d1a7Andy Huang mOverflowButton = findViewById(R.id.overflow); 28365fe28fa88daad08f3be4c084ca5b4eaa366d1a7Andy Huang mDraftIcon = findViewById(R.id.draft); 28465fe28fa88daad08f3be4c084ca5b4eaa366d1a7Andy Huang mEditDraftButton = findViewById(R.id.edit_draft); 28565fe28fa88daad08f3be4c084ca5b4eaa366d1a7Andy Huang mUpperDateView = (TextView) findViewById(R.id.upper_date); 28665fe28fa88daad08f3be4c084ca5b4eaa366d1a7Andy Huang mAttachmentIcon = findViewById(R.id.attachment); 2872862cba002c7805a8f8e28146c6d5504831dcec7Andrew Sapperstein mExtraContentView = (ViewGroup) findViewById(R.id.header_extra_content); 288326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira 2890a135884c7452225bc0c86c5f768d581c0ce6c04Mark Wei mCollapsedStarVisible = mStarView.getVisibility() == VISIBLE; 290c5499cdd4627df39b935c3569c2b8e6e4b6ed38eAndrew Sapperstein final Resources resources = getResources(); 291c5499cdd4627df39b935c3569c2b8e6e4b6ed38eAndrew Sapperstein mTitleContainerCollapsedMarginEnd = resources.getDimensionPixelSize( 292c5499cdd4627df39b935c3569c2b8e6e4b6ed38eAndrew Sapperstein R.dimen.message_header_title_container_margin_end_collapsed); 2939f369596f1dc59184cdabe683c2ebfc19ead4f83Andy Huang 294326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira setExpanded(true); 295326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira 296326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira registerMessageClickTargets(R.id.reply, R.id.reply_all, R.id.forward, R.id.star, 297326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira R.id.edit_draft, R.id.overflow, R.id.upper_header); 2982b7bbb53344b1e2c1d970a8da051a7431565db1fRohan Shah 2992b7bbb53344b1e2c1d970a8da051a7431565db1fRohan Shah mUpperHeaderView.setOnCreateContextMenuListener(mEmailCopyMenu); 300326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } 301326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira 302326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira private void registerMessageClickTargets(int... ids) { 303326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira for (int id : ids) { 304326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira View v = findViewById(id); 305326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira if (v != null) { 306326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira v.setOnClickListener(this); 307326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } 308326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } 309326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } 310326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira 311326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira /** 312326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira * Associate the header with a contact info source for later contact 313326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira * presence/photo lookup. 314326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira */ 315326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira public void setContactInfoSource(ContactInfoSource contactInfoSource) { 316326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira mContactInfoSource = contactInfoSource; 317326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } 318326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira 319326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira public void setCallbacks(MessageHeaderViewCallbacks callbacks) { 320326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira mCallbacks = callbacks; 321326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } 322326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira 32369a6cdff8afde77ec9bcd75a5651ee212344019eVikram Aggarwal public void setVeiledMatcher(VeiledAddressMatcher matcher) { 32469a6cdff8afde77ec9bcd75a5651ee212344019eVikram Aggarwal mVeiledMatcher = matcher; 32569a6cdff8afde77ec9bcd75a5651ee212344019eVikram Aggarwal } 32669a6cdff8afde77ec9bcd75a5651ee212344019eVikram Aggarwal 327326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira public boolean isExpanded() { 328c7543579c6a97c0ae3341578332f56d4d226f34cAndy Huang // (let's just arbitrarily say that unbound views are expanded by default) 329c7543579c6a97c0ae3341578332f56d4d226f34cAndy Huang return mMessageHeaderItem == null || mMessageHeaderItem.isExpanded(); 330326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } 331326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira 332326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira public void setSnappy(boolean snappy) { 333326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira mIsSnappy = snappy; 334326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira hideMessageDetails(); 335326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } 336326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira 337b8331b4565566ca733997398e8c07a26cd2bee98Andy Huang @Override 338b8331b4565566ca733997398e8c07a26cd2bee98Andy Huang public void onDetachedFromParent() { 339b8331b4565566ca733997398e8c07a26cd2bee98Andy Huang unbind(); 340b8331b4565566ca733997398e8c07a26cd2bee98Andy Huang } 341b8331b4565566ca733997398e8c07a26cd2bee98Andy Huang 342326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira /** 343326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira * Headers that are unbound will not match any rendered header (matches() 344326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira * will return false). Unbinding is not guaranteed to *hide* the view's old 345326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira * data, though. To re-bind this header to message data, call render() or 346326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira * renderUpperHeaderFrom(). 347326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira */ 348326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira public void unbind() { 349c7543579c6a97c0ae3341578332f56d4d226f34cAndy Huang mMessageHeaderItem = null; 3503233bff8ae08a56543c9f5abf1bc6ab38f0574ceAndy Huang mMessage = null; 351b8331b4565566ca733997398e8c07a26cd2bee98Andy Huang 35259e0b18db1bd06cfb74693d7dbb0cb48112a69b1Andy Huang if (mObservingContactInfo) { 35359e0b18db1bd06cfb74693d7dbb0cb48112a69b1Andy Huang mContactInfoSource.unregisterObserver(mContactInfoObserver); 35459e0b18db1bd06cfb74693d7dbb0cb48112a69b1Andy Huang mObservingContactInfo = false; 35559e0b18db1bd06cfb74693d7dbb0cb48112a69b1Andy Huang } 356326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } 357326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira 35814f937408fe2451a91b44d3cd7d141347e716775Andrew Sapperstein public void initialize(ConversationAccountController accountController, 35965fe28fa88daad08f3be4c084ca5b4eaa366d1a7Andy Huang Map<String, Address> addressCache) { 36028b7aee7fa1f7d096d33fc823a88a64f7a3fa79dAndy Huang mAccountController = accountController; 36165fe28fa88daad08f3be4c084ca5b4eaa366d1a7Andy Huang mAddressCache = addressCache; 362326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } 363326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira 36428b7aee7fa1f7d096d33fc823a88a64f7a3fa79dAndy Huang private Account getAccount() { 3654ddda2f0a4ee5381a90779a6939b05b064ce5d11Andrew Sapperstein return mAccountController != null ? mAccountController.getAccount() : null; 36628b7aee7fa1f7d096d33fc823a88a64f7a3fa79dAndy Huang } 36728b7aee7fa1f7d096d33fc823a88a64f7a3fa79dAndy Huang 36828b7aee7fa1f7d096d33fc823a88a64f7a3fa79dAndy Huang public void bind(MessageHeaderItem headerItem, boolean measureOnly) { 36959e0b18db1bd06cfb74693d7dbb0cb48112a69b1Andy Huang if (mMessageHeaderItem != null && mMessageHeaderItem == headerItem) { 37059e0b18db1bd06cfb74693d7dbb0cb48112a69b1Andy Huang return; 37159e0b18db1bd06cfb74693d7dbb0cb48112a69b1Andy Huang } 37259e0b18db1bd06cfb74693d7dbb0cb48112a69b1Andy Huang 3736b3d0d9ab407c3d8b6bcb73bddbfd23f2513bb83Andy Huang mMessageHeaderItem = headerItem; 3746b3d0d9ab407c3d8b6bcb73bddbfd23f2513bb83Andy Huang render(measureOnly); 3756b3d0d9ab407c3d8b6bcb73bddbfd23f2513bb83Andy Huang } 3766b3d0d9ab407c3d8b6bcb73bddbfd23f2513bb83Andy Huang 377968e014c857439de821cf2590ec6aa44363352d0Andrew Sapperstein /** 378968e014c857439de821cf2590ec6aa44363352d0Andrew Sapperstein * Rebinds the view to its data. This will only update the view 379968e014c857439de821cf2590ec6aa44363352d0Andrew Sapperstein * if the {@link MessageHeaderItem} sent as a parameter is the 380968e014c857439de821cf2590ec6aa44363352d0Andrew Sapperstein * same as the view's current {@link MessageHeaderItem} and the 381968e014c857439de821cf2590ec6aa44363352d0Andrew Sapperstein * view's expanded state differs from the item's expanded state. 382968e014c857439de821cf2590ec6aa44363352d0Andrew Sapperstein */ 383968e014c857439de821cf2590ec6aa44363352d0Andrew Sapperstein public void rebind(MessageHeaderItem headerItem) { 384968e014c857439de821cf2590ec6aa44363352d0Andrew Sapperstein if (mMessageHeaderItem == null || mMessageHeaderItem != headerItem || 385968e014c857439de821cf2590ec6aa44363352d0Andrew Sapperstein isActivated() == isExpanded()) { 386968e014c857439de821cf2590ec6aa44363352d0Andrew Sapperstein return; 387968e014c857439de821cf2590ec6aa44363352d0Andrew Sapperstein } 388968e014c857439de821cf2590ec6aa44363352d0Andrew Sapperstein 389968e014c857439de821cf2590ec6aa44363352d0Andrew Sapperstein render(false /* measureOnly */); 390968e014c857439de821cf2590ec6aa44363352d0Andrew Sapperstein } 391968e014c857439de821cf2590ec6aa44363352d0Andrew Sapperstein 3926b3d0d9ab407c3d8b6bcb73bddbfd23f2513bb83Andy Huang public void refresh() { 3936b3d0d9ab407c3d8b6bcb73bddbfd23f2513bb83Andy Huang render(false); 3946b3d0d9ab407c3d8b6bcb73bddbfd23f2513bb83Andy Huang } 3956b3d0d9ab407c3d8b6bcb73bddbfd23f2513bb83Andy Huang 3966b3d0d9ab407c3d8b6bcb73bddbfd23f2513bb83Andy Huang private void render(boolean measureOnly) { 3974baafcbb39e20a81a1585270fc270a560ec8824dAndy Huang if (mMessageHeaderItem == null) { 3984baafcbb39e20a81a1585270fc270a560ec8824dAndy Huang return; 3994baafcbb39e20a81a1585270fc270a560ec8824dAndy Huang } 4004baafcbb39e20a81a1585270fc270a560ec8824dAndy Huang 401326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira Timer t = new Timer(); 402326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira t.start(HEADER_RENDER_TAG); 403326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira 404f70fc4052b72a850bbb9be585d0f5a4877ee9448Andy Huang mCollapsedDetailsValid = false; 405f70fc4052b72a850bbb9be585d0f5a4877ee9448Andy Huang mExpandedDetailsValid = false; 406f70fc4052b72a850bbb9be585d0f5a4877ee9448Andy Huang 4076b3d0d9ab407c3d8b6bcb73bddbfd23f2513bb83Andy Huang mMessage = mMessageHeaderItem.getMessage(); 408c7543579c6a97c0ae3341578332f56d4d226f34cAndy Huang mShowImagePrompt = mMessage.shouldShowImagePrompt(); 4096b3d0d9ab407c3d8b6bcb73bddbfd23f2513bb83Andy Huang setExpanded(mMessageHeaderItem.isExpanded()); 410326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira 411d5b369b324a22d28b63def902eefaf6591edf004Andrew Sapperstein mFrom = mMessage.getFromAddresses(); 412bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook mTo = mMessage.getToAddresses(); 413bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook mCc = mMessage.getCcAddresses(); 414bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook mBcc = mMessage.getBccAddresses(); 415bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook mReplyTo = mMessage.getReplyToAddresses(); 416326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira 417326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira /** 418326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira * Turns draft mode on or off. Draft mode hides message operations other 419326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira * than "edit", hides contact photo, hides presence, and changes the 42014f937408fe2451a91b44d3cd7d141347e716775Andrew Sapperstein * sender name to "Draft". 421326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira */ 42214f937408fe2451a91b44d3cd7d141347e716775Andrew Sapperstein mIsDraft = mMessage.draftType != UIProvider.DraftType.NOT_A_DRAFT; 4232a1e8e30bdd02dc08bdf2f878201b279f60d5142Andy Huang mIsSending = mMessage.isSending; 424326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira 425326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira // If this was a sent message AND: 426326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira // 1. the account has a custom from, the cursor will populate the 427326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira // selected custom from as the fromAddress when a message is sent but 428326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira // not yet synced. 429326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira // 2. the account has no custom froms, fromAddress will be empty, and we 430326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira // can safely fall back and show the account name as sender since it's 431326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira // the only possible fromAddress. 4328960f0af431bc164003e09b3c8981aab808d9ec1Scott Kennedy String from = mMessage.getFrom(); 433326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira if (TextUtils.isEmpty(from)) { 43428b7aee7fa1f7d096d33fc823a88a64f7a3fa79dAndy Huang from = getAccount().name; 435326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } 43665fe28fa88daad08f3be4c084ca5b4eaa366d1a7Andy Huang mSender = getAddress(from); 437326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira 4380a135884c7452225bc0c86c5f768d581c0ce6c04Mark Wei mStarView.setSelected(mMessage.starred); 4390a135884c7452225bc0c86c5f768d581c0ce6c04Mark Wei mStarView.setContentDescription(getResources().getString( 4400a135884c7452225bc0c86c5f768d581c0ce6c04Mark Wei mStarView.isSelected() ? R.string.remove_star : R.string.add_star)); 4410a135884c7452225bc0c86c5f768d581c0ce6c04Mark Wei mStarShown = true; 4424ddda2f0a4ee5381a90779a6939b05b064ce5d11Andrew Sapperstein 4434ddda2f0a4ee5381a90779a6939b05b064ce5d11Andrew Sapperstein final Conversation conversation = mMessage.getConversation(); 4444ddda2f0a4ee5381a90779a6939b05b064ce5d11Andrew Sapperstein if (conversation != null) { 4454ddda2f0a4ee5381a90779a6939b05b064ce5d11Andrew Sapperstein for (Folder folder : conversation.getRawFolders()) { 4464ddda2f0a4ee5381a90779a6939b05b064ce5d11Andrew Sapperstein if (folder.isTrash()) { 4474ddda2f0a4ee5381a90779a6939b05b064ce5d11Andrew Sapperstein mStarShown = false; 4484ddda2f0a4ee5381a90779a6939b05b064ce5d11Andrew Sapperstein break; 4494ddda2f0a4ee5381a90779a6939b05b064ce5d11Andrew Sapperstein } 4500a135884c7452225bc0c86c5f768d581c0ce6c04Mark Wei } 4510a135884c7452225bc0c86c5f768d581c0ce6c04Mark Wei } 4520a135884c7452225bc0c86c5f768d581c0ce6c04Mark Wei 4533b08c51ec46794b3c22c8649eb86bf77c72e0d9aAndrew Sapperstein updateChildVisibility(); 4543b08c51ec46794b3c22c8649eb86bf77c72e0d9aAndrew Sapperstein 4552a1e8e30bdd02dc08bdf2f878201b279f60d5142Andy Huang if (mIsDraft || mIsSending) { 4563b08c51ec46794b3c22c8649eb86bf77c72e0d9aAndrew Sapperstein mSnippet = makeSnippet(mMessage.snippet); 4573b08c51ec46794b3c22c8649eb86bf77c72e0d9aAndrew Sapperstein } else { 4583b08c51ec46794b3c22c8649eb86bf77c72e0d9aAndrew Sapperstein mSnippet = mMessage.snippet; 4593b08c51ec46794b3c22c8649eb86bf77c72e0d9aAndrew Sapperstein } 4603b08c51ec46794b3c22c8649eb86bf77c72e0d9aAndrew Sapperstein 461326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira mSenderNameView.setText(getHeaderTitle()); 462326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira mSenderEmailView.setText(getHeaderSubtitle()); 46314f937408fe2451a91b44d3cd7d141347e716775Andrew Sapperstein mDateView.setText(mMessageHeaderItem.getTimestampLong()); 46435c3bb793ac3ea8f63ff73d282c0dabfee5a49ceAndrew Sapperstein mSnippetView.setText(mSnippet); 4652b7bbb53344b1e2c1d970a8da051a7431565db1fRohan Shah setAddressOnContextMenu(); 466326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira 46765fe28fa88daad08f3be4c084ca5b4eaa366d1a7Andy Huang if (mUpperDateView != null) { 46814f937408fe2451a91b44d3cd7d141347e716775Andrew Sapperstein mUpperDateView.setText(mMessageHeaderItem.getTimestampShort()); 469326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } 470326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira 47159e0b18db1bd06cfb74693d7dbb0cb48112a69b1Andy Huang if (measureOnly) { 47259e0b18db1bd06cfb74693d7dbb0cb48112a69b1Andy Huang // avoid leaving any state around that would interfere with future regular bind() calls 47359e0b18db1bd06cfb74693d7dbb0cb48112a69b1Andy Huang unbind(); 47459e0b18db1bd06cfb74693d7dbb0cb48112a69b1Andy Huang } else { 475b8331b4565566ca733997398e8c07a26cd2bee98Andy Huang updateContactInfo(); 47659e0b18db1bd06cfb74693d7dbb0cb48112a69b1Andy Huang if (!mObservingContactInfo) { 47759e0b18db1bd06cfb74693d7dbb0cb48112a69b1Andy Huang mContactInfoSource.registerObserver(mContactInfoObserver); 47859e0b18db1bd06cfb74693d7dbb0cb48112a69b1Andy Huang mObservingContactInfo = true; 47959e0b18db1bd06cfb74693d7dbb0cb48112a69b1Andy Huang } 480b8331b4565566ca733997398e8c07a26cd2bee98Andy Huang } 481326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira 482326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira t.pause(HEADER_RENDER_TAG); 483326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } 484326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira 4852b7bbb53344b1e2c1d970a8da051a7431565db1fRohan Shah /** 4862b7bbb53344b1e2c1d970a8da051a7431565db1fRohan Shah * Update context menu's address field for when the user long presses 4872b7bbb53344b1e2c1d970a8da051a7431565db1fRohan Shah * on the message header and attempts to copy/send email. 4882b7bbb53344b1e2c1d970a8da051a7431565db1fRohan Shah */ 4892b7bbb53344b1e2c1d970a8da051a7431565db1fRohan Shah private void setAddressOnContextMenu() { 4902b7bbb53344b1e2c1d970a8da051a7431565db1fRohan Shah mEmailCopyMenu.setAddress(mSender.getAddress()); 4912b7bbb53344b1e2c1d970a8da051a7431565db1fRohan Shah } 4922b7bbb53344b1e2c1d970a8da051a7431565db1fRohan Shah 4934baafcbb39e20a81a1585270fc270a560ec8824dAndy Huang public boolean isBoundTo(ConversationOverlayItem item) { 4944baafcbb39e20a81a1585270fc270a560ec8824dAndy Huang return item == mMessageHeaderItem; 4954baafcbb39e20a81a1585270fc270a560ec8824dAndy Huang } 4964baafcbb39e20a81a1585270fc270a560ec8824dAndy Huang 49721a6ed2bdd46ccfdf9aa3e8aecd4cb1af6c2539fAndrew Sapperstein public Address getAddress(String emailStr) { 49865fe28fa88daad08f3be4c084ca5b4eaa366d1a7Andy Huang return getAddress(mAddressCache, emailStr); 49965fe28fa88daad08f3be4c084ca5b4eaa366d1a7Andy Huang } 50065fe28fa88daad08f3be4c084ca5b4eaa366d1a7Andy Huang 50121a6ed2bdd46ccfdf9aa3e8aecd4cb1af6c2539fAndrew Sapperstein public static Address getAddress(Map<String, Address> cache, String emailStr) { 50265fe28fa88daad08f3be4c084ca5b4eaa366d1a7Andy Huang Address addr = null; 503543e709c976ce954a072020ba6f75d12f41b1fbaAndy Huang synchronized (cache) { 50465fe28fa88daad08f3be4c084ca5b4eaa366d1a7Andy Huang if (cache != null) { 505543e709c976ce954a072020ba6f75d12f41b1fbaAndy Huang addr = cache.get(emailStr); 506543e709c976ce954a072020ba6f75d12f41b1fbaAndy Huang } 507543e709c976ce954a072020ba6f75d12f41b1fbaAndy Huang if (addr == null) { 508543e709c976ce954a072020ba6f75d12f41b1fbaAndy Huang addr = Address.getEmailAddress(emailStr); 509543e709c976ce954a072020ba6f75d12f41b1fbaAndy Huang if (cache != null) { 510543e709c976ce954a072020ba6f75d12f41b1fbaAndy Huang cache.put(emailStr, addr); 511543e709c976ce954a072020ba6f75d12f41b1fbaAndy Huang } 51265fe28fa88daad08f3be4c084ca5b4eaa366d1a7Andy Huang } 51365fe28fa88daad08f3be4c084ca5b4eaa366d1a7Andy Huang } 51465fe28fa88daad08f3be4c084ca5b4eaa366d1a7Andy Huang return addr; 51565fe28fa88daad08f3be4c084ca5b4eaa366d1a7Andy Huang } 51665fe28fa88daad08f3be4c084ca5b4eaa366d1a7Andy Huang 517c7543579c6a97c0ae3341578332f56d4d226f34cAndy Huang private void updateSpacerHeight() { 518c7543579c6a97c0ae3341578332f56d4d226f34cAndy Huang final int h = measureHeight(); 519c7543579c6a97c0ae3341578332f56d4d226f34cAndy Huang 520c7543579c6a97c0ae3341578332f56d4d226f34cAndy Huang mMessageHeaderItem.setHeight(h); 521c7543579c6a97c0ae3341578332f56d4d226f34cAndy Huang if (mCallbacks != null) { 522c7543579c6a97c0ae3341578332f56d4d226f34cAndy Huang mCallbacks.setMessageSpacerHeight(mMessageHeaderItem, h); 523c7543579c6a97c0ae3341578332f56d4d226f34cAndy Huang } 524c7543579c6a97c0ae3341578332f56d4d226f34cAndy Huang } 525c7543579c6a97c0ae3341578332f56d4d226f34cAndy Huang 526c7543579c6a97c0ae3341578332f56d4d226f34cAndy Huang private int measureHeight() { 527c7543579c6a97c0ae3341578332f56d4d226f34cAndy Huang ViewGroup parent = (ViewGroup) getParent(); 528326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira if (parent == null) { 529c7543579c6a97c0ae3341578332f56d4d226f34cAndy Huang LogUtils.e(LOG_TAG, new Error(), "Unable to measure height of detached header"); 530326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira return getHeight(); 531326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } 532326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira mPreMeasuring = true; 533c7543579c6a97c0ae3341578332f56d4d226f34cAndy Huang final int h = Utils.measureViewHeight(this, parent); 534326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira mPreMeasuring = false; 535326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira return h; 536326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } 537326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira 538326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira private CharSequence getHeaderTitle() { 539326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira CharSequence title; 540326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira 541326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira if (mIsDraft) { 542326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira title = getResources().getQuantityText(R.plurals.draft, 1); 543326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } else if (mIsSending) { 544326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira title = getResources().getString(R.string.sending); 545326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } else { 546326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira title = getSenderName(mSender); 547326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } 548326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira 549326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira return title; 550326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } 551326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira 552326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira private CharSequence getHeaderSubtitle() { 553326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira CharSequence sub; 554326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira if (mIsSending) { 555326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira sub = null; 556326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } else { 557d5b369b324a22d28b63def902eefaf6591edf004Andrew Sapperstein if (isExpanded()) { 558d5b369b324a22d28b63def902eefaf6591edf004Andrew Sapperstein if (mMessage.viaDomain != null) { 559d5b369b324a22d28b63def902eefaf6591edf004Andrew Sapperstein sub = getResources().getString( 560d5b369b324a22d28b63def902eefaf6591edf004Andrew Sapperstein R.string.via_domain, mMessage.viaDomain); 561d5b369b324a22d28b63def902eefaf6591edf004Andrew Sapperstein } else { 562d5b369b324a22d28b63def902eefaf6591edf004Andrew Sapperstein sub = getSenderAddress(mSender); 563d5b369b324a22d28b63def902eefaf6591edf004Andrew Sapperstein } 564d5b369b324a22d28b63def902eefaf6591edf004Andrew Sapperstein } else { 565d5b369b324a22d28b63def902eefaf6591edf004Andrew Sapperstein sub = mSnippet; 566d5b369b324a22d28b63def902eefaf6591edf004Andrew Sapperstein } 567326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } 568326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira return sub; 569326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } 570326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira 571326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira /** 572326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira * Return the name, if known, or just the address. 573326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira */ 574326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira private static CharSequence getSenderName(Address sender) { 57565fe28fa88daad08f3be4c084ca5b4eaa366d1a7Andy Huang final String displayName = sender.getName(); 57665fe28fa88daad08f3be4c084ca5b4eaa366d1a7Andy Huang return TextUtils.isEmpty(displayName) ? sender.getAddress() : displayName; 577326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } 578326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira 579326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira /** 580326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira * Return the address, if a name is present, or null if not. 581326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira */ 582326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira private static CharSequence getSenderAddress(Address sender) { 5836a187d5113518435d13c60e2f1cabc418238c600Andrew Sapperstein return sender.getAddress(); 584326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } 585326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira 5863b965d78774a42358ce6bbdcc43b4c8df130a60eScott Kennedy private static void setChildVisibility(int visibility, View... children) { 58765fe28fa88daad08f3be4c084ca5b4eaa366d1a7Andy Huang for (View v : children) { 588326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira if (v != null) { 589326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira v.setVisibility(visibility); 590326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } 591326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } 592326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } 593326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira 594326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira private void setExpanded(final boolean expanded) { 595326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira // use View's 'activated' flag to store expanded state 596326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira // child view state lists can use this to toggle drawables 597326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira setActivated(expanded); 598c7543579c6a97c0ae3341578332f56d4d226f34cAndy Huang if (mMessageHeaderItem != null) { 599c7543579c6a97c0ae3341578332f56d4d226f34cAndy Huang mMessageHeaderItem.setExpanded(expanded); 600c7543579c6a97c0ae3341578332f56d4d226f34cAndy Huang } 601326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } 602326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira 603326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira /** 604326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira * Update the visibility of the many child views based on expanded/collapsed 605326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira * and draft/normal state. 606326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira */ 607326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira private void updateChildVisibility() { 608326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira // Too bad this can't be done with an XML state list... 609326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira 6104ddda2f0a4ee5381a90779a6939b05b064ce5d11Andrew Sapperstein if (mIsViewOnlyMode) { 6114ddda2f0a4ee5381a90779a6939b05b064ce5d11Andrew Sapperstein setMessageDetailsVisibility(VISIBLE); 6126a187d5113518435d13c60e2f1cabc418238c600Andrew Sapperstein setChildVisibility(GONE, mSnapHeaderBottomBorder); 6134ddda2f0a4ee5381a90779a6939b05b064ce5d11Andrew Sapperstein 6144ddda2f0a4ee5381a90779a6939b05b064ce5d11Andrew Sapperstein setChildVisibility(GONE, mReplyButton, mReplyAllButton, mForwardButton, 6154ddda2f0a4ee5381a90779a6939b05b064ce5d11Andrew Sapperstein mOverflowButton, mDraftIcon, mEditDraftButton, mStarView, 61635c3bb793ac3ea8f63ff73d282c0dabfee5a49ceAndrew Sapperstein mAttachmentIcon, mUpperDateView, mSnippetView); 61735c3bb793ac3ea8f63ff73d282c0dabfee5a49ceAndrew Sapperstein setChildVisibility(VISIBLE, mPhotoView, mSenderEmailView, mDateView); 6184ddda2f0a4ee5381a90779a6939b05b064ce5d11Andrew Sapperstein 619c5499cdd4627df39b935c3569c2b8e6e4b6ed38eAndrew Sapperstein setChildMarginEnd(mTitleContainerView, 0); 6204ddda2f0a4ee5381a90779a6939b05b064ce5d11Andrew Sapperstein } else if (isExpanded()) { 621326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira int normalVis, draftVis; 622326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira 623326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira setMessageDetailsVisibility((mIsSnappy) ? GONE : VISIBLE); 6246a187d5113518435d13c60e2f1cabc418238c600Andrew Sapperstein setChildVisibility(mIsSnappy ? VISIBLE : GONE, mSnapHeaderBottomBorder); 625326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira 626326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira if (mIsDraft) { 627326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira normalVis = GONE; 628326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira draftVis = VISIBLE; 629326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } else { 630326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira normalVis = VISIBLE; 631326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira draftVis = GONE; 632326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } 633326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira 634326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira setReplyOrReplyAllVisible(); 63514f937408fe2451a91b44d3cd7d141347e716775Andrew Sapperstein setChildVisibility(normalVis, mPhotoView, mForwardButton, mOverflowButton); 63665fe28fa88daad08f3be4c084ca5b4eaa366d1a7Andy Huang setChildVisibility(draftVis, mDraftIcon, mEditDraftButton); 63714f937408fe2451a91b44d3cd7d141347e716775Andrew Sapperstein setChildVisibility(VISIBLE, mSenderEmailView, mDateView); 63835c3bb793ac3ea8f63ff73d282c0dabfee5a49ceAndrew Sapperstein setChildVisibility(GONE, mAttachmentIcon, mUpperDateView, mSnippetView); 6390a135884c7452225bc0c86c5f768d581c0ce6c04Mark Wei setChildVisibility(mStarShown ? VISIBLE : GONE, mStarView); 640326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira 641c5499cdd4627df39b935c3569c2b8e6e4b6ed38eAndrew Sapperstein setChildMarginEnd(mTitleContainerView, 0); 642326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira 643326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } else { 644326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira 645326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira setMessageDetailsVisibility(GONE); 6466a187d5113518435d13c60e2f1cabc418238c600Andrew Sapperstein setChildVisibility(GONE, mSnapHeaderBottomBorder); 64735c3bb793ac3ea8f63ff73d282c0dabfee5a49ceAndrew Sapperstein setChildVisibility(VISIBLE, mSnippetView, mUpperDateView); 648326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira 64965fe28fa88daad08f3be4c084ca5b4eaa366d1a7Andy Huang setChildVisibility(GONE, mEditDraftButton, mReplyButton, mReplyAllButton, 65035c3bb793ac3ea8f63ff73d282c0dabfee5a49ceAndrew Sapperstein mForwardButton, mOverflowButton, mSenderEmailView, mDateView); 651326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira 65288fc42e48ee4e927eb77e5cab23f2f5151cac649Andy Huang setChildVisibility(mMessage.hasAttachments ? VISIBLE : GONE, 65365fe28fa88daad08f3be4c084ca5b4eaa366d1a7Andy Huang mAttachmentIcon); 654326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira 6550a135884c7452225bc0c86c5f768d581c0ce6c04Mark Wei setChildVisibility(mCollapsedStarVisible && mStarShown ? VISIBLE : GONE, mStarView); 656326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira 657c5499cdd4627df39b935c3569c2b8e6e4b6ed38eAndrew Sapperstein setChildMarginEnd(mTitleContainerView, mTitleContainerCollapsedMarginEnd); 658326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira 659326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira if (mIsDraft) { 660326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira 66165fe28fa88daad08f3be4c084ca5b4eaa366d1a7Andy Huang setChildVisibility(VISIBLE, mDraftIcon); 662c5499cdd4627df39b935c3569c2b8e6e4b6ed38eAndrew Sapperstein setChildVisibility(GONE, mPhotoView); 663326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira 664326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } else { 665326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira 66665fe28fa88daad08f3be4c084ca5b4eaa366d1a7Andy Huang setChildVisibility(GONE, mDraftIcon); 667c5499cdd4627df39b935c3569c2b8e6e4b6ed38eAndrew Sapperstein setChildVisibility(VISIBLE, mPhotoView); 668326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira 669326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } 670326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } 671326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } 672326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira 673326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira /** 674326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira * If an overflow menu is present in this header's layout, set the 675326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira * visibility of "Reply" and "Reply All" actions based on a user preference. 676326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira * Only one of those actions will be visible when an overflow is present. If 677326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira * no overflow is present (e.g. big phone or tablet), it's assumed we have 678326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira * plenty of screen real estate and can show both. 679326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira */ 680326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira private void setReplyOrReplyAllVisible() { 681326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira if (mIsDraft) { 68265fe28fa88daad08f3be4c084ca5b4eaa366d1a7Andy Huang setChildVisibility(GONE, mReplyButton, mReplyAllButton); 683326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira return; 68465fe28fa88daad08f3be4c084ca5b4eaa366d1a7Andy Huang } else if (mOverflowButton == null) { 68565fe28fa88daad08f3be4c084ca5b4eaa366d1a7Andy Huang setChildVisibility(VISIBLE, mReplyButton, mReplyAllButton); 686326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira return; 687326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } 688326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira 6894ddda2f0a4ee5381a90779a6939b05b064ce5d11Andrew Sapperstein final Account account = getAccount(); 6904ddda2f0a4ee5381a90779a6939b05b064ce5d11Andrew Sapperstein final boolean defaultReplyAll = (account != null) ? account.settings.replyBehavior 6914ddda2f0a4ee5381a90779a6939b05b064ce5d11Andrew Sapperstein == UIProvider.DefaultReplyBehavior.REPLY_ALL : false; 69228b7aee7fa1f7d096d33fc823a88a64f7a3fa79dAndy Huang setChildVisibility(defaultReplyAll ? GONE : VISIBLE, mReplyButton); 69328b7aee7fa1f7d096d33fc823a88a64f7a3fa79dAndy Huang setChildVisibility(defaultReplyAll ? VISIBLE : GONE, mReplyAllButton); 694326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } 695326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira 696c5499cdd4627df39b935c3569c2b8e6e4b6ed38eAndrew Sapperstein private static void setChildMarginEnd(View childView, int marginEnd) { 697326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira MarginLayoutParams mlp = (MarginLayoutParams) childView.getLayoutParams(); 698c5499cdd4627df39b935c3569c2b8e6e4b6ed38eAndrew Sapperstein if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { 699c5499cdd4627df39b935c3569c2b8e6e4b6ed38eAndrew Sapperstein mlp.setMarginEnd(marginEnd); 700c5499cdd4627df39b935c3569c2b8e6e4b6ed38eAndrew Sapperstein } else { 701c5499cdd4627df39b935c3569c2b8e6e4b6ed38eAndrew Sapperstein mlp.rightMargin = marginEnd; 702c5499cdd4627df39b935c3569c2b8e6e4b6ed38eAndrew Sapperstein } 703326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira childView.setLayoutParams(mlp); 704326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } 705326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira 706a8dc86faac4d1ac07901be75dc92b7a877ca46ffVikram Aggarwal /** 707326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira * Utility class to build a list of recipient lists. 708326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira */ 709326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira private static class RecipientListsBuilder { 710326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira private final Context mContext; 711326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira private final String mMe; 7127faa4d0a0ee25200f4fdc6dee30bb98b8e18b24aVikram Aggarwal private final String mMyName; 713326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira private final SpannableStringBuilder mBuilder = new SpannableStringBuilder(); 714326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira private final CharSequence mComma; 71565fe28fa88daad08f3be4c084ca5b4eaa366d1a7Andy Huang private final Map<String, Address> mAddressCache; 7167faa4d0a0ee25200f4fdc6dee30bb98b8e18b24aVikram Aggarwal private final VeiledAddressMatcher mMatcher; 717326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira 718326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira int mRecipientCount = 0; 719326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira boolean mFirst = true; 720326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira 7217faa4d0a0ee25200f4fdc6dee30bb98b8e18b24aVikram Aggarwal public RecipientListsBuilder(Context context, String me, String myName, 7227faa4d0a0ee25200f4fdc6dee30bb98b8e18b24aVikram Aggarwal Map<String, Address> addressCache, VeiledAddressMatcher matcher) { 723326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira mContext = context; 724326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira mMe = me; 7257faa4d0a0ee25200f4fdc6dee30bb98b8e18b24aVikram Aggarwal mMyName = myName; 726326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira mComma = mContext.getText(R.string.enumeration_comma); 72765fe28fa88daad08f3be4c084ca5b4eaa366d1a7Andy Huang mAddressCache = addressCache; 7287faa4d0a0ee25200f4fdc6dee30bb98b8e18b24aVikram Aggarwal mMatcher = matcher; 729326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } 730326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira 731326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira public void append(String[] recipients, int headingRes) { 732326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira int addLimit = SUMMARY_MAX_RECIPIENTS - mRecipientCount; 733326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira CharSequence recipientList = getSummaryTextForHeading(headingRes, recipients, addLimit); 734326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira if (recipientList != null) { 735326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira // duplicate TextUtils.join() logic to minimize temporary 736326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira // allocations, and because we need to support spans 737326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira if (mFirst) { 738326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira mFirst = false; 739326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } else { 740326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira mBuilder.append(RECIPIENT_HEADING_DELIMITER); 741326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } 742326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira mBuilder.append(recipientList); 743326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira mRecipientCount += Math.min(addLimit, recipients.length); 744326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } 745326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } 746326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira 747326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira private CharSequence getSummaryTextForHeading(int headingStrRes, String[] rawAddrs, 748326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira int maxToCopy) { 749326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira if (rawAddrs == null || rawAddrs.length == 0 || maxToCopy == 0) { 750326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira return null; 751326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } 752326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira 753326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira SpannableStringBuilder ssb = new SpannableStringBuilder( 754326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira mContext.getString(headingStrRes)); 75535c3bb793ac3ea8f63ff73d282c0dabfee5a49ceAndrew Sapperstein ssb.setSpan(new StyleSpan(Typeface.NORMAL), 0, ssb.length(), 756326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); 757326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira 758326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira final int len = Math.min(maxToCopy, rawAddrs.length); 759326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira boolean first = true; 760326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira for (int i = 0; i < len; i++) { 7617faa4d0a0ee25200f4fdc6dee30bb98b8e18b24aVikram Aggarwal final Address email = getAddress(mAddressCache, rawAddrs[i]); 7627faa4d0a0ee25200f4fdc6dee30bb98b8e18b24aVikram Aggarwal final String emailAddress = email.getAddress(); 7637faa4d0a0ee25200f4fdc6dee30bb98b8e18b24aVikram Aggarwal final String name; 7644ddda2f0a4ee5381a90779a6939b05b064ce5d11Andrew Sapperstein if (mMatcher != null && mMatcher.isVeiledAddress(emailAddress)) { 7657faa4d0a0ee25200f4fdc6dee30bb98b8e18b24aVikram Aggarwal if (TextUtils.isEmpty(email.getName())) { 7667faa4d0a0ee25200f4fdc6dee30bb98b8e18b24aVikram Aggarwal // Let's write something more readable. 7677faa4d0a0ee25200f4fdc6dee30bb98b8e18b24aVikram Aggarwal name = mContext.getString(VeiledAddressMatcher.VEILED_SUMMARY_UNKNOWN); 7687faa4d0a0ee25200f4fdc6dee30bb98b8e18b24aVikram Aggarwal } else { 7697faa4d0a0ee25200f4fdc6dee30bb98b8e18b24aVikram Aggarwal name = email.getSimplifiedName(); 7707faa4d0a0ee25200f4fdc6dee30bb98b8e18b24aVikram Aggarwal } 7717faa4d0a0ee25200f4fdc6dee30bb98b8e18b24aVikram Aggarwal } else { 7727faa4d0a0ee25200f4fdc6dee30bb98b8e18b24aVikram Aggarwal // Not a veiled address, show first part of email, or "me". 7737faa4d0a0ee25200f4fdc6dee30bb98b8e18b24aVikram Aggarwal name = mMe.equals(emailAddress) ? mMyName : email.getSimplifiedName(); 7747faa4d0a0ee25200f4fdc6dee30bb98b8e18b24aVikram Aggarwal } 775326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira 776326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira // duplicate TextUtils.join() logic to minimize temporary 777326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira // allocations, and because we need to support spans 778326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira if (first) { 779326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira first = false; 780326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } else { 781326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira ssb.append(mComma); 782326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } 783326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira ssb.append(name); 784326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } 785326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira 786326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira return ssb; 787326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } 788326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira 789326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira public CharSequence build() { 790326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira return mBuilder; 791326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } 792326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } 793326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira 794326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira @VisibleForTesting 7957faa4d0a0ee25200f4fdc6dee30bb98b8e18b24aVikram Aggarwal static CharSequence getRecipientSummaryText(Context context, String me, String myName, 7967faa4d0a0ee25200f4fdc6dee30bb98b8e18b24aVikram Aggarwal String[] to, String[] cc, String[] bcc, Map<String, Address> addressCache, 7977faa4d0a0ee25200f4fdc6dee30bb98b8e18b24aVikram Aggarwal VeiledAddressMatcher matcher) { 798326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira 7997faa4d0a0ee25200f4fdc6dee30bb98b8e18b24aVikram Aggarwal final RecipientListsBuilder builder = 8007faa4d0a0ee25200f4fdc6dee30bb98b8e18b24aVikram Aggarwal new RecipientListsBuilder(context, me, myName, addressCache, matcher); 801326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira 802326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira builder.append(to, R.string.to_heading); 803326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira builder.append(cc, R.string.cc_heading); 804326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira builder.append(bcc, R.string.bcc_heading); 805326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira 806326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira return builder.build(); 807326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } 808326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira 80931c38a8247b4583ac1cc506acf8454d8922ee491Andy Huang private void updateContactInfo() { 810326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira if (mContactInfoSource == null || mSender == null) { 811326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira mPhotoView.setImageToDefault(); 812326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira mPhotoView.setContentDescription(getResources().getString( 813326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira R.string.contact_info_string_default)); 814326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira return; 815326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } 816326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira 817326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira // Set the photo to either a found Bitmap or the default 818326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira // and ensure either the contact URI or email is set so the click 819326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira // handling works 820326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira String contentDesc = getResources().getString(R.string.contact_info_string, 821326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira !TextUtils.isEmpty(mSender.getName()) ? mSender.getName() : mSender.getAddress()); 822326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira mPhotoView.setContentDescription(contentDesc); 823326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira boolean photoSet = false; 824c5499cdd4627df39b935c3569c2b8e6e4b6ed38eAndrew Sapperstein final String email = mSender.getAddress(); 825c5499cdd4627df39b935c3569c2b8e6e4b6ed38eAndrew Sapperstein final ContactInfo info = mContactInfoSource.getContactInfo(email); 826326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira if (info != null) { 827326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira mPhotoView.assignContactUri(info.contactUri); 828326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira if (info.photo != null) { 829326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira mPhotoView.setImageBitmap(info.photo); 830326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira photoSet = true; 831326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } 832326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } else { 833326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira mPhotoView.assignContactFromEmail(email, true /* lazyLookup */); 834326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } 835326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira 836326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira if (!photoSet) { 8375fbc58bc22df9642385e35da34f0ba8e218620b4Andrew Sapperstein mPhotoView.setImageBitmap(makeLetterTile(mSender.getName(), email)); 838326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } 839326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } 840326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira 841c5499cdd4627df39b935c3569c2b8e6e4b6ed38eAndrew Sapperstein private Bitmap makeLetterTile( 8425fbc58bc22df9642385e35da34f0ba8e218620b4Andrew Sapperstein String displayName, String senderAddress) { 8435fbc58bc22df9642385e35da34f0ba8e218620b4Andrew Sapperstein if (mLetterTileProvider == null) { 8445fbc58bc22df9642385e35da34f0ba8e218620b4Andrew Sapperstein mLetterTileProvider = new LetterTileProvider(getContext()); 845c5499cdd4627df39b935c3569c2b8e6e4b6ed38eAndrew Sapperstein } 8465fbc58bc22df9642385e35da34f0ba8e218620b4Andrew Sapperstein 8475fbc58bc22df9642385e35da34f0ba8e218620b4Andrew Sapperstein final ImageCanvas.Dimensions dimensions = new ImageCanvas.Dimensions( 8485fbc58bc22df9642385e35da34f0ba8e218620b4Andrew Sapperstein mContactPhotoWidth, mContactPhotoHeight, ImageCanvas.Dimensions.SCALE_ONE); 8495fbc58bc22df9642385e35da34f0ba8e218620b4Andrew Sapperstein return mLetterTileProvider.getLetterTile(dimensions, displayName, senderAddress); 850c5499cdd4627df39b935c3569c2b8e6e4b6ed38eAndrew Sapperstein } 851c5499cdd4627df39b935c3569c2b8e6e4b6ed38eAndrew Sapperstein 852326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira 853326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira @Override 854326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira public boolean onMenuItemClick(MenuItem item) { 855326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira mPopup.dismiss(); 856326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira return onClick(null, item.getItemId()); 857326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } 858326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira 859326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira @Override 860326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira public void onClick(View v) { 861326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira onClick(v, v.getId()); 862326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } 863326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira 864326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira /** 865326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira * Handles clicks on either views or menu items. View parameter can be null 866326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira * for menu item clicks. 867326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira */ 8682b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy public boolean onClick(final View v, final int id) { 869e952353a26db3e2e6e422072daf2213e5f7b9f82Andy Huang if (mMessage == null) { 870e952353a26db3e2e6e422072daf2213e5f7b9f82Andy Huang LogUtils.i(LOG_TAG, "ignoring message header tap on unbound view"); 871e952353a26db3e2e6e422072daf2213e5f7b9f82Andy Huang return false; 872e952353a26db3e2e6e422072daf2213e5f7b9f82Andy Huang } 873e952353a26db3e2e6e422072daf2213e5f7b9f82Andy Huang 874326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira boolean handled = true; 875326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira 8762b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy if (id == R.id.reply) { 8772b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy ComposeActivity.reply(getContext(), getAccount(), mMessage); 8782b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy } else if (id == R.id.reply_all) { 8792b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy ComposeActivity.replyAll(getContext(), getAccount(), mMessage); 8802b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy } else if (id == R.id.forward) { 8812b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy ComposeActivity.forward(getContext(), getAccount(), mMessage); 8822b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy } else if (id == R.id.report_rendering_problem) { 8832b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy final String text = getContext().getString(R.string.report_rendering_problem_desc); 8842b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy ComposeActivity.reportRenderingFeedback(getContext(), getAccount(), mMessage, 8852b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy text + "\n\n" + mCallbacks.getMessageTransforms(mMessage)); 8862b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy } else if (id == R.id.report_rendering_improvement) { 8872b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy final String text = getContext().getString(R.string.report_rendering_improvement_desc); 8882b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy ComposeActivity.reportRenderingFeedback(getContext(), getAccount(), mMessage, 8892b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy text + "\n\n" + mCallbacks.getMessageTransforms(mMessage)); 8902b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy } else if (id == R.id.star) { 8912b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy final boolean newValue = !v.isSelected(); 8922b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy v.setSelected(newValue); 8932b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy mMessage.star(newValue); 8942b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy } else if (id == R.id.edit_draft) { 8952b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy ComposeActivity.editDraft(getContext(), getAccount(), mMessage); 8962b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy } else if (id == R.id.overflow) { 8972b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy if (mPopup == null) { 8982b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy mPopup = new PopupMenu(getContext(), v); 8992b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy mPopup.getMenuInflater().inflate(R.menu.message_header_overflow_menu, 9002b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy mPopup.getMenu()); 9012b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy mPopup.setOnMenuItemClickListener(this); 902326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } 9032b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy final boolean defaultReplyAll = getAccount().settings.replyBehavior 9042b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy == UIProvider.DefaultReplyBehavior.REPLY_ALL; 9052b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy final Menu m = mPopup.getMenu(); 9062b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy m.findItem(R.id.reply).setVisible(defaultReplyAll); 9072b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy m.findItem(R.id.reply_all).setVisible(!defaultReplyAll); 9082b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy 9092b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy final boolean reportRendering = ENABLE_REPORT_RENDERING_PROBLEM 9102b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy && mCallbacks.supportsMessageTransforms(); 9112b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy m.findItem(R.id.report_rendering_improvement).setVisible(reportRendering); 9122b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy m.findItem(R.id.report_rendering_problem).setVisible(reportRendering); 9132b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy 9142b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy mPopup.show(); 9152b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy } else if (id == R.id.details_collapsed_content 9162b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy || id == R.id.details_expanded_content) { 9172b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy toggleMessageDetails(v); 9182b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy } else if (id == R.id.upper_header) { 9192b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy toggleExpanded(); 9202b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy } else if (id == R.id.show_pictures_text) { 9212b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy handleShowImagePromptClick(v); 9222b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy } else { 9232b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy LogUtils.i(LOG_TAG, "unrecognized header tap: %d", id); 9242b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy handled = false; 925326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } 926326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira return handled; 927326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } 928326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira 9294ddda2f0a4ee5381a90779a6939b05b064ce5d11Andrew Sapperstein /** 9304ddda2f0a4ee5381a90779a6939b05b064ce5d11Andrew Sapperstein * Set to true if the user should not be able to perfrom message actions 9314ddda2f0a4ee5381a90779a6939b05b064ce5d11Andrew Sapperstein * on the message such as reply/reply all/forward/star/etc. 9324ddda2f0a4ee5381a90779a6939b05b064ce5d11Andrew Sapperstein * 9334ddda2f0a4ee5381a90779a6939b05b064ce5d11Andrew Sapperstein * Default is false. 9344ddda2f0a4ee5381a90779a6939b05b064ce5d11Andrew Sapperstein */ 9354ddda2f0a4ee5381a90779a6939b05b064ce5d11Andrew Sapperstein public void setViewOnlyMode(boolean isViewOnlyMode) { 9364ddda2f0a4ee5381a90779a6939b05b064ce5d11Andrew Sapperstein mIsViewOnlyMode = isViewOnlyMode; 9374ddda2f0a4ee5381a90779a6939b05b064ce5d11Andrew Sapperstein } 9384ddda2f0a4ee5381a90779a6939b05b064ce5d11Andrew Sapperstein 939f4fce1227d8b49f45e6569f1590565f2df9e8d6emindyp public void setExpandable(boolean expandable) { 940f4fce1227d8b49f45e6569f1590565f2df9e8d6emindyp mExpandable = expandable; 941f4fce1227d8b49f45e6569f1590565f2df9e8d6emindyp } 942f4fce1227d8b49f45e6569f1590565f2df9e8d6emindyp 943326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira public void toggleExpanded() { 944f4fce1227d8b49f45e6569f1590565f2df9e8d6emindyp if (!mExpandable) { 945f4fce1227d8b49f45e6569f1590565f2df9e8d6emindyp return; 946f4fce1227d8b49f45e6569f1590565f2df9e8d6emindyp } 947c7543579c6a97c0ae3341578332f56d4d226f34cAndy Huang setExpanded(!isExpanded()); 948326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira 949f69a05bc8aabf7d3ae37b1f7ba76ac0a5eeb252dmindyp // The snappy header will disappear; no reason to update text. 950f69a05bc8aabf7d3ae37b1f7ba76ac0a5eeb252dmindyp if (!mIsSnappy) { 951f69a05bc8aabf7d3ae37b1f7ba76ac0a5eeb252dmindyp mSenderNameView.setText(getHeaderTitle()); 952f69a05bc8aabf7d3ae37b1f7ba76ac0a5eeb252dmindyp mSenderEmailView.setText(getHeaderSubtitle()); 95314f937408fe2451a91b44d3cd7d141347e716775Andrew Sapperstein mDateView.setText(mMessageHeaderItem.getTimestampLong()); 95435c3bb793ac3ea8f63ff73d282c0dabfee5a49ceAndrew Sapperstein mSnippetView.setText(mSnippet); 955f69a05bc8aabf7d3ae37b1f7ba76ac0a5eeb252dmindyp } 956326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira 957326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira updateChildVisibility(); 958326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira 959cee3c90574b48ccaa0f8b9f9341383c231ed41d2Andrew Sapperstein final BorderHeights borderHeights = updateBorderExpandedState(); 960cee3c90574b48ccaa0f8b9f9341383c231ed41d2Andrew Sapperstein 961326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira // Force-measure the new header height so we can set the spacer size and 962f69a05bc8aabf7d3ae37b1f7ba76ac0a5eeb252dmindyp // reveal the message div in one pass. Force-measuring makes it unnecessary to set 963326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira // mSizeChanged. 964c7543579c6a97c0ae3341578332f56d4d226f34cAndy Huang int h = measureHeight(); 965c7543579c6a97c0ae3341578332f56d4d226f34cAndy Huang mMessageHeaderItem.setHeight(h); 966326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira if (mCallbacks != null) { 967cee3c90574b48ccaa0f8b9f9341383c231ed41d2Andrew Sapperstein mCallbacks.setMessageExpanded(mMessageHeaderItem, h, 968cee3c90574b48ccaa0f8b9f9341383c231ed41d2Andrew Sapperstein borderHeights.topHeight, borderHeights.bottomHeight); 969cee3c90574b48ccaa0f8b9f9341383c231ed41d2Andrew Sapperstein } 970cee3c90574b48ccaa0f8b9f9341383c231ed41d2Andrew Sapperstein } 971cee3c90574b48ccaa0f8b9f9341383c231ed41d2Andrew Sapperstein 972cee3c90574b48ccaa0f8b9f9341383c231ed41d2Andrew Sapperstein /** 973cee3c90574b48ccaa0f8b9f9341383c231ed41d2Andrew Sapperstein * Checks the neighboring messages to this message and 974cee3c90574b48ccaa0f8b9f9341383c231ed41d2Andrew Sapperstein * updates the {@link BorderItem}s of the borders of this message 975cee3c90574b48ccaa0f8b9f9341383c231ed41d2Andrew Sapperstein * in case they should be collapsed or expanded. 976cee3c90574b48ccaa0f8b9f9341383c231ed41d2Andrew Sapperstein * @return a {@link BorderHeights} object containing 977cee3c90574b48ccaa0f8b9f9341383c231ed41d2Andrew Sapperstein * the new heights of the top and bottom borders. 978cee3c90574b48ccaa0f8b9f9341383c231ed41d2Andrew Sapperstein */ 979cee3c90574b48ccaa0f8b9f9341383c231ed41d2Andrew Sapperstein private BorderHeights updateBorderExpandedState() { 980cee3c90574b48ccaa0f8b9f9341383c231ed41d2Andrew Sapperstein final int position = mMessageHeaderItem.getPosition(); 981cee3c90574b48ccaa0f8b9f9341383c231ed41d2Andrew Sapperstein final boolean isExpanded = mMessageHeaderItem.isExpanded(); 982cee3c90574b48ccaa0f8b9f9341383c231ed41d2Andrew Sapperstein final int abovePosition = position - 2; // position of MessageFooterItem above header 983cee3c90574b48ccaa0f8b9f9341383c231ed41d2Andrew Sapperstein final int belowPosition = position + 3; // position of next MessageHeaderItem 984cee3c90574b48ccaa0f8b9f9341383c231ed41d2Andrew Sapperstein final ConversationViewAdapter adapter = mMessageHeaderItem.getAdapter(); 985cee3c90574b48ccaa0f8b9f9341383c231ed41d2Andrew Sapperstein final int size = adapter.getCount(); 986cee3c90574b48ccaa0f8b9f9341383c231ed41d2Andrew Sapperstein final BorderHeights borderHeights = new BorderHeights(); 987cee3c90574b48ccaa0f8b9f9341383c231ed41d2Andrew Sapperstein 988cee3c90574b48ccaa0f8b9f9341383c231ed41d2Andrew Sapperstein // if an above message exists, update the border above this message 989cee3c90574b48ccaa0f8b9f9341383c231ed41d2Andrew Sapperstein if (isValidPosition(abovePosition, size)) { 990cee3c90574b48ccaa0f8b9f9341383c231ed41d2Andrew Sapperstein final ConversationOverlayItem item = adapter.getItem(abovePosition); 991cee3c90574b48ccaa0f8b9f9341383c231ed41d2Andrew Sapperstein final int type = item.getType(); 992cee3c90574b48ccaa0f8b9f9341383c231ed41d2Andrew Sapperstein if (type == ConversationViewAdapter.VIEW_TYPE_MESSAGE_FOOTER || 993cee3c90574b48ccaa0f8b9f9341383c231ed41d2Andrew Sapperstein type == ConversationViewAdapter.VIEW_TYPE_SUPER_COLLAPSED_BLOCK) { 994cee3c90574b48ccaa0f8b9f9341383c231ed41d2Andrew Sapperstein final BorderItem borderItem = (BorderItem) adapter.getItem(abovePosition + 1); 995cee3c90574b48ccaa0f8b9f9341383c231ed41d2Andrew Sapperstein final boolean borderIsExpanded = isExpanded || item.isExpanded(); 996cee3c90574b48ccaa0f8b9f9341383c231ed41d2Andrew Sapperstein borderItem.setExpanded(borderIsExpanded); 997cee3c90574b48ccaa0f8b9f9341383c231ed41d2Andrew Sapperstein borderHeights.topHeight = borderIsExpanded ? 998cee3c90574b48ccaa0f8b9f9341383c231ed41d2Andrew Sapperstein BorderView.getExpandedHeight() : BorderView.getCollapsedHeight(); 999cee3c90574b48ccaa0f8b9f9341383c231ed41d2Andrew Sapperstein borderItem.setHeight(borderHeights.topHeight); 1000cee3c90574b48ccaa0f8b9f9341383c231ed41d2Andrew Sapperstein } 1001cee3c90574b48ccaa0f8b9f9341383c231ed41d2Andrew Sapperstein } 1002cee3c90574b48ccaa0f8b9f9341383c231ed41d2Andrew Sapperstein 1003cee3c90574b48ccaa0f8b9f9341383c231ed41d2Andrew Sapperstein 1004cee3c90574b48ccaa0f8b9f9341383c231ed41d2Andrew Sapperstein // if a below message exists, update the border below this message 1005cee3c90574b48ccaa0f8b9f9341383c231ed41d2Andrew Sapperstein if (isValidPosition(belowPosition, size)) { 1006cee3c90574b48ccaa0f8b9f9341383c231ed41d2Andrew Sapperstein final ConversationOverlayItem item = adapter.getItem(belowPosition); 1007cee3c90574b48ccaa0f8b9f9341383c231ed41d2Andrew Sapperstein if (item.getType() == ConversationViewAdapter.VIEW_TYPE_MESSAGE_HEADER) { 1008cee3c90574b48ccaa0f8b9f9341383c231ed41d2Andrew Sapperstein final BorderItem borderItem = (BorderItem) adapter.getItem(belowPosition - 1); 1009cee3c90574b48ccaa0f8b9f9341383c231ed41d2Andrew Sapperstein final boolean borderIsExpanded = isExpanded || item.isExpanded(); 1010cee3c90574b48ccaa0f8b9f9341383c231ed41d2Andrew Sapperstein borderItem.setExpanded(borderIsExpanded); 1011cee3c90574b48ccaa0f8b9f9341383c231ed41d2Andrew Sapperstein borderHeights.bottomHeight = borderIsExpanded ? 1012cee3c90574b48ccaa0f8b9f9341383c231ed41d2Andrew Sapperstein BorderView.getExpandedHeight() : BorderView.getCollapsedHeight(); 1013cee3c90574b48ccaa0f8b9f9341383c231ed41d2Andrew Sapperstein borderItem.setHeight(borderHeights.bottomHeight); 1014cee3c90574b48ccaa0f8b9f9341383c231ed41d2Andrew Sapperstein } 1015326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } 1016cee3c90574b48ccaa0f8b9f9341383c231ed41d2Andrew Sapperstein 1017cee3c90574b48ccaa0f8b9f9341383c231ed41d2Andrew Sapperstein return borderHeights; 1018cee3c90574b48ccaa0f8b9f9341383c231ed41d2Andrew Sapperstein } 1019cee3c90574b48ccaa0f8b9f9341383c231ed41d2Andrew Sapperstein 1020cee3c90574b48ccaa0f8b9f9341383c231ed41d2Andrew Sapperstein /** 1021cee3c90574b48ccaa0f8b9f9341383c231ed41d2Andrew Sapperstein * A plain-old-data class used to return the new heights of the top and bottom borders 1022cee3c90574b48ccaa0f8b9f9341383c231ed41d2Andrew Sapperstein * in {@link #updateBorderExpandedState()}. 1023cee3c90574b48ccaa0f8b9f9341383c231ed41d2Andrew Sapperstein * If {@link #topHeight} or {@link #bottomHeight} are -1 after returning, 1024cee3c90574b48ccaa0f8b9f9341383c231ed41d2Andrew Sapperstein * do not update the heights of the spacer for their respective borders 1025cee3c90574b48ccaa0f8b9f9341383c231ed41d2Andrew Sapperstein * as their state has not changed. 1026cee3c90574b48ccaa0f8b9f9341383c231ed41d2Andrew Sapperstein */ 1027cee3c90574b48ccaa0f8b9f9341383c231ed41d2Andrew Sapperstein private class BorderHeights { 1028cee3c90574b48ccaa0f8b9f9341383c231ed41d2Andrew Sapperstein public int topHeight = -1; 1029cee3c90574b48ccaa0f8b9f9341383c231ed41d2Andrew Sapperstein public int bottomHeight = -1; 1030cee3c90574b48ccaa0f8b9f9341383c231ed41d2Andrew Sapperstein } 1031cee3c90574b48ccaa0f8b9f9341383c231ed41d2Andrew Sapperstein 1032cee3c90574b48ccaa0f8b9f9341383c231ed41d2Andrew Sapperstein private boolean isValidPosition(int position, int size) { 1033cee3c90574b48ccaa0f8b9f9341383c231ed41d2Andrew Sapperstein return position >= 0 && position < size; 1034326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } 1035326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira 1036326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira private void toggleMessageDetails(View visibleDetailsView) { 10371b3cc47f54072105c161d6ed557550e0e149b8bbmindyp int heightBefore = measureHeight(); 1038c7543579c6a97c0ae3341578332f56d4d226f34cAndy Huang final boolean detailsExpanded = (visibleDetailsView == mCollapsedDetailsView); 1039c7543579c6a97c0ae3341578332f56d4d226f34cAndy Huang setMessageDetailsExpanded(detailsExpanded); 1040c7543579c6a97c0ae3341578332f56d4d226f34cAndy Huang updateSpacerHeight(); 10411b3cc47f54072105c161d6ed557550e0e149b8bbmindyp if (mCallbacks != null) { 10421b3cc47f54072105c161d6ed557550e0e149b8bbmindyp mCallbacks.setMessageDetailsExpanded(mMessageHeaderItem, detailsExpanded, heightBefore); 10431b3cc47f54072105c161d6ed557550e0e149b8bbmindyp } 1044326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } 1045326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira 1046326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira private void setMessageDetailsExpanded(boolean expand) { 104777a4605e6fbc368b2b87b4888f2ffd6329620807mindyp if (mExpandMode == DEFAULT_MODE) { 104877a4605e6fbc368b2b87b4888f2ffd6329620807mindyp if (expand) { 104977a4605e6fbc368b2b87b4888f2ffd6329620807mindyp showExpandedDetails(); 105077a4605e6fbc368b2b87b4888f2ffd6329620807mindyp hideCollapsedDetails(); 105177a4605e6fbc368b2b87b4888f2ffd6329620807mindyp } else { 105277a4605e6fbc368b2b87b4888f2ffd6329620807mindyp hideExpandedDetails(); 105377a4605e6fbc368b2b87b4888f2ffd6329620807mindyp showCollapsedDetails(); 105477a4605e6fbc368b2b87b4888f2ffd6329620807mindyp } 105577a4605e6fbc368b2b87b4888f2ffd6329620807mindyp } else if (mExpandMode == POPUP_MODE) { 105677a4605e6fbc368b2b87b4888f2ffd6329620807mindyp if (expand) { 105777a4605e6fbc368b2b87b4888f2ffd6329620807mindyp showDetailsPopup(); 105877a4605e6fbc368b2b87b4888f2ffd6329620807mindyp } else { 105977a4605e6fbc368b2b87b4888f2ffd6329620807mindyp hideDetailsPopup(); 106077a4605e6fbc368b2b87b4888f2ffd6329620807mindyp showCollapsedDetails(); 106177a4605e6fbc368b2b87b4888f2ffd6329620807mindyp } 1062326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } 1063c7543579c6a97c0ae3341578332f56d4d226f34cAndy Huang if (mMessageHeaderItem != null) { 1064c7543579c6a97c0ae3341578332f56d4d226f34cAndy Huang mMessageHeaderItem.detailsExpanded = expand; 1065c7543579c6a97c0ae3341578332f56d4d226f34cAndy Huang } 1066326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } 1067326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira 1068326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira public void setMessageDetailsVisibility(int vis) { 1069326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira if (vis == GONE) { 1070326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira hideCollapsedDetails(); 1071326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira hideExpandedDetails(); 10723b08c51ec46794b3c22c8649eb86bf77c72e0d9aAndrew Sapperstein hideSpamWarning(); 1073326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira hideShowImagePrompt(); 1074a71f1f3368f26b6627512298f64484611fd6b0e8Andy Huang hideInvite(); 10752b7bbb53344b1e2c1d970a8da051a7431565db1fRohan Shah mUpperHeaderView.setOnCreateContextMenuListener(null); 1076326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } else { 1077c7543579c6a97c0ae3341578332f56d4d226f34cAndy Huang setMessageDetailsExpanded(mMessageHeaderItem.detailsExpanded); 10783b08c51ec46794b3c22c8649eb86bf77c72e0d9aAndrew Sapperstein if (mMessage.spamWarningString == null) { 10793b08c51ec46794b3c22c8649eb86bf77c72e0d9aAndrew Sapperstein hideSpamWarning(); 10803b08c51ec46794b3c22c8649eb86bf77c72e0d9aAndrew Sapperstein } else { 10813b08c51ec46794b3c22c8649eb86bf77c72e0d9aAndrew Sapperstein showSpamWarning(); 10823b08c51ec46794b3c22c8649eb86bf77c72e0d9aAndrew Sapperstein } 1083326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira if (mShowImagePrompt) { 1084202738427ede23dd5863583aa3df17e4abfbf5e2Scott Kennedy if (mMessageHeaderItem.getShowImages()) { 1085202738427ede23dd5863583aa3df17e4abfbf5e2Scott Kennedy showImagePromptAlways(true); 1086202738427ede23dd5863583aa3df17e4abfbf5e2Scott Kennedy } else { 1087202738427ede23dd5863583aa3df17e4abfbf5e2Scott Kennedy showImagePromptOnce(); 1088202738427ede23dd5863583aa3df17e4abfbf5e2Scott Kennedy } 10893233bff8ae08a56543c9f5abf1bc6ab38f0574ceAndy Huang } else { 10903233bff8ae08a56543c9f5abf1bc6ab38f0574ceAndy Huang hideShowImagePrompt(); 1091326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } 1092a71f1f3368f26b6627512298f64484611fd6b0e8Andy Huang if (mMessage.isFlaggedCalendarInvite()) { 1093a71f1f3368f26b6627512298f64484611fd6b0e8Andy Huang showInvite(); 1094a71f1f3368f26b6627512298f64484611fd6b0e8Andy Huang } else { 1095a71f1f3368f26b6627512298f64484611fd6b0e8Andy Huang hideInvite(); 1096a71f1f3368f26b6627512298f64484611fd6b0e8Andy Huang } 10972b7bbb53344b1e2c1d970a8da051a7431565db1fRohan Shah mUpperHeaderView.setOnCreateContextMenuListener(mEmailCopyMenu); 1098326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } 1099326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } 1100326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira 1101326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira public void hideMessageDetails() { 1102326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira setMessageDetailsVisibility(GONE); 1103326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } 1104326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira 1105326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira private void hideCollapsedDetails() { 1106326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira if (mCollapsedDetailsView != null) { 1107326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira mCollapsedDetailsView.setVisibility(GONE); 1108326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } 1109326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } 1110326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira 1111326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira private void hideExpandedDetails() { 1112326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira if (mExpandedDetailsView != null) { 1113326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira mExpandedDetailsView.setVisibility(GONE); 1114326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } 1115326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } 1116326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira 1117a71f1f3368f26b6627512298f64484611fd6b0e8Andy Huang private void hideInvite() { 1118a71f1f3368f26b6627512298f64484611fd6b0e8Andy Huang if (mInviteView != null) { 1119a71f1f3368f26b6627512298f64484611fd6b0e8Andy Huang mInviteView.setVisibility(GONE); 1120a71f1f3368f26b6627512298f64484611fd6b0e8Andy Huang } 1121a71f1f3368f26b6627512298f64484611fd6b0e8Andy Huang } 1122a71f1f3368f26b6627512298f64484611fd6b0e8Andy Huang 1123a71f1f3368f26b6627512298f64484611fd6b0e8Andy Huang private void showInvite() { 1124a71f1f3368f26b6627512298f64484611fd6b0e8Andy Huang if (mInviteView == null) { 1125a71f1f3368f26b6627512298f64484611fd6b0e8Andy Huang mInviteView = (MessageInviteView) mInflater.inflate( 1126a71f1f3368f26b6627512298f64484611fd6b0e8Andy Huang R.layout.conversation_message_invite, this, false); 11272862cba002c7805a8f8e28146c6d5504831dcec7Andrew Sapperstein mExtraContentView.addView(mInviteView); 1128a71f1f3368f26b6627512298f64484611fd6b0e8Andy Huang } 1129a71f1f3368f26b6627512298f64484611fd6b0e8Andy Huang mInviteView.bind(mMessage); 1130a71f1f3368f26b6627512298f64484611fd6b0e8Andy Huang mInviteView.setVisibility(VISIBLE); 1131a71f1f3368f26b6627512298f64484611fd6b0e8Andy Huang } 1132a71f1f3368f26b6627512298f64484611fd6b0e8Andy Huang 1133326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira private void hideShowImagePrompt() { 1134326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira if (mImagePromptView != null) { 1135326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira mImagePromptView.setVisibility(GONE); 1136326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } 1137326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } 1138326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira 1139202738427ede23dd5863583aa3df17e4abfbf5e2Scott Kennedy private void showImagePromptOnce() { 1140326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira if (mImagePromptView == null) { 114114f937408fe2451a91b44d3cd7d141347e716775Andrew Sapperstein mImagePromptView = (TextView) mInflater.inflate( 114214f937408fe2451a91b44d3cd7d141347e716775Andrew Sapperstein R.layout.conversation_message_show_pics, this, false); 11432862cba002c7805a8f8e28146c6d5504831dcec7Andrew Sapperstein mExtraContentView.addView(mImagePromptView); 114414f937408fe2451a91b44d3cd7d141347e716775Andrew Sapperstein mImagePromptView.setOnClickListener(this); 1145326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } 1146326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira mImagePromptView.setVisibility(VISIBLE); 114714f937408fe2451a91b44d3cd7d141347e716775Andrew Sapperstein mImagePromptView.setText(R.string.show_images); 1148eb9a4bdc53269ee05fe11870b9ebf03f18196585Scott Kennedy mImagePromptView.setTag(SHOW_IMAGE_PROMPT_ONCE); 1149326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } 1150326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira 1151202738427ede23dd5863583aa3df17e4abfbf5e2Scott Kennedy /** 1152202738427ede23dd5863583aa3df17e4abfbf5e2Scott Kennedy * Shows the "Always show pictures" message 1153202738427ede23dd5863583aa3df17e4abfbf5e2Scott Kennedy * 1154202738427ede23dd5863583aa3df17e4abfbf5e2Scott Kennedy * @param initialShowing <code>true</code> if this is the first time we are showing the prompt 1155202738427ede23dd5863583aa3df17e4abfbf5e2Scott Kennedy * for "show images", <code>false</code> if we are transitioning from "Show pictures" 1156202738427ede23dd5863583aa3df17e4abfbf5e2Scott Kennedy */ 1157202738427ede23dd5863583aa3df17e4abfbf5e2Scott Kennedy private void showImagePromptAlways(final boolean initialShowing) { 1158202738427ede23dd5863583aa3df17e4abfbf5e2Scott Kennedy if (initialShowing) { 1159202738427ede23dd5863583aa3df17e4abfbf5e2Scott Kennedy // Initialize the view 1160202738427ede23dd5863583aa3df17e4abfbf5e2Scott Kennedy showImagePromptOnce(); 1161202738427ede23dd5863583aa3df17e4abfbf5e2Scott Kennedy } 1162202738427ede23dd5863583aa3df17e4abfbf5e2Scott Kennedy 116314f937408fe2451a91b44d3cd7d141347e716775Andrew Sapperstein mImagePromptView.setText(R.string.always_show_images); 1164202738427ede23dd5863583aa3df17e4abfbf5e2Scott Kennedy mImagePromptView.setTag(SHOW_IMAGE_PROMPT_ALWAYS); 1165202738427ede23dd5863583aa3df17e4abfbf5e2Scott Kennedy 1166202738427ede23dd5863583aa3df17e4abfbf5e2Scott Kennedy if (!initialShowing) { 1167202738427ede23dd5863583aa3df17e4abfbf5e2Scott Kennedy // the new text's line count may differ, so update the spacer height 1168202738427ede23dd5863583aa3df17e4abfbf5e2Scott Kennedy updateSpacerHeight(); 1169202738427ede23dd5863583aa3df17e4abfbf5e2Scott Kennedy } 1170202738427ede23dd5863583aa3df17e4abfbf5e2Scott Kennedy } 1171202738427ede23dd5863583aa3df17e4abfbf5e2Scott Kennedy 11723b08c51ec46794b3c22c8649eb86bf77c72e0d9aAndrew Sapperstein private void hideSpamWarning() { 11733b08c51ec46794b3c22c8649eb86bf77c72e0d9aAndrew Sapperstein if (mSpamWarningView != null) { 11743b08c51ec46794b3c22c8649eb86bf77c72e0d9aAndrew Sapperstein mSpamWarningView.setVisibility(GONE); 11753b08c51ec46794b3c22c8649eb86bf77c72e0d9aAndrew Sapperstein } 11763b08c51ec46794b3c22c8649eb86bf77c72e0d9aAndrew Sapperstein } 11773b08c51ec46794b3c22c8649eb86bf77c72e0d9aAndrew Sapperstein 11783b08c51ec46794b3c22c8649eb86bf77c72e0d9aAndrew Sapperstein private void showSpamWarning() { 11793b08c51ec46794b3c22c8649eb86bf77c72e0d9aAndrew Sapperstein if (mSpamWarningView == null) { 11803b08c51ec46794b3c22c8649eb86bf77c72e0d9aAndrew Sapperstein mSpamWarningView = (SpamWarningView) 11813b08c51ec46794b3c22c8649eb86bf77c72e0d9aAndrew Sapperstein mInflater.inflate(R.layout.conversation_message_spam_warning, this, false); 11822862cba002c7805a8f8e28146c6d5504831dcec7Andrew Sapperstein mExtraContentView.addView(mSpamWarningView); 11833b08c51ec46794b3c22c8649eb86bf77c72e0d9aAndrew Sapperstein } 11843b08c51ec46794b3c22c8649eb86bf77c72e0d9aAndrew Sapperstein 11853b08c51ec46794b3c22c8649eb86bf77c72e0d9aAndrew Sapperstein mSpamWarningView.showSpamWarning(mMessage, mSender); 11863b08c51ec46794b3c22c8649eb86bf77c72e0d9aAndrew Sapperstein } 11873b08c51ec46794b3c22c8649eb86bf77c72e0d9aAndrew Sapperstein 1188326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira private void handleShowImagePromptClick(View v) { 1189326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira Integer state = (Integer) v.getTag(); 1190326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira if (state == null) { 1191326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira return; 1192326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } 1193326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira switch (state) { 1194326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira case SHOW_IMAGE_PROMPT_ONCE: 1195326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira if (mCallbacks != null) { 11963233bff8ae08a56543c9f5abf1bc6ab38f0574ceAndy Huang mCallbacks.showExternalResources(mMessage); 1197326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } 1198470aa42b2b33d3ec5cdffa967d47e7a7b4b7209aAndy Huang if (mMessageHeaderItem != null) { 1199470aa42b2b33d3ec5cdffa967d47e7a7b4b7209aAndy Huang mMessageHeaderItem.setShowImages(true); 1200470aa42b2b33d3ec5cdffa967d47e7a7b4b7209aAndy Huang } 12014ddda2f0a4ee5381a90779a6939b05b064ce5d11Andrew Sapperstein if (mIsViewOnlyMode) { 12024ddda2f0a4ee5381a90779a6939b05b064ce5d11Andrew Sapperstein hideShowImagePrompt(); 12034ddda2f0a4ee5381a90779a6939b05b064ce5d11Andrew Sapperstein } else { 12044ddda2f0a4ee5381a90779a6939b05b064ce5d11Andrew Sapperstein showImagePromptAlways(false); 12054ddda2f0a4ee5381a90779a6939b05b064ce5d11Andrew Sapperstein } 1206326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira break; 1207326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira case SHOW_IMAGE_PROMPT_ALWAYS: 12083233bff8ae08a56543c9f5abf1bc6ab38f0574ceAndy Huang mMessage.markAlwaysShowImages(getQueryHandler(), 0 /* token */, null /* cookie */); 12093233bff8ae08a56543c9f5abf1bc6ab38f0574ceAndy Huang 1210eb9a4bdc53269ee05fe11870b9ebf03f18196585Scott Kennedy if (mCallbacks != null) { 1211eb9a4bdc53269ee05fe11870b9ebf03f18196585Scott Kennedy mCallbacks.showExternalResources(mMessage.getFrom()); 1212eb9a4bdc53269ee05fe11870b9ebf03f18196585Scott Kennedy } 1213eb9a4bdc53269ee05fe11870b9ebf03f18196585Scott Kennedy 1214326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira mShowImagePrompt = false; 1215326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira v.setTag(null); 1216326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira v.setVisibility(GONE); 1217c7543579c6a97c0ae3341578332f56d4d226f34cAndy Huang updateSpacerHeight(); 1218326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira Toast.makeText(getContext(), R.string.always_show_images_toast, Toast.LENGTH_SHORT) 1219326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira .show(); 1220326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira break; 1221326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } 1222326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } 1223326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira 12243233bff8ae08a56543c9f5abf1bc6ab38f0574ceAndy Huang private AsyncQueryHandler getQueryHandler() { 12253233bff8ae08a56543c9f5abf1bc6ab38f0574ceAndy Huang if (mQueryHandler == null) { 12263233bff8ae08a56543c9f5abf1bc6ab38f0574ceAndy Huang mQueryHandler = new AsyncQueryHandler(getContext().getContentResolver()) {}; 12273233bff8ae08a56543c9f5abf1bc6ab38f0574ceAndy Huang } 12283233bff8ae08a56543c9f5abf1bc6ab38f0574ceAndy Huang return mQueryHandler; 12293233bff8ae08a56543c9f5abf1bc6ab38f0574ceAndy Huang } 12303233bff8ae08a56543c9f5abf1bc6ab38f0574ceAndy Huang 1231326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira /** 1232326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira * Makes collapsed details visible. If necessary, will inflate details 1233326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira * layout and render using saved-off state (senders, timestamp, etc). 1234326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira */ 1235326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira private void showCollapsedDetails() { 1236326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira if (mCollapsedDetailsView == null) { 12379f369596f1dc59184cdabe683c2ebfc19ead4f83Andy Huang mCollapsedDetailsView = (ViewGroup) mInflater.inflate( 12389f369596f1dc59184cdabe683c2ebfc19ead4f83Andy Huang R.layout.conversation_message_details_header, this, false); 12392862cba002c7805a8f8e28146c6d5504831dcec7Andrew Sapperstein mExtraContentView.addView(mCollapsedDetailsView, 0); 1240326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira mCollapsedDetailsView.setOnClickListener(this); 1241f70fc4052b72a850bbb9be585d0f5a4877ee9448Andy Huang } 1242f70fc4052b72a850bbb9be585d0f5a4877ee9448Andy Huang if (!mCollapsedDetailsValid) { 124365fe28fa88daad08f3be4c084ca5b4eaa366d1a7Andy Huang if (mMessageHeaderItem.recipientSummaryText == null) { 12444ddda2f0a4ee5381a90779a6939b05b064ce5d11Andrew Sapperstein final Account account = getAccount(); 12454ddda2f0a4ee5381a90779a6939b05b064ce5d11Andrew Sapperstein final String name = (account != null) ? account.name : ""; 124665fe28fa88daad08f3be4c084ca5b4eaa366d1a7Andy Huang mMessageHeaderItem.recipientSummaryText = getRecipientSummaryText(getContext(), 12474ddda2f0a4ee5381a90779a6939b05b064ce5d11Andrew Sapperstein name, mMyName, mTo, mCc, mBcc, mAddressCache, mVeiledMatcher); 124865fe28fa88daad08f3be4c084ca5b4eaa366d1a7Andy Huang } 124965fe28fa88daad08f3be4c084ca5b4eaa366d1a7Andy Huang ((TextView) findViewById(R.id.recipients_summary)) 125065fe28fa88daad08f3be4c084ca5b4eaa366d1a7Andy Huang .setText(mMessageHeaderItem.recipientSummaryText); 1251326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira 1252f70fc4052b72a850bbb9be585d0f5a4877ee9448Andy Huang mCollapsedDetailsValid = true; 1253326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } 1254326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira mCollapsedDetailsView.setVisibility(VISIBLE); 1255326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } 1256326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira 1257326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira /** 1258326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira * Makes expanded details visible. If necessary, will inflate expanded 1259326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira * details layout and render using saved-off state (senders, timestamp, 1260326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira * etc). 1261326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira */ 1262326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira private void showExpandedDetails() { 1263326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira // lazily create expanded details view 126463f9b48ee0d54faf9ddc802e4582b7e499d87e04Paul Westbrook final boolean expandedViewCreated = ensureExpandedDetailsView(); 126563f9b48ee0d54faf9ddc802e4582b7e499d87e04Paul Westbrook if (expandedViewCreated) { 12662862cba002c7805a8f8e28146c6d5504831dcec7Andrew Sapperstein mExtraContentView.addView(mExpandedDetailsView, 0); 126763f9b48ee0d54faf9ddc802e4582b7e499d87e04Paul Westbrook } 126877a4605e6fbc368b2b87b4888f2ffd6329620807mindyp mExpandedDetailsView.setVisibility(VISIBLE); 126977a4605e6fbc368b2b87b4888f2ffd6329620807mindyp } 127077a4605e6fbc368b2b87b4888f2ffd6329620807mindyp 127163f9b48ee0d54faf9ddc802e4582b7e499d87e04Paul Westbrook private boolean ensureExpandedDetailsView() { 127263f9b48ee0d54faf9ddc802e4582b7e499d87e04Paul Westbrook boolean viewCreated = false; 1273326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira if (mExpandedDetailsView == null) { 127421a6ed2bdd46ccfdf9aa3e8aecd4cb1af6c2539fAndrew Sapperstein View v = inflateExpandedDetails(mInflater); 1275326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira v.setOnClickListener(this); 1276326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira 1277f70fc4052b72a850bbb9be585d0f5a4877ee9448Andy Huang mExpandedDetailsView = (ViewGroup) v; 127863f9b48ee0d54faf9ddc802e4582b7e499d87e04Paul Westbrook viewCreated = true; 1279f70fc4052b72a850bbb9be585d0f5a4877ee9448Andy Huang } 1280f70fc4052b72a850bbb9be585d0f5a4877ee9448Andy Huang if (!mExpandedDetailsValid) { 128121a6ed2bdd46ccfdf9aa3e8aecd4cb1af6c2539fAndrew Sapperstein renderExpandedDetails(getResources(), mExpandedDetailsView, mMessage.viaDomain, 128231b828da09beb6ef3d8ffaf4a72bf80dc4030b62Andrew Sapperstein mAddressCache, getAccount(), mVeiledMatcher, mFrom, mReplyTo, mTo, mCc, mBcc, 128331b828da09beb6ef3d8ffaf4a72bf80dc4030b62Andrew Sapperstein mMessageHeaderItem.getTimestampLong()); 1284326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira 1285f70fc4052b72a850bbb9be585d0f5a4877ee9448Andy Huang mExpandedDetailsValid = true; 1286326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } 128763f9b48ee0d54faf9ddc802e4582b7e499d87e04Paul Westbrook return viewCreated; 128877a4605e6fbc368b2b87b4888f2ffd6329620807mindyp } 128977a4605e6fbc368b2b87b4888f2ffd6329620807mindyp 129021a6ed2bdd46ccfdf9aa3e8aecd4cb1af6c2539fAndrew Sapperstein public static View inflateExpandedDetails(LayoutInflater inflater) { 129121a6ed2bdd46ccfdf9aa3e8aecd4cb1af6c2539fAndrew Sapperstein return inflater.inflate(R.layout.conversation_message_details_header_expanded, null, 129221a6ed2bdd46ccfdf9aa3e8aecd4cb1af6c2539fAndrew Sapperstein false); 129321a6ed2bdd46ccfdf9aa3e8aecd4cb1af6c2539fAndrew Sapperstein } 129421a6ed2bdd46ccfdf9aa3e8aecd4cb1af6c2539fAndrew Sapperstein 129521a6ed2bdd46ccfdf9aa3e8aecd4cb1af6c2539fAndrew Sapperstein public static void renderExpandedDetails(Resources res, View detailsView, 129621a6ed2bdd46ccfdf9aa3e8aecd4cb1af6c2539fAndrew Sapperstein String viaDomain, Map<String, Address> addressCache, Account account, 129721a6ed2bdd46ccfdf9aa3e8aecd4cb1af6c2539fAndrew Sapperstein VeiledAddressMatcher veiledMatcher, String[] from, String[] replyTo, 129831b828da09beb6ef3d8ffaf4a72bf80dc4030b62Andrew Sapperstein String[] to, String[] cc, String[] bcc, CharSequence receivedTimestamp) { 1299ef8d379fa5a6dadf0602159d3aa3f498327adde7Andrew Sapperstein renderEmailList(res, R.id.from_heading, R.id.from_details, from, viaDomain, 130021a6ed2bdd46ccfdf9aa3e8aecd4cb1af6c2539fAndrew Sapperstein detailsView, addressCache, account, veiledMatcher); 1301ef8d379fa5a6dadf0602159d3aa3f498327adde7Andrew Sapperstein renderEmailList(res, R.id.replyto_heading, R.id.replyto_details, replyTo, viaDomain, 130221a6ed2bdd46ccfdf9aa3e8aecd4cb1af6c2539fAndrew Sapperstein detailsView, addressCache, account, veiledMatcher); 1303ef8d379fa5a6dadf0602159d3aa3f498327adde7Andrew Sapperstein renderEmailList(res, R.id.to_heading, R.id.to_details, to, viaDomain, 130421a6ed2bdd46ccfdf9aa3e8aecd4cb1af6c2539fAndrew Sapperstein detailsView, addressCache, account, veiledMatcher); 1305ef8d379fa5a6dadf0602159d3aa3f498327adde7Andrew Sapperstein renderEmailList(res, R.id.cc_heading, R.id.cc_details, cc, viaDomain, 130621a6ed2bdd46ccfdf9aa3e8aecd4cb1af6c2539fAndrew Sapperstein detailsView, addressCache, account, veiledMatcher); 1307ef8d379fa5a6dadf0602159d3aa3f498327adde7Andrew Sapperstein renderEmailList(res, R.id.bcc_heading, R.id.bcc_details, bcc, viaDomain, 130821a6ed2bdd46ccfdf9aa3e8aecd4cb1af6c2539fAndrew Sapperstein detailsView, addressCache, account, veiledMatcher); 130931b828da09beb6ef3d8ffaf4a72bf80dc4030b62Andrew Sapperstein 131031b828da09beb6ef3d8ffaf4a72bf80dc4030b62Andrew Sapperstein // Render date 131131b828da09beb6ef3d8ffaf4a72bf80dc4030b62Andrew Sapperstein detailsView.findViewById(R.id.date_heading).setVisibility(VISIBLE); 131231b828da09beb6ef3d8ffaf4a72bf80dc4030b62Andrew Sapperstein final TextView date = (TextView) detailsView.findViewById(R.id.date_details); 131331b828da09beb6ef3d8ffaf4a72bf80dc4030b62Andrew Sapperstein date.setText(receivedTimestamp); 131431b828da09beb6ef3d8ffaf4a72bf80dc4030b62Andrew Sapperstein date.setVisibility(VISIBLE); 131521a6ed2bdd46ccfdf9aa3e8aecd4cb1af6c2539fAndrew Sapperstein } 131621a6ed2bdd46ccfdf9aa3e8aecd4cb1af6c2539fAndrew Sapperstein 131721a6ed2bdd46ccfdf9aa3e8aecd4cb1af6c2539fAndrew Sapperstein /** 131821a6ed2bdd46ccfdf9aa3e8aecd4cb1af6c2539fAndrew Sapperstein * Render an email list for the expanded message details view. 131921a6ed2bdd46ccfdf9aa3e8aecd4cb1af6c2539fAndrew Sapperstein */ 1320ef8d379fa5a6dadf0602159d3aa3f498327adde7Andrew Sapperstein private static void renderEmailList(Resources res, int headerId, int detailsId, 132121a6ed2bdd46ccfdf9aa3e8aecd4cb1af6c2539fAndrew Sapperstein String[] emails, String viaDomain, View rootView, 132221a6ed2bdd46ccfdf9aa3e8aecd4cb1af6c2539fAndrew Sapperstein Map<String, Address> addressCache, Account account, 132321a6ed2bdd46ccfdf9aa3e8aecd4cb1af6c2539fAndrew Sapperstein VeiledAddressMatcher veiledMatcher) { 132421a6ed2bdd46ccfdf9aa3e8aecd4cb1af6c2539fAndrew Sapperstein if (emails == null || emails.length == 0) { 132521a6ed2bdd46ccfdf9aa3e8aecd4cb1af6c2539fAndrew Sapperstein return; 132621a6ed2bdd46ccfdf9aa3e8aecd4cb1af6c2539fAndrew Sapperstein } 132721a6ed2bdd46ccfdf9aa3e8aecd4cb1af6c2539fAndrew Sapperstein final String[] formattedEmails = new String[emails.length]; 132821a6ed2bdd46ccfdf9aa3e8aecd4cb1af6c2539fAndrew Sapperstein for (int i = 0; i < emails.length; i++) { 132921a6ed2bdd46ccfdf9aa3e8aecd4cb1af6c2539fAndrew Sapperstein final Address email = getAddress(addressCache, emails[i]); 133021a6ed2bdd46ccfdf9aa3e8aecd4cb1af6c2539fAndrew Sapperstein String name = email.getName(); 133121a6ed2bdd46ccfdf9aa3e8aecd4cb1af6c2539fAndrew Sapperstein final String address = email.getAddress(); 133221a6ed2bdd46ccfdf9aa3e8aecd4cb1af6c2539fAndrew Sapperstein // Check if the address here is a veiled address. If it is, we need to display an 133321a6ed2bdd46ccfdf9aa3e8aecd4cb1af6c2539fAndrew Sapperstein // alternate layout 133421a6ed2bdd46ccfdf9aa3e8aecd4cb1af6c2539fAndrew Sapperstein final boolean isVeiledAddress = veiledMatcher != null && 133521a6ed2bdd46ccfdf9aa3e8aecd4cb1af6c2539fAndrew Sapperstein veiledMatcher.isVeiledAddress(address); 133621a6ed2bdd46ccfdf9aa3e8aecd4cb1af6c2539fAndrew Sapperstein final String addressShown; 133721a6ed2bdd46ccfdf9aa3e8aecd4cb1af6c2539fAndrew Sapperstein if (isVeiledAddress) { 133821a6ed2bdd46ccfdf9aa3e8aecd4cb1af6c2539fAndrew Sapperstein // Add the warning at the end of the name, and remove the address. The alternate 133921a6ed2bdd46ccfdf9aa3e8aecd4cb1af6c2539fAndrew Sapperstein // text cannot be put in the address part, because the address is made into a link, 134021a6ed2bdd46ccfdf9aa3e8aecd4cb1af6c2539fAndrew Sapperstein // and the alternate human-readable text is not a link. 134121a6ed2bdd46ccfdf9aa3e8aecd4cb1af6c2539fAndrew Sapperstein addressShown = ""; 134221a6ed2bdd46ccfdf9aa3e8aecd4cb1af6c2539fAndrew Sapperstein if (TextUtils.isEmpty(name)) { 134321a6ed2bdd46ccfdf9aa3e8aecd4cb1af6c2539fAndrew Sapperstein // Empty name and we will block out the address. Let's write something more 134421a6ed2bdd46ccfdf9aa3e8aecd4cb1af6c2539fAndrew Sapperstein // readable. 134521a6ed2bdd46ccfdf9aa3e8aecd4cb1af6c2539fAndrew Sapperstein name = res.getString(VeiledAddressMatcher.VEILED_ALTERNATE_TEXT_UNKNOWN_PERSON); 134621a6ed2bdd46ccfdf9aa3e8aecd4cb1af6c2539fAndrew Sapperstein } else { 134721a6ed2bdd46ccfdf9aa3e8aecd4cb1af6c2539fAndrew Sapperstein name = name + res.getString(VeiledAddressMatcher.VEILED_ALTERNATE_TEXT); 134821a6ed2bdd46ccfdf9aa3e8aecd4cb1af6c2539fAndrew Sapperstein } 134921a6ed2bdd46ccfdf9aa3e8aecd4cb1af6c2539fAndrew Sapperstein } else { 135021a6ed2bdd46ccfdf9aa3e8aecd4cb1af6c2539fAndrew Sapperstein addressShown = address; 135121a6ed2bdd46ccfdf9aa3e8aecd4cb1af6c2539fAndrew Sapperstein } 135221a6ed2bdd46ccfdf9aa3e8aecd4cb1af6c2539fAndrew Sapperstein if (name == null || name.length() == 0) { 135321a6ed2bdd46ccfdf9aa3e8aecd4cb1af6c2539fAndrew Sapperstein formattedEmails[i] = addressShown; 135421a6ed2bdd46ccfdf9aa3e8aecd4cb1af6c2539fAndrew Sapperstein } else { 135521a6ed2bdd46ccfdf9aa3e8aecd4cb1af6c2539fAndrew Sapperstein // The one downside to having the showViaDomain here is that 135621a6ed2bdd46ccfdf9aa3e8aecd4cb1af6c2539fAndrew Sapperstein // if the sender does not have a name, it will not show the via info 135721a6ed2bdd46ccfdf9aa3e8aecd4cb1af6c2539fAndrew Sapperstein if (viaDomain != null) { 135821a6ed2bdd46ccfdf9aa3e8aecd4cb1af6c2539fAndrew Sapperstein formattedEmails[i] = res.getString( 135921a6ed2bdd46ccfdf9aa3e8aecd4cb1af6c2539fAndrew Sapperstein R.string.address_display_format_with_via_domain, 136021a6ed2bdd46ccfdf9aa3e8aecd4cb1af6c2539fAndrew Sapperstein name, addressShown, viaDomain); 136121a6ed2bdd46ccfdf9aa3e8aecd4cb1af6c2539fAndrew Sapperstein } else { 136221a6ed2bdd46ccfdf9aa3e8aecd4cb1af6c2539fAndrew Sapperstein formattedEmails[i] = res.getString(R.string.address_display_format, 136321a6ed2bdd46ccfdf9aa3e8aecd4cb1af6c2539fAndrew Sapperstein name, addressShown); 136421a6ed2bdd46ccfdf9aa3e8aecd4cb1af6c2539fAndrew Sapperstein } 136521a6ed2bdd46ccfdf9aa3e8aecd4cb1af6c2539fAndrew Sapperstein } 136621a6ed2bdd46ccfdf9aa3e8aecd4cb1af6c2539fAndrew Sapperstein } 136721a6ed2bdd46ccfdf9aa3e8aecd4cb1af6c2539fAndrew Sapperstein 1368ef8d379fa5a6dadf0602159d3aa3f498327adde7Andrew Sapperstein rootView.findViewById(headerId).setVisibility(VISIBLE); 136921a6ed2bdd46ccfdf9aa3e8aecd4cb1af6c2539fAndrew Sapperstein final TextView detailsText = (TextView) rootView.findViewById(detailsId); 1370ef8d379fa5a6dadf0602159d3aa3f498327adde7Andrew Sapperstein detailsText.setText(TextUtils.join("\n", formattedEmails)); 137121a6ed2bdd46ccfdf9aa3e8aecd4cb1af6c2539fAndrew Sapperstein stripUnderlines(detailsText, account); 137221a6ed2bdd46ccfdf9aa3e8aecd4cb1af6c2539fAndrew Sapperstein detailsText.setVisibility(VISIBLE); 137321a6ed2bdd46ccfdf9aa3e8aecd4cb1af6c2539fAndrew Sapperstein } 137421a6ed2bdd46ccfdf9aa3e8aecd4cb1af6c2539fAndrew Sapperstein 137521a6ed2bdd46ccfdf9aa3e8aecd4cb1af6c2539fAndrew Sapperstein private static void stripUnderlines(TextView textView, Account account) { 137621a6ed2bdd46ccfdf9aa3e8aecd4cb1af6c2539fAndrew Sapperstein final Spannable spannable = (Spannable) textView.getText(); 137721a6ed2bdd46ccfdf9aa3e8aecd4cb1af6c2539fAndrew Sapperstein final URLSpan[] urls = textView.getUrls(); 137821a6ed2bdd46ccfdf9aa3e8aecd4cb1af6c2539fAndrew Sapperstein 137921a6ed2bdd46ccfdf9aa3e8aecd4cb1af6c2539fAndrew Sapperstein for (URLSpan span : urls) { 138021a6ed2bdd46ccfdf9aa3e8aecd4cb1af6c2539fAndrew Sapperstein final int start = spannable.getSpanStart(span); 138121a6ed2bdd46ccfdf9aa3e8aecd4cb1af6c2539fAndrew Sapperstein final int end = spannable.getSpanEnd(span); 138221a6ed2bdd46ccfdf9aa3e8aecd4cb1af6c2539fAndrew Sapperstein spannable.removeSpan(span); 138321a6ed2bdd46ccfdf9aa3e8aecd4cb1af6c2539fAndrew Sapperstein span = new EmailAddressSpan(account, span.getURL().substring(7)); 138421a6ed2bdd46ccfdf9aa3e8aecd4cb1af6c2539fAndrew Sapperstein spannable.setSpan(span, start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); 138521a6ed2bdd46ccfdf9aa3e8aecd4cb1af6c2539fAndrew Sapperstein } 138621a6ed2bdd46ccfdf9aa3e8aecd4cb1af6c2539fAndrew Sapperstein } 138721a6ed2bdd46ccfdf9aa3e8aecd4cb1af6c2539fAndrew Sapperstein 138877a4605e6fbc368b2b87b4888f2ffd6329620807mindyp private void showDetailsPopup() { 138921a6ed2bdd46ccfdf9aa3e8aecd4cb1af6c2539fAndrew Sapperstein final FragmentManager manager = mCallbacks.getFragmentManager(); 139021a6ed2bdd46ccfdf9aa3e8aecd4cb1af6c2539fAndrew Sapperstein mDetailsPopup = (DialogFragment) manager.findFragmentByTag(DETAILS_DIALOG_TAG); 139177a4605e6fbc368b2b87b4888f2ffd6329620807mindyp if (mDetailsPopup == null) { 139221a6ed2bdd46ccfdf9aa3e8aecd4cb1af6c2539fAndrew Sapperstein mDetailsPopup = MessageHeaderDetailsDialogFragment.newInstance( 139331b828da09beb6ef3d8ffaf4a72bf80dc4030b62Andrew Sapperstein mAddressCache, getAccount(), mFrom, mReplyTo, mTo, mCc, mBcc, 139431b828da09beb6ef3d8ffaf4a72bf80dc4030b62Andrew Sapperstein mMessageHeaderItem.getTimestampLong()); 139521a6ed2bdd46ccfdf9aa3e8aecd4cb1af6c2539fAndrew Sapperstein mDetailsPopup.show(manager, DETAILS_DIALOG_TAG); 139677a4605e6fbc368b2b87b4888f2ffd6329620807mindyp } 139777a4605e6fbc368b2b87b4888f2ffd6329620807mindyp } 139877a4605e6fbc368b2b87b4888f2ffd6329620807mindyp 139977a4605e6fbc368b2b87b4888f2ffd6329620807mindyp private void hideDetailsPopup() { 140077a4605e6fbc368b2b87b4888f2ffd6329620807mindyp if (mDetailsPopup != null) { 140121a6ed2bdd46ccfdf9aa3e8aecd4cb1af6c2539fAndrew Sapperstein mDetailsPopup.dismiss(); 140221a6ed2bdd46ccfdf9aa3e8aecd4cb1af6c2539fAndrew Sapperstein mDetailsPopup = null; 140377a4605e6fbc368b2b87b4888f2ffd6329620807mindyp } 1404326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } 1405326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira 1406326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira /** 1407326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira * Returns a short plaintext snippet generated from the given HTML message 1408326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira * body. Collapses whitespace, ignores '<' and '>' characters and 1409326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira * everything in between, and truncates the snippet to no more than 100 1410326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira * characters. 1411326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira * 1412326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira * @return Short plaintext snippet 1413326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira */ 1414326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira @VisibleForTesting 1415326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira static String makeSnippet(final String messageBody) { 1416e805ab4b4e4dcdfc21dd58d4341ec226bf70b65dAndy Huang if (TextUtils.isEmpty(messageBody)) { 1417e805ab4b4e4dcdfc21dd58d4341ec226bf70b65dAndy Huang return null; 1418e805ab4b4e4dcdfc21dd58d4341ec226bf70b65dAndy Huang } 1419e805ab4b4e4dcdfc21dd58d4341ec226bf70b65dAndy Huang 1420e805ab4b4e4dcdfc21dd58d4341ec226bf70b65dAndy Huang final StringBuilder snippet = new StringBuilder(MAX_SNIPPET_LENGTH); 1421326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira 1422e805ab4b4e4dcdfc21dd58d4341ec226bf70b65dAndy Huang final StringReader reader = new StringReader(messageBody); 1423326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira try { 1424326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira int c; 1425326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira while ((c = reader.read()) != -1 && snippet.length() < MAX_SNIPPET_LENGTH) { 1426326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira // Collapse whitespace. 1427326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira if (Character.isWhitespace(c)) { 1428326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira snippet.append(' '); 1429326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira do { 1430326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira c = reader.read(); 1431326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } while (Character.isWhitespace(c)); 1432326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira if (c == -1) { 1433326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira break; 1434326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } 1435326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } 1436326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira 1437326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira if (c == '<') { 1438326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira // Ignore everything up to and including the next '>' 1439326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira // character. 1440326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira while ((c = reader.read()) != -1) { 1441326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira if (c == '>') { 1442326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira break; 1443326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } 1444326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } 1445326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira 1446326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira // If we reached the end of the message body, exit. 1447326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira if (c == -1) { 1448326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira break; 1449326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } 1450326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } else if (c == '&') { 1451326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira // Read HTML entity. 1452326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira StringBuilder sb = new StringBuilder(); 1453326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira 1454326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira while ((c = reader.read()) != -1) { 1455326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira if (c == ';') { 1456326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira break; 1457326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } 1458326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira sb.append((char) c); 1459326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } 1460326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira 1461326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira String entity = sb.toString(); 1462326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira if ("nbsp".equals(entity)) { 1463326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira snippet.append(' '); 1464326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } else if ("lt".equals(entity)) { 1465326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira snippet.append('<'); 1466326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } else if ("gt".equals(entity)) { 1467326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira snippet.append('>'); 1468326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } else if ("amp".equals(entity)) { 1469326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira snippet.append('&'); 1470326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } else if ("quot".equals(entity)) { 1471326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira snippet.append('"'); 1472326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } else if ("apos".equals(entity) || "#39".equals(entity)) { 1473326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira snippet.append('\''); 1474326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } else { 1475326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira // Unknown entity; just append the literal string. 1476326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira snippet.append('&').append(entity); 1477326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira if (c == ';') { 1478326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira snippet.append(';'); 1479326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } 1480326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } 1481326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira 1482326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira // If we reached the end of the message body, exit. 1483326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira if (c == -1) { 1484326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira break; 1485326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } 1486326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } else { 1487326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira // The current character is a non-whitespace character that 1488326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira // isn't inside some 1489326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira // HTML tag and is not part of an HTML entity. 1490326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira snippet.append((char) c); 1491326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } 1492326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } 1493326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } catch (IOException e) { 1494326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira LogUtils.wtf(LOG_TAG, e, "Really? IOException while reading a freaking string?!? "); 1495326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } 1496326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira 1497326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira return snippet.toString(); 1498326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } 1499326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira 1500326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira @Override 1501326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira protected void onLayout(boolean changed, int l, int t, int r, int b) { 1502326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira Timer perf = new Timer(); 1503326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira perf.start(LAYOUT_TAG); 1504326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira super.onLayout(changed, l, t, r, b); 1505326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira perf.pause(LAYOUT_TAG); 1506326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } 1507326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira 1508326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira @Override 1509326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 1510326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira Timer t = new Timer(); 1511326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira if (Timer.ENABLE_TIMER && !mPreMeasuring) { 15123233bff8ae08a56543c9f5abf1bc6ab38f0574ceAndy Huang t.count("header measure id=" + mMessage.id); 1513326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira t.start(MEASURE_TAG); 1514326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } 1515326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira super.onMeasure(widthMeasureSpec, heightMeasureSpec); 1516326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira if (!mPreMeasuring) { 1517326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira t.pause(MEASURE_TAG); 1518326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } 1519326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } 1520326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira} 1521