ComposeActivity.java revision 30e2c24b056542f3b1b438aeb798305d1226d0c8
18e9305ec0bbe23cec01eb34a2aee76c55199a10aMindy Pereira/** 28e9305ec0bbe23cec01eb34a2aee76c55199a10aMindy Pereira * Copyright (c) 2011, Google Inc. 38e9305ec0bbe23cec01eb34a2aee76c55199a10aMindy Pereira * 48e9305ec0bbe23cec01eb34a2aee76c55199a10aMindy Pereira * Licensed under the Apache License, Version 2.0 (the "License"); 58e9305ec0bbe23cec01eb34a2aee76c55199a10aMindy Pereira * you may not use this file except in compliance with the License. 68e9305ec0bbe23cec01eb34a2aee76c55199a10aMindy Pereira * You may obtain a copy of the License at 78e9305ec0bbe23cec01eb34a2aee76c55199a10aMindy Pereira * 88e9305ec0bbe23cec01eb34a2aee76c55199a10aMindy Pereira * http://www.apache.org/licenses/LICENSE-2.0 98e9305ec0bbe23cec01eb34a2aee76c55199a10aMindy Pereira * 108e9305ec0bbe23cec01eb34a2aee76c55199a10aMindy Pereira * Unless required by applicable law or agreed to in writing, software 118e9305ec0bbe23cec01eb34a2aee76c55199a10aMindy Pereira * distributed under the License is distributed on an "AS IS" BASIS, 128e9305ec0bbe23cec01eb34a2aee76c55199a10aMindy Pereira * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 138e9305ec0bbe23cec01eb34a2aee76c55199a10aMindy Pereira * See the License for the specific language governing permissions and 148e9305ec0bbe23cec01eb34a2aee76c55199a10aMindy Pereira * limitations under the License. 158e9305ec0bbe23cec01eb34a2aee76c55199a10aMindy Pereira */ 168e9305ec0bbe23cec01eb34a2aee76c55199a10aMindy Pereira 1730e2c24b056542f3b1b438aeb798305d1226d0c8Andy Huangpackage com.android.mail.compose; 188e9305ec0bbe23cec01eb34a2aee76c55199a10aMindy Pereira 19c17d073dd43871df36ea70b3dea55963bdb98384Mindy Pereiraimport android.accounts.Account; 20326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereiraimport android.app.ActionBar; 21326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereiraimport android.app.ActionBar.OnNavigationListener; 228e9305ec0bbe23cec01eb34a2aee76c55199a10aMindy Pereiraimport android.app.Activity; 236349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereiraimport android.content.ContentResolver; 246349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereiraimport android.content.Context; 256349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereiraimport android.content.Intent; 266349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereiraimport android.database.Cursor; 27013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereiraimport android.database.sqlite.SQLiteException; 286349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereiraimport android.net.Uri; 298e9305ec0bbe23cec01eb34a2aee76c55199a10aMindy Pereiraimport android.os.Bundle; 30013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereiraimport android.os.ParcelFileDescriptor; 31013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereiraimport android.provider.OpenableColumns; 32013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereiraimport android.provider.Settings; 3346ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereiraimport android.text.Editable; 34c182762df95fd382faf8e4a25e5cf7783ea10176Paul Westbrookimport android.text.TextUtils; 3546ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereiraimport android.text.util.Rfc822Token; 36c17d073dd43871df36ea70b3dea55963bdb98384Mindy Pereiraimport android.text.util.Rfc822Tokenizer; 37013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereiraimport android.view.Gravity; 38326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereiraimport android.view.LayoutInflater; 39b47f3e286bcf78e85ab2d3389e38e99020d0634fMindy Pereiraimport android.view.Menu; 40b47f3e286bcf78e85ab2d3389e38e99020d0634fMindy Pereiraimport android.view.MenuInflater; 41b47f3e286bcf78e85ab2d3389e38e99020d0634fMindy Pereiraimport android.view.MenuItem; 428e9305ec0bbe23cec01eb34a2aee76c55199a10aMindy Pereiraimport android.view.View; 43326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereiraimport android.view.ViewGroup; 448e9305ec0bbe23cec01eb34a2aee76c55199a10aMindy Pereiraimport android.view.View.OnClickListener; 451a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereiraimport android.widget.AdapterView; 461a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereiraimport android.widget.AdapterView.OnItemSelectedListener; 47326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereiraimport android.widget.ArrayAdapter; 488e9305ec0bbe23cec01eb34a2aee76c55199a10aMindy Pereiraimport android.widget.Button; 491a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereiraimport android.widget.Spinner; 506349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereiraimport android.widget.TextView; 51013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereiraimport android.widget.Toast; 527b56a61174eeb202eea468b7f68b79729737ded2Mindy Pereira 53c17d073dd43871df36ea70b3dea55963bdb98384Mindy Pereiraimport com.android.common.Rfc822Validator; 5430e2c24b056542f3b1b438aeb798305d1226d0c8Andy Huangimport com.android.mail.compose.QuotedTextView.RespondInlineListener; 5530e2c24b056542f3b1b438aeb798305d1226d0c8Andy Huangimport com.android.mail.providers.Address; 5630e2c24b056542f3b1b438aeb798305d1226d0c8Andy Huangimport com.android.mail.providers.Attachment; 5730e2c24b056542f3b1b438aeb798305d1226d0c8Andy Huangimport com.android.mail.providers.UIProvider; 5830e2c24b056542f3b1b438aeb798305d1226d0c8Andy Huangimport com.android.mail.providers.protos.mock.MockAttachment; 5930e2c24b056542f3b1b438aeb798305d1226d0c8Andy Huangimport com.android.mail.R; 6030e2c24b056542f3b1b438aeb798305d1226d0c8Andy Huangimport com.android.mail.utils.AccountUtils; 6130e2c24b056542f3b1b438aeb798305d1226d0c8Andy Huangimport com.android.mail.utils.LogUtils; 6230e2c24b056542f3b1b438aeb798305d1226d0c8Andy Huangimport com.android.mail.utils.MimeType; 6330e2c24b056542f3b1b438aeb798305d1226d0c8Andy Huangimport com.android.mail.utils.Utils; 64c17d073dd43871df36ea70b3dea55963bdb98384Mindy Pereiraimport com.android.ex.chips.RecipientEditTextView; 6546ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereiraimport com.google.common.annotations.VisibleForTesting; 664a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereiraimport com.google.common.collect.Sets; 678e9305ec0bbe23cec01eb34a2aee76c55199a10aMindy Pereira 68013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereiraimport java.io.FileNotFoundException; 69013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereiraimport java.io.IOException; 7046ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereiraimport java.text.DateFormat; 7146ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereiraimport java.util.ArrayList; 7246ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereiraimport java.util.Arrays; 7346ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereiraimport java.util.Collection; 741a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereiraimport java.util.Collections; 7546ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereiraimport java.util.Date; 7646ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereiraimport java.util.HashSet; 7746ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereiraimport java.util.List; 784a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereiraimport java.util.Set; 7946ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira 8046ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereirapublic class ComposeActivity extends Activity implements OnClickListener, OnNavigationListener, 811a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira RespondInlineListener, OnItemSelectedListener { 826349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira // Identifiers for which type of composition this is 836349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira static final int COMPOSE = -1; // also used for editing a draft 846349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira static final int REPLY = 0; 856349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira static final int REPLY_ALL = 1; 866349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira static final int FORWARD = 2; 876349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira 8846ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira // HTML tags used to quote reply content 8946ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira // The following style must be in-sync with 9046ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira // pinto.app.MessageUtil.QUOTE_STYLE and 9146ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira // java/com/google/caribou/ui/pinto/modules/app/messageutil.js 9246ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira // BEG_QUOTE_BIDI is also available there when we support BIDI 9346ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira private static final String BLOCKQUOTE_BEGIN = "<blockquote class=\"quote\" style=\"" 9446ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira + "margin:0 0 0 .8ex;" + "border-left:1px #ccc solid;" + "padding-left:1ex\">"; 9546ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira private static final String BLOCKQUOTE_END = "</blockquote>"; 9646ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira // HTML tags used to quote replies & forwards 9746ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira /* package for testing */static final String QUOTE_BEGIN = "<div class=\"quote\">"; 9846ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira private static final String QUOTE_END = "</div>"; 9946ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira // Separates the attribution headers (Subject, To, etc) from the body in 10046ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira // quoted text. 10146ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira /* package for testing */ static final String HEADER_SEPARATOR = "<br type='attribution'>"; 10246ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira private static final int HEADER_SEPARATOR_LENGTH = HEADER_SEPARATOR.length(); 10346ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira 1046349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira // Integer extra holding one of the above compose action 1056349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira private static final String EXTRA_ACTION = "action"; 1066349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira 1076349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira /** 1086349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira * Notifies the {@code Activity} that the caller is an Email 1096349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira * {@code Activity}, so that the back behavior may be modified accordingly. 1106349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira * 1116349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira * @see #onAppUpPressed 1126349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira */ 1136349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira private static final String EXTRA_FROM_EMAIL_TASK = "fromemail"; 1146349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira 1156349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira // If this is a reply/forward then this extra will hold the original message uri 1166349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira private static final String EXTRA_IN_REFERENCE_TO_MESSAGE_URI = "in-reference-to-uri"; 1174a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira private static final String END_TOKEN = ", "; 118013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira private static final String LOG_TAG = new LogUtils().getLogTag(); 119013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira // Request numbers for activities we start 120013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira private static final int RESULT_PICK_ATTACHMENT = 1; 121013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira private static final int RESULT_CREATE_ACCOUNT = 2; 1228e9305ec0bbe23cec01eb34a2aee76c55199a10aMindy Pereira 123c17d073dd43871df36ea70b3dea55963bdb98384Mindy Pereira private RecipientEditTextView mTo; 124c17d073dd43871df36ea70b3dea55963bdb98384Mindy Pereira private RecipientEditTextView mCc; 125c17d073dd43871df36ea70b3dea55963bdb98384Mindy Pereira private RecipientEditTextView mBcc; 1268e9305ec0bbe23cec01eb34a2aee76c55199a10aMindy Pereira private Button mCcBccButton; 1278e9305ec0bbe23cec01eb34a2aee76c55199a10aMindy Pereira private CcBccView mCcBccView; 1287b56a61174eeb202eea468b7f68b79729737ded2Mindy Pereira private AttachmentsView mAttachmentsView; 129c17d073dd43871df36ea70b3dea55963bdb98384Mindy Pereira private String mAccount; 130c17d073dd43871df36ea70b3dea55963bdb98384Mindy Pereira private Rfc822Validator mRecipientValidator; 1316349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira private Uri mRefMessageUri; 1326349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira private TextView mSubject; 1336349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira 134326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira private ActionBar mActionBar; 135326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira private ComposeModeAdapter mComposeModeAdapter; 136326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira private int mComposeMode = -1; 13746ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira private boolean mForward; 13846ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira private String mRecipient; 13946ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira private boolean mAttachmentsChanged; 14046ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira private QuotedTextView mQuotedTextView; 14146ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira private TextView mBodyText; 1421a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira private View mFromStatic; 1431a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira private View mFromSpinner; 1441a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira private Spinner mFrom; 1451a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira private List<String[]> mReplyFromAccounts; 1461a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira private boolean mAccountSpinnerReady; 1471a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira private String[] mCurrentReplyFromAccount; 1481a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira private boolean mMessageIsForwardOrReply; 1491a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira private List<String> mAccounts; 150013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira private boolean mAddingAttachment; 151013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira private boolean mAttachmentAddedOrRemoved; 152326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira 153326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira /** 154326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira * Can be called from a non-UI thread. 155326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira */ 156326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira public static void editDraft(Context context, String account, long mLocalMessageId) { 157326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } 158326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira 1596349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira /** 1606349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira * Can be called from a non-UI thread. 1616349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira */ 1626349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira public static void compose(Context launcher, String account) { 1636349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira launch(launcher, account, null, COMPOSE); 1646349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira } 1656349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira 1666349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira /** 1676349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira * Can be called from a non-UI thread. 1686349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira */ 1696349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira public static void reply(Context launcher, String account, String uri) { 1706349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira launch(launcher, account, uri, REPLY); 1716349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira } 1726349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira 1736349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira /** 1746349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira * Can be called from a non-UI thread. 1756349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira */ 1766349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira public static void replyAll(Context launcher, String account, String uri) { 1776349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira launch(launcher, account, uri, REPLY_ALL); 1786349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira } 1796349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira 1806349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira /** 1816349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira * Can be called from a non-UI thread. 1826349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira */ 1836349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira public static void forward(Context launcher, String account, String uri) { 1846349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira launch(launcher, account, uri, FORWARD); 1856349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira } 1866349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira 1876349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira private static void launch(Context launcher, String account, String uri, int action) { 1886349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira Intent intent = new Intent(launcher, ComposeActivity.class); 1896349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira intent.putExtra(EXTRA_FROM_EMAIL_TASK, true); 1906349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira intent.putExtra(EXTRA_ACTION, action); 1916349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira intent.putExtra(Utils.EXTRA_ACCOUNT, account); 1926349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira intent.putExtra(EXTRA_IN_REFERENCE_TO_MESSAGE_URI, uri); 1936349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira launcher.startActivity(intent); 1946349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira } 1958e9305ec0bbe23cec01eb34a2aee76c55199a10aMindy Pereira 1968e9305ec0bbe23cec01eb34a2aee76c55199a10aMindy Pereira @Override 1978e9305ec0bbe23cec01eb34a2aee76c55199a10aMindy Pereira public void onCreate(Bundle savedInstanceState) { 1988e9305ec0bbe23cec01eb34a2aee76c55199a10aMindy Pereira super.onCreate(savedInstanceState); 1993528d3657bd8f6f128e2b9b18acd018c4b3e5130Mindy Pereira Intent intent = getIntent(); 2003528d3657bd8f6f128e2b9b18acd018c4b3e5130Mindy Pereira mAccount = intent.getStringExtra(Utils.EXTRA_ACCOUNT); 2018e9305ec0bbe23cec01eb34a2aee76c55199a10aMindy Pereira setContentView(R.layout.compose); 20246ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira findViews(); 20346ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira int action = intent.getIntExtra(EXTRA_ACTION, COMPOSE); 20446ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira if (action == REPLY || action == REPLY_ALL || action == FORWARD) { 20546ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira mRefMessageUri = Uri.parse(intent.getStringExtra(EXTRA_IN_REFERENCE_TO_MESSAGE_URI)); 20646ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira initFromRefMessage(action, mAccount); 20746ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira } else { 20846ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira setQuotedTextVisibility(false); 20946ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira } 2101a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira initActionBar(action); 2111a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira asyncInitFromSpinner(); 2121a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira } 2131a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira 2141a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira @Override 2151a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira protected void onResume() { 2161a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira super.onResume(); 2171a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira // Update the from spinner as other accounts 2181a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira // may now be available. 2191a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira asyncInitFromSpinner(); 2201a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira } 2211a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira 2221a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira private void asyncInitFromSpinner() { 2231a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira Account[] result = AccountUtils.getSyncingAccounts(this, null, null, null); 2241a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira mAccounts = AccountUtils 2251a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira .mergeAccountLists(mAccounts, result, true /* prioritizeAccountList */); 2261a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira createReplyFromCache(); 2271a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira initFromSpinner(); 2281a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira } 2291a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira 2301a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira /** 2311a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira * Create a cache of all accounts a user could send mail from 2321a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira */ 2331a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira private void createReplyFromCache() { 2341a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira // Check for replyFroms. 2351a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira List<String> accounts = null; 2361a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira mReplyFromAccounts = new ArrayList<String[]>(); 2371a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira 2381a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira if (mMessageIsForwardOrReply) { 2391a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira accounts = Collections.singletonList(mAccount); 2401a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira } else { 2411a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira accounts = mAccounts; 2421a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira } 2431a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira for (String account : accounts) { 2441a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira // First add the account. First position is account, second 2451a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira // is display of account, 3rd position is the REAL account this 2461a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira // is being sent from / synced to. 2471a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira mReplyFromAccounts.add(new String[] { 2481a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira account, account, account, "false" 2491a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira }); 2501a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira } 2511a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira } 2521a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira 2531a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira private void initFromSpinner() { 2541a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira // If there are not yet any accounts in the cached synced accounts 2551a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira // because this is the first time Gmail was opened, and it was opened directly 2561a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira // to the compose activity,don't bother populating the reply from spinner yet. 2571a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira if (mReplyFromAccounts == null || mReplyFromAccounts.size() == 0) { 2581a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira mAccountSpinnerReady = false; 2591a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira return; 2601a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira } 2611a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira FromAddressSpinnerAdapter adapter = new FromAddressSpinnerAdapter(this); 2621a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira int currentAccountIndex = 0; 2631a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira String replyFromAccount = mAccount; 2641a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira 2651a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira boolean checkRealAccount = mRecipient == null || mAccount.equals(mRecipient); 2661a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira 2671a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira currentAccountIndex = addAccountsToAdapter(adapter, checkRealAccount, replyFromAccount); 2681a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira 2691a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira mFrom.setAdapter(adapter); 2701a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira mFrom.setSelection(currentAccountIndex, false); 2711a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira mFrom.setOnItemSelectedListener(this); 2721a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira mCurrentReplyFromAccount = mReplyFromAccounts.get(currentAccountIndex); 2731a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira 2741a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira hideOrShowFromSpinner(); 2751a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira mAccountSpinnerReady = true; 2761a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira adapter.setSpinner(mFrom); 2771a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira } 2781a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira 2791a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira private void hideOrShowFromSpinner() { 2801a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira // Determine whether the from account spinner or the static 2811a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira // from text should be show 2821a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira // When the spinner is shown, the static from text 2831a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira // is hidden 2841a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira showFromSpinner(mFrom.getCount() > 1); 2851a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira } 2861a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira 2871a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira private int addAccountsToAdapter(FromAddressSpinnerAdapter adapter, boolean checkRealAccount, 2881a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira String replyFromAccount) { 2891a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira int currentIndex = 0; 2901a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira int currentAccountIndex = 0; 2911a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira // Get the position of the current account 2921a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira for (String[] account : mReplyFromAccounts) { 2931a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira // Add the account to the Adapter 2941a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira // The reason that we are not adding the Account array, but adding 2951a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira // the names of each account, is because Account returns a string 2961a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira // that we don't want to display on toString() 2971a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira adapter.add(account); 2981a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira // Compare to the account address, not the real account being 2991a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira // sent from. 3001a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira if (checkRealAccount) { 3011a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira // Need to check the real account and the account address 3021a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira // so that we can send from the correct address on the 3031a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira // correct account when the same address may exist across 3041a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira // multiple accounts. 3051a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira if (account[FromAddressSpinnerAdapter.REAL_ACCOUNT].equals(mAccount) 3061a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira && account[FromAddressSpinnerAdapter.ACCOUNT_ADDRESS] 3071a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira .equals(replyFromAccount)) { 3081a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira currentAccountIndex = currentIndex; 3091a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira } 3101a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira } else { 3111a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira // Just need to check the account address. 3121a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira if (replyFromAccount.equals( 3131a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira account[FromAddressSpinnerAdapter.ACCOUNT_ADDRESS])) { 3141a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira currentAccountIndex = currentIndex; 3151a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira } 3161a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira } 3171a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira 3181a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira currentIndex++; 3191a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira } 3201a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira return currentAccountIndex; 32146ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira } 32246ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira 32346ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira private void findViews() { 324a26b54e3a858de409be3746e65591bb8a0d6ea9aMindy Pereira mCcBccButton = (Button) findViewById(R.id.add_cc_bcc); 3258e9305ec0bbe23cec01eb34a2aee76c55199a10aMindy Pereira if (mCcBccButton != null) { 3268e9305ec0bbe23cec01eb34a2aee76c55199a10aMindy Pereira mCcBccButton.setOnClickListener(this); 3278e9305ec0bbe23cec01eb34a2aee76c55199a10aMindy Pereira } 3288e9305ec0bbe23cec01eb34a2aee76c55199a10aMindy Pereira mCcBccView = (CcBccView) findViewById(R.id.cc_bcc_wrapper); 3297b56a61174eeb202eea468b7f68b79729737ded2Mindy Pereira mAttachmentsView = (AttachmentsView)findViewById(R.id.attachments); 330c17d073dd43871df36ea70b3dea55963bdb98384Mindy Pereira mTo = setupRecipients(R.id.to); 331c17d073dd43871df36ea70b3dea55963bdb98384Mindy Pereira mCc = setupRecipients(R.id.cc); 332c17d073dd43871df36ea70b3dea55963bdb98384Mindy Pereira mBcc = setupRecipients(R.id.bcc); 3336349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira mSubject = (TextView) findViewById(R.id.subject); 33446ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira mQuotedTextView = (QuotedTextView) findViewById(R.id.quoted_text_view); 33546ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira mQuotedTextView.setRespondInlineListener(this); 33646ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira mBodyText = (TextView) findViewById(R.id.body); 3371a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira mFromStatic = findViewById(R.id.static_from_content); 3381a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira mFromSpinner = findViewById(R.id.spinner_from_content); 3391a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira mFrom = (Spinner) findViewById(R.id.from_picker); 3401a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira } 3411a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira 3421a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira /** 3431a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira * Show the static from text view or the spinner 3441a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira * @param showSpinner Whether the spinner should be shown 3451a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira */ 3461a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira private void showFromSpinner(boolean showSpinner) { 3471a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira // show/hide the static text 3481a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira mFromStatic.setVisibility( 3491a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira showSpinner ? View.GONE : View.VISIBLE); 3501a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira 3511a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira // show/hide the spinner 3521a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira mFromSpinner.setVisibility( 3531a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira showSpinner ? View.VISIBLE : View.GONE); 35446ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira } 35546ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira 35646ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira private void setQuotedTextVisibility(boolean show) { 35746ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira mQuotedTextView.setVisibility(show ? View.VISIBLE : View.GONE); 358326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } 359326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira 360326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira private void initActionBar(int action) { 361326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira mComposeMode = action; 362326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira mActionBar = getActionBar(); 363326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira if (action == ComposeActivity.COMPOSE) { 364326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira mActionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_STANDARD); 365326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira mActionBar.setTitle(R.string.compose); 366326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } else { 367326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira mActionBar.setTitle(null); 368326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira if (mComposeModeAdapter == null) { 369326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira mComposeModeAdapter = new ComposeModeAdapter(this); 370326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } 371326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira mActionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_LIST); 372326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira mActionBar.setListNavigationCallbacks(mComposeModeAdapter, this); 373326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira switch (action) { 374326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira case ComposeActivity.REPLY: 375326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira mActionBar.setSelectedNavigationItem(0); 376326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira break; 377326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira case ComposeActivity.REPLY_ALL: 378326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira mActionBar.setSelectedNavigationItem(1); 379326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira break; 380326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira case ComposeActivity.FORWARD: 381326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira mActionBar.setSelectedNavigationItem(2); 382326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira break; 383326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } 3846349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira } 3856349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira } 3866349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira 38746ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira private void initFromRefMessage(int action, String recipientAddress) { 3886349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira ContentResolver resolver = getContentResolver(); 3896349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira Cursor refMessage = resolver.query(mRefMessageUri, UIProvider.MESSAGE_PROJECTION, null, 3906349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira null, null); 3916349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira if (refMessage != null) { 39246ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira try { 39346ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira refMessage.moveToFirst(); 39446ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira setSubject(refMessage, action); 39546ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira // Setup recipients 39646ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira if (action == FORWARD) { 39746ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira mForward = true; 39846ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira } 39946ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira setQuotedTextVisibility(true); 40046ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira initRecipientsFromRefMessageCursor(recipientAddress, refMessage, action); 40146ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira initBodyFromRefMessage(refMessage, action); 40246ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira if (action == ComposeActivity.FORWARD || mAttachmentsChanged) { 40346ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira updateAttachments(action, refMessage); 40446ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira } else { 40546ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira // Clear the attachments. 40646ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira removeAllAttachments(); 40746ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira } 40846ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira updateHideOrShowCcBcc(); 40946ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira } finally { 41046ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira refMessage.close(); 41146ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira } 4126349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira } 413c17d073dd43871df36ea70b3dea55963bdb98384Mindy Pereira } 414c17d073dd43871df36ea70b3dea55963bdb98384Mindy Pereira 41546ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira private void initBodyFromRefMessage(Cursor refMessage, int action) { 41646ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira boolean forward = action == FORWARD; 41746ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira DateFormat dateFormat = DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.SHORT); 41846ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira Date date = new Date(refMessage.getLong(UIProvider.MESSAGE_DATE_RECEIVED_MS_COLUMN)); 41946ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira StringBuffer quotedText = new StringBuffer(); 42046ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira 42146ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira if (action == ComposeActivity.REPLY || action == ComposeActivity.REPLY_ALL) { 42246ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira quotedText.append(QUOTE_BEGIN); 42346ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira quotedText 42446ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira .append(String.format( 42546ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira getString(R.string.reply_attribution), 42646ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira dateFormat.format(date), 42746ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira Utils.cleanUpString( 42846ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira refMessage.getString(UIProvider.MESSAGE_FROM_COLUMN), true))); 42946ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira quotedText.append(HEADER_SEPARATOR); 43046ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira quotedText.append(BLOCKQUOTE_BEGIN); 43146ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira quotedText.append(refMessage.getString(UIProvider.MESSAGE_BODY_HTML)); 43246ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira quotedText.append(BLOCKQUOTE_END); 43346ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira quotedText.append(QUOTE_END); 43446ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira } else if (action == ComposeActivity.FORWARD) { 43546ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira quotedText.append(QUOTE_BEGIN); 43646ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira quotedText 43746ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira .append(String.format(getString(R.string.forward_attribution), Utils 43846ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira .cleanUpString(refMessage.getString(UIProvider.MESSAGE_FROM_COLUMN), 43946ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira true /* remove empty quotes */), dateFormat.format(date), Utils 44046ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira .cleanUpString(refMessage.getString(UIProvider.MESSAGE_SUBJECT_COLUMN), 44146ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira false /* don't remove empty quotes */), Utils.cleanUpString( 44246ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira refMessage.getString(UIProvider.MESSAGE_TO_COLUMN), true))); 44346ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira String ccAddresses = refMessage.getString(UIProvider.MESSAGE_CC_COLUMN); 44446ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira quotedText.append(String.format(getString(R.string.cc_attribution), 44546ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira Utils.cleanUpString(ccAddresses, true /* remove empty quotes */))); 44646ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira } 44746ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira quotedText.append(HEADER_SEPARATOR); 44846ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira quotedText.append(refMessage.getString(UIProvider.MESSAGE_BODY_HTML)); 44946ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira quotedText.append(QUOTE_END); 45046ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira setQuotedText(quotedText.toString(), !forward); 45146ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira } 45246ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira 45346ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira /** 45446ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira * Fill the quoted text WebView. There is no point in having a "Show quoted 45546ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira * text" checkbox in a forwarded message so make sure mForward is 45646ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira * initialized properly before calling this method so we can hide it. 45746ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira */ 45846ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira public void setQuotedText(CharSequence text, boolean allow) { 45946ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira // There is no way to retrieve this string from the WebView once it's 46046ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira // been loaded, so we need to store it here. 46146ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira mQuotedTextView.setQuotedText(text); 46246ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira mQuotedTextView.allowQuotedText(allow); 46346ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira // If there is quoted text, we always allow respond inline, since this 46446ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira // may be a forward. 46546ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira mQuotedTextView.allowRespondInline(true); 46646ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira } 46746ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira 46846ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira private void updateHideOrShowCcBcc() { 469ec8b0edb23c0e0b7f1a8ce9558a919be31169d45Mindy Pereira // Its possible there is a menu item OR a button. 470a26b54e3a858de409be3746e65591bb8a0d6ea9aMindy Pereira boolean ccVisible = !TextUtils.isEmpty(mCc.getText()); 471a26b54e3a858de409be3746e65591bb8a0d6ea9aMindy Pereira boolean bccVisible = !TextUtils.isEmpty(mBcc.getText()); 472a26b54e3a858de409be3746e65591bb8a0d6ea9aMindy Pereira if (ccVisible || bccVisible) { 473a26b54e3a858de409be3746e65591bb8a0d6ea9aMindy Pereira mCcBccView.show(false, ccVisible, bccVisible); 474a26b54e3a858de409be3746e65591bb8a0d6ea9aMindy Pereira } 475ec8b0edb23c0e0b7f1a8ce9558a919be31169d45Mindy Pereira if (mCcBccButton != null) { 476ec8b0edb23c0e0b7f1a8ce9558a919be31169d45Mindy Pereira if (!mCc.isShown() || !mBcc.isShown()) { 477ec8b0edb23c0e0b7f1a8ce9558a919be31169d45Mindy Pereira mCcBccButton.setVisibility(View.VISIBLE); 478ec8b0edb23c0e0b7f1a8ce9558a919be31169d45Mindy Pereira mCcBccButton.setText(getString(!mCc.isShown() ? R.string.add_cc_label 479ec8b0edb23c0e0b7f1a8ce9558a919be31169d45Mindy Pereira : R.string.add_bcc_label)); 480ec8b0edb23c0e0b7f1a8ce9558a919be31169d45Mindy Pereira } else { 481ec8b0edb23c0e0b7f1a8ce9558a919be31169d45Mindy Pereira mCcBccButton.setVisibility(View.GONE); 482ec8b0edb23c0e0b7f1a8ce9558a919be31169d45Mindy Pereira } 483ec8b0edb23c0e0b7f1a8ce9558a919be31169d45Mindy Pereira } 48446ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira } 48546ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira 48646ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira public void removeAllAttachments() { 48746ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira mAttachmentsView.removeAllViews(); 48846ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira } 48946ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira 49046ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira private void updateAttachments(int action, Cursor refMessage) { 49146ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira // TODO: when we hook up attachments, make this work properly. 49246ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira } 49346ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira 494013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira @Override 495013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira protected final void onActivityResult(int request, int result, Intent data) { 496013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira mAddingAttachment = false; 497013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira if (result != RESULT_OK) { 498013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira return; 499013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira } 500013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira 501013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira if (request == RESULT_PICK_ATTACHMENT) { 502013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira addAttachmentAndUpdateView(data); 503013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira } 504013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira } 505013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira /** 506013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira * Add attachment and update the compose area appropriately. 507013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira * @param data 508013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira */ 509013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira public void addAttachmentAndUpdateView(Intent data) { 510013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira Uri uri = data != null ? data.getData() : null; 511013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira if (uri != null && !TextUtils.isEmpty(uri.getPath())) { 512013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira mAttachmentsChanged = true; 513013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira String contentType = getContentResolver().getType(uri); 514013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira try { 515013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira addAttachment(uri, contentType, false /* doSave */); 516013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira } catch (AttachmentFailureException e) { 517013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira // A toast has already been shown to the user, no need to do anything. 518013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira LogUtils.e(LOG_TAG, e, "Error adding attachment"); 519013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira } 520013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira } else { 521013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira showAttachmentTooBigToast(); 522013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira } 523013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira } 524013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira 525013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira @VisibleForTesting 526013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira protected int getSizeFromFile(Uri uri, ContentResolver contentResolver) { 527013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira int size = -1; 528013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira ParcelFileDescriptor file = null; 529013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira try { 530013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira file = contentResolver.openFileDescriptor(uri, "r"); 531013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira size = (int) file.getStatSize(); 532013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira } catch (FileNotFoundException e) { 533013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira LogUtils.w(LOG_TAG, "Error opening file to obtain size."); 534013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira } finally { 535013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira try { 536013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira if (file != null) { 537013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira file.close(); 538013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira } 539013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira } catch (IOException e) { 540013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira LogUtils.w(LOG_TAG, "Error closing file opened to obtain size."); 541013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira } 542013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira } 543013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira return size; 544013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira } 545013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira 546013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira /** 547013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira * Adds an attachment 548013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira * @param uri the uri to attach 549013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira * @param contentType the type of the resource pointed to by the URI or null if the type is 550013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira * unknown 551013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira * @param doSave whether the message should be saved 552013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira * 553013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira * @return int size of the attachment added. 554013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira * @throws AttachmentFailureException if an error occurs adding the attachment. 555013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira */ 556013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira private int addAttachment(Uri uri, String contentType, boolean doSave) 557013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira throws AttachmentFailureException { 558013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira final ContentResolver contentResolver = getContentResolver(); 559013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira if (contentType == null) contentType = ""; 560013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira 561013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira MockAttachment attachment = new MockAttachment(); 562013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira // partId will be assigned by the engine. 563013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira attachment.name = null; 564013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira attachment.contentType = contentType; 565013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira attachment.size = 0; 566013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira attachment.simpleContentType = contentType; 567013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira attachment.origin = uri; 568013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira attachment.originExtras = uri.toString(); 569013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira 570013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira Cursor metadataCursor = null; 571013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira try { 572013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira metadataCursor = contentResolver.query( 573013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira uri, new String[]{OpenableColumns.DISPLAY_NAME, OpenableColumns.SIZE}, 574013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira null, null, null); 575013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira if (metadataCursor != null) { 576013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira try { 577013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira if (metadataCursor.moveToNext()) { 578013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira attachment.name = metadataCursor.getString(0); 579013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira attachment.size = metadataCursor.getInt(1); 580013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira } 581013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira } finally { 582013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira metadataCursor.close(); 583013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira } 584013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira } 585013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira } catch (SQLiteException ex) { 586013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira // One of the two columns is probably missing, let's make one more attempt to get at 587013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira // least one. 588013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira // Note that the documentations in Intent#ACTION_OPENABLE and 589013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira // OpenableColumns seem to contradict each other about whether these columns are 590013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira // required, but it doesn't hurt to fail properly. 591013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira 592013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira // Let's try to get DISPLAY_NAME 593013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira try { 594013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira metadataCursor = 595013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira getOptionalColumn(contentResolver, uri, OpenableColumns.DISPLAY_NAME); 596013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira if (metadataCursor != null && metadataCursor.moveToNext()) { 597013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira attachment.name = metadataCursor.getString(0); 598013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira } 599013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira } finally { 600013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira if (metadataCursor != null) metadataCursor.close(); 601013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira } 602013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira 603013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira // Let's try to get SIZE 604013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira try { 605013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira metadataCursor = 606013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira getOptionalColumn(contentResolver, uri, OpenableColumns.SIZE); 607013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira if (metadataCursor != null && metadataCursor.moveToNext()) { 608013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira attachment.size = metadataCursor.getInt(0); 609013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira } else { 610013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira // Unable to get the size from the metadata cursor. Open the file and seek. 611013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira attachment.size = getSizeFromFile(uri, contentResolver); 612013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira } 613013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira } finally { 614013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira if (metadataCursor != null) metadataCursor.close(); 615013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira } 616013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira } catch (SecurityException e) { 617013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira // We received a security exception when attempting to add an 618013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira // attachment. Warn the user. 619013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira // TODO(pwestbro): determine if we need more specific text in the toast. 620013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira Toast.makeText(this, 621013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira R.string.generic_attachment_problem, Toast.LENGTH_LONG).show(); 622013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira throw new AttachmentFailureException("Security Exception from attachment uri", e); 623013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira } 624013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira 625013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira if (attachment.name == null) { 626013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira attachment.name = uri.getLastPathSegment(); 627013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira } 628013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira 629013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira int maxSize = UIProvider.getMailMaxAttachmentSize(mAccount); 630013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira 631013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira // Error getting the size or the size was too big. 632013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira if (attachment.size == -1 || attachment.size > maxSize) { 633013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira showAttachmentTooBigToast(); 634013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira throw new AttachmentFailureException("Attachment too large to attach"); 635013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira } else if ((mAttachmentsView.getTotalAttachmentsSize() 636013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira + attachment.size) > maxSize) { 637013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira showAttachmentTooBigToast(); 638013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira throw new AttachmentFailureException("Attachment too large to attach"); 639013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira } else { 640013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira addAttachment(attachment); 641013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira } 642013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira 643013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira return attachment.size; 644013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira } 645013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira 646013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira /** 647013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira * @return a cursor to the requested column or null if an exception occurs while trying 648013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira * to query it. 649013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira */ 650013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira private Cursor getOptionalColumn(ContentResolver contentResolver, Uri uri, String columnName) { 651013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira Cursor result = null; 652013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira try { 653013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira result = contentResolver.query(uri, new String[]{columnName}, null, null, null); 654013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira } catch (SQLiteException ex) { 655013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira // ignore, leave result null 656013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira } 657013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira return result; 658013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira } 659013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira 660013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira /** 661013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira * Add attachment. 662013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira * @param attachment 663013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira */ 664013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira public void addAttachment(Attachment attachment) { 665013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira mAttachmentsView.addAttachment(attachment); 666013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira } 667013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira 668013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira /** 669013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira * When an attachment is too large to be added to a message, show a toast. 670013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira * This method also updates the position of the toast so that it is shown 671013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira * clearly above they keyboard if it happens to be open. 672013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira */ 673013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira private void showAttachmentTooBigToast() { 674013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira Toast t = Toast.makeText(this, R.string.generic_attachment_problem, Toast.LENGTH_LONG); 675013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira t.setText(R.string.too_large_to_attach); 676013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira t.setGravity(Gravity.CENTER_HORIZONTAL, 0, getResources() 677013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira .getDimensionPixelSize(R.dimen.attachment_toast_yoffset)); 678013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira t.show(); 679013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira } 680013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira 681013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira /** 682013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira * Class containing information about failures when adding attachments. 683013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira */ 684013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira class AttachmentFailureException extends Exception { 685013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira private static final long serialVersionUID = 1L; 686013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira 687013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira public AttachmentFailureException(String error) { 688013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira super(error); 689013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira } 690013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira public AttachmentFailureException(String detailMessage, Throwable throwable) { 691013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira super(detailMessage, throwable); 692013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira } 693013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira } 694013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira 69546ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira private void initRecipientsFromRefMessageCursor(String recipientAddress, Cursor refMessage, 69646ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira int action) { 6974a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira // Don't populate the address if this is a forward. 6984a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira if (action == ComposeActivity.FORWARD) { 6994a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira return; 7004a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira } 7014a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira initReplyRecipients(mAccount, refMessage, action); 7024a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira } 7034a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira 7044a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira private void initReplyRecipients(String account, Cursor refMessage, int action) { 7054a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira // This is the email address of the current user, i.e. the one composing 7064a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira // the reply. 7074a20b708dd9ff3fb2b96f29b0b59012194c6fa34Mindy Pereira final String accountEmail = Address.getEmailAddress(account).getAddress(); 7084a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira String fromAddress = refMessage.getString(UIProvider.MESSAGE_FROM_COLUMN); 7094a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira String[] sentToAddresses = Utils.splitCommaSeparatedString(refMessage 7104a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira .getString(UIProvider.MESSAGE_TO_COLUMN)); 7114a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira String[] replytoAddresses = Utils.splitCommaSeparatedString(refMessage 7124a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira .getString(UIProvider.MESSAGE_REPLY_TO_COLUMN)); 713a26b54e3a858de409be3746e65591bb8a0d6ea9aMindy Pereira final Collection<String> toAddresses; 7144a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira 7154a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira // If this is a reply, the Cc list is empty. If this is a reply-all, the 7164a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira // Cc list is the union of the To and Cc recipients of the original 7174a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira // message, excluding the current user's email address and any addresses 718a26b54e3a858de409be3746e65591bb8a0d6ea9aMindy Pereira // already on the To list. 719a26b54e3a858de409be3746e65591bb8a0d6ea9aMindy Pereira if (action == ComposeActivity.REPLY) { 720a26b54e3a858de409be3746e65591bb8a0d6ea9aMindy Pereira toAddresses = initToRecipients(account, accountEmail, fromAddress, 721a26b54e3a858de409be3746e65591bb8a0d6ea9aMindy Pereira replytoAddresses, new String[0]); 722a26b54e3a858de409be3746e65591bb8a0d6ea9aMindy Pereira addToAddresses(toAddresses); 723a26b54e3a858de409be3746e65591bb8a0d6ea9aMindy Pereira } else if (action == ComposeActivity.REPLY_ALL) { 7244a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira final Set<String> ccAddresses = Sets.newHashSet(); 725a26b54e3a858de409be3746e65591bb8a0d6ea9aMindy Pereira toAddresses = initToRecipients(account, accountEmail, fromAddress, 726a26b54e3a858de409be3746e65591bb8a0d6ea9aMindy Pereira replytoAddresses, new String[0]); 7274a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira addRecipients(accountEmail, ccAddresses, sentToAddresses); 7284a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira addRecipients(accountEmail, ccAddresses, Utils.splitCommaSeparatedString(refMessage 7294a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira .getString(UIProvider.MESSAGE_CC_COLUMN))); 7304a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira addCcAddresses(ccAddresses, toAddresses); 7314a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira } 7324a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira } 7334a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira 7344a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira private void addToAddresses(Collection<String> addresses) { 7354a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira addAddressesToList(addresses, mTo); 7364a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira } 7374a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira 7384a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira private void addCcAddresses(Collection<String> addresses, Collection<String> toAddresses) { 7394a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira addCcAddressesToList(tokenizeAddressList(addresses), tokenizeAddressList(toAddresses), 7404a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira mCc); 7414a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira } 7424a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira 7434a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira @VisibleForTesting 7444a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira protected void addCcAddressesToList(List<Rfc822Token[]> addresses, 7454a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira List<Rfc822Token[]> compareToList, RecipientEditTextView list) { 7464a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira String address; 7474a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira 7484a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira HashSet<String> compareTo = convertToHashSet(compareToList); 7494a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira for (Rfc822Token[] tokens : addresses) { 7504a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira for (int i = 0; i < tokens.length; i++) { 7514a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira address = tokens[i].toString(); 7524a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira // Check if this is a duplicate: 7534a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira if (!compareTo.contains(tokens[i].getAddress())) { 7544a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira // Get the address here 7554a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira list.append(address + END_TOKEN); 7564a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira } 7574a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira } 7584a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira } 7594a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira } 7604a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira 7614a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira private void addAddressesToList(List<Rfc822Token[]> addresses, RecipientEditTextView list) { 7624a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira String address; 7634a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira for (Rfc822Token[] tokens : addresses) { 7644a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira for (int i = 0; i < tokens.length; i++) { 7654a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira address = tokens[i].toString(); 7664a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira list.append(address + END_TOKEN); 7674a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira } 7684a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira } 7694a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira } 7704a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira 7714a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira private HashSet<String> convertToHashSet(List<Rfc822Token[]> list) { 7724a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira HashSet<String> hash = new HashSet<String>(); 7734a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira for (Rfc822Token[] tokens : list) { 7744a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira for (int i = 0; i < tokens.length; i++) { 7754a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira hash.add(tokens[i].getAddress()); 7764a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira } 7774a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira } 7784a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira return hash; 7794a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira } 7804a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira 7814a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira private void addBccAddresses(Collection<String> addresses) { 7824a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira addAddressesToList(addresses, mBcc); 7834a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira } 7844a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira 7854a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira protected List<Rfc822Token[]> tokenizeAddressList(Collection<String> addresses) { 7864a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira @VisibleForTesting 7874a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira List<Rfc822Token[]> tokenized = new ArrayList<Rfc822Token[]>(); 7884a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira 7894a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira for (String address: addresses) { 7904a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira tokenized.add(Rfc822Tokenizer.tokenize(address)); 7914a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira } 7924a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira return tokenized; 7934a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira } 7944a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira 7954a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira @VisibleForTesting 7964a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira void addAddressesToList(Collection<String> addresses, RecipientEditTextView list) { 7974a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira for (String address : addresses) { 7984a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira addAddressToList(address, list); 7994a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira } 8004a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira } 8014a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira 8024a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira private void addAddressToList(String address, RecipientEditTextView list) { 8034a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira if (address == null || list == null) 8044a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira return; 8054a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira 8064a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira Rfc822Token[] tokens = Rfc822Tokenizer.tokenize(address); 8074a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira 8084a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira for (int i = 0; i < tokens.length; i++) { 8094a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira list.append(tokens[i] + END_TOKEN); 8104a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira } 8114a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira } 8124a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira 8134a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira @VisibleForTesting 8144a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira protected Collection<String> initToRecipients(String account, String accountEmail, 8154a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira String senderAddress, String[] replyToAddresses, String[] inToAddresses) { 8164a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira // The To recipient is the reply-to address specified in the original 8174a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira // message, unless it is: 8184a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira // the current user OR a custom from of the current user, in which case 8194a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira // it's the To recipient list of the original message. 8204a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira // OR missing, in which case use the sender of the original message 8214a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira Set<String> toAddresses = Sets.newHashSet(); 8224a20b708dd9ff3fb2b96f29b0b59012194c6fa34Mindy Pereira Address sender = Address.getEmailAddress(senderAddress); 8234a20b708dd9ff3fb2b96f29b0b59012194c6fa34Mindy Pereira if (sender != null && sender.getAddress().equalsIgnoreCase(account)) { 8244a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira // The sender address is this account, so reply acts like reply all. 8254a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira toAddresses.addAll(Arrays.asList(inToAddresses)); 8264a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira } else if (replyToAddresses != null && replyToAddresses.length != 0) { 8274a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira toAddresses.addAll(Arrays.asList(replyToAddresses)); 8284a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira } else { 8294a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira // Check to see if the sender address is one of the user's custom 8304a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira // from addresses. 8314a20b708dd9ff3fb2b96f29b0b59012194c6fa34Mindy Pereira if (senderAddress != null && sender != null 8324a20b708dd9ff3fb2b96f29b0b59012194c6fa34Mindy Pereira && !accountEmail.equalsIgnoreCase(sender.getAddress())) { 8334a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira // Replying to the sender of the original message is the most 8344a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira // common case. 8354a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira toAddresses.add(senderAddress); 8364a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira } else { 8374a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira // This happens if the user replies to a message they originally 8384a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira // wrote. In this case, "reply" really means "re-send," so we 8394a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira // target the original recipients. This works as expected even 8404a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira // if the user sent the original message to themselves. 8414a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira toAddresses.addAll(Arrays.asList(inToAddresses)); 8424a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira } 8434a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira } 8444a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira return toAddresses; 8454a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira } 8464a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira 8474a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira private static void addRecipients(String account, Set<String> recipients, String[] addresses) { 8484a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira for (String email : addresses) { 8494a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira // Do not add this account, or any of the custom froms, to the list 8504a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira // of recipients. 8514a20b708dd9ff3fb2b96f29b0b59012194c6fa34Mindy Pereira final String recipientAddress = Address.getEmailAddress(email).getAddress(); 8524a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira if (!account.equalsIgnoreCase(recipientAddress)) { 8534a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira recipients.add(email.replace("\"\"", "")); 8544a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira } 8554a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira } 85646ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira } 85746ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira 85846ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira private void setSubject(Cursor refMessage, int action) { 85946ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira String subject = refMessage.getString(UIProvider.MESSAGE_SUBJECT_COLUMN); 86046ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira String prefix; 86146ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira String correctedSubject = null; 86246ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira if (action == ComposeActivity.COMPOSE) { 86346ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira prefix = ""; 86446ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira } else if (action == ComposeActivity.FORWARD) { 86546ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira prefix = getString(R.string.forward_subject_label); 86646ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira } else { 86746ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira prefix = getString(R.string.reply_subject_label); 86846ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira } 86946ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira 87046ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira // Don't duplicate the prefix 87146ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira if (subject.toLowerCase().startsWith(prefix.toLowerCase())) { 87246ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira correctedSubject = subject; 87346ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira } else { 87446ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira correctedSubject = String 87546ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira .format(getString(R.string.formatted_subject), prefix, subject); 87646ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira } 87746ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira mSubject.setText(correctedSubject); 87846ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira } 87946ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira 880c17d073dd43871df36ea70b3dea55963bdb98384Mindy Pereira private RecipientEditTextView setupRecipients(int id) { 881c17d073dd43871df36ea70b3dea55963bdb98384Mindy Pereira RecipientEditTextView view = (RecipientEditTextView) findViewById(id); 882c17d073dd43871df36ea70b3dea55963bdb98384Mindy Pereira view.setAdapter(new RecipientAdapter(this, mAccount)); 883c17d073dd43871df36ea70b3dea55963bdb98384Mindy Pereira view.setTokenizer(new Rfc822Tokenizer()); 884c17d073dd43871df36ea70b3dea55963bdb98384Mindy Pereira if (mRecipientValidator == null) { 885c17d073dd43871df36ea70b3dea55963bdb98384Mindy Pereira int offset = mAccount.indexOf("@") + 1; 886c17d073dd43871df36ea70b3dea55963bdb98384Mindy Pereira String account = mAccount; 887c17d073dd43871df36ea70b3dea55963bdb98384Mindy Pereira if (offset > -1) { 888c17d073dd43871df36ea70b3dea55963bdb98384Mindy Pereira account = account.substring(mAccount.indexOf("@") + 1); 889c17d073dd43871df36ea70b3dea55963bdb98384Mindy Pereira } 890c17d073dd43871df36ea70b3dea55963bdb98384Mindy Pereira mRecipientValidator = new Rfc822Validator(account); 891c17d073dd43871df36ea70b3dea55963bdb98384Mindy Pereira } 892c17d073dd43871df36ea70b3dea55963bdb98384Mindy Pereira view.setValidator(mRecipientValidator); 893c17d073dd43871df36ea70b3dea55963bdb98384Mindy Pereira return view; 8948e9305ec0bbe23cec01eb34a2aee76c55199a10aMindy Pereira } 8958e9305ec0bbe23cec01eb34a2aee76c55199a10aMindy Pereira 8968e9305ec0bbe23cec01eb34a2aee76c55199a10aMindy Pereira @Override 8978e9305ec0bbe23cec01eb34a2aee76c55199a10aMindy Pereira public void onClick(View v) { 8988e9305ec0bbe23cec01eb34a2aee76c55199a10aMindy Pereira int id = v.getId(); 8998e9305ec0bbe23cec01eb34a2aee76c55199a10aMindy Pereira switch (id) { 900a26b54e3a858de409be3746e65591bb8a0d6ea9aMindy Pereira case R.id.add_cc_bcc: 9018e9305ec0bbe23cec01eb34a2aee76c55199a10aMindy Pereira // Verify that cc/ bcc aren't showing. 9028e9305ec0bbe23cec01eb34a2aee76c55199a10aMindy Pereira // Animate in cc/bcc. 903a26b54e3a858de409be3746e65591bb8a0d6ea9aMindy Pereira showCcBccViews(); 9048e9305ec0bbe23cec01eb34a2aee76c55199a10aMindy Pereira break; 9058e9305ec0bbe23cec01eb34a2aee76c55199a10aMindy Pereira } 9068e9305ec0bbe23cec01eb34a2aee76c55199a10aMindy Pereira } 907b47f3e286bcf78e85ab2d3389e38e99020d0634fMindy Pereira 908b47f3e286bcf78e85ab2d3389e38e99020d0634fMindy Pereira @Override 909b47f3e286bcf78e85ab2d3389e38e99020d0634fMindy Pereira public boolean onCreateOptionsMenu(Menu menu) { 910b47f3e286bcf78e85ab2d3389e38e99020d0634fMindy Pereira super.onCreateOptionsMenu(menu); 911b47f3e286bcf78e85ab2d3389e38e99020d0634fMindy Pereira MenuInflater inflater = getMenuInflater(); 912b47f3e286bcf78e85ab2d3389e38e99020d0634fMindy Pereira inflater.inflate(R.menu.compose_menu, menu); 913b47f3e286bcf78e85ab2d3389e38e99020d0634fMindy Pereira return true; 914b47f3e286bcf78e85ab2d3389e38e99020d0634fMindy Pereira } 915b47f3e286bcf78e85ab2d3389e38e99020d0634fMindy Pereira 916b47f3e286bcf78e85ab2d3389e38e99020d0634fMindy Pereira @Override 917ec8b0edb23c0e0b7f1a8ce9558a919be31169d45Mindy Pereira public boolean onPrepareOptionsMenu(Menu menu) { 918ec8b0edb23c0e0b7f1a8ce9558a919be31169d45Mindy Pereira MenuItem ccBcc = menu.findItem(R.id.add_cc_bcc); 919ec8b0edb23c0e0b7f1a8ce9558a919be31169d45Mindy Pereira if (ccBcc != null) { 920ec8b0edb23c0e0b7f1a8ce9558a919be31169d45Mindy Pereira // Its possible there is a menu item OR a button. 921ec8b0edb23c0e0b7f1a8ce9558a919be31169d45Mindy Pereira boolean ccFieldVisible = mCc.isShown(); 922ec8b0edb23c0e0b7f1a8ce9558a919be31169d45Mindy Pereira boolean bccFieldVisible = mBcc.isShown(); 923ec8b0edb23c0e0b7f1a8ce9558a919be31169d45Mindy Pereira if (!ccFieldVisible || !bccFieldVisible) { 924ec8b0edb23c0e0b7f1a8ce9558a919be31169d45Mindy Pereira ccBcc.setVisible(true); 925ec8b0edb23c0e0b7f1a8ce9558a919be31169d45Mindy Pereira ccBcc.setTitle(getString(!ccFieldVisible ? R.string.add_cc_label 926ec8b0edb23c0e0b7f1a8ce9558a919be31169d45Mindy Pereira : R.string.add_bcc_label)); 927ec8b0edb23c0e0b7f1a8ce9558a919be31169d45Mindy Pereira } else { 928ec8b0edb23c0e0b7f1a8ce9558a919be31169d45Mindy Pereira ccBcc.setVisible(false); 929ec8b0edb23c0e0b7f1a8ce9558a919be31169d45Mindy Pereira } 930ec8b0edb23c0e0b7f1a8ce9558a919be31169d45Mindy Pereira } 931ec8b0edb23c0e0b7f1a8ce9558a919be31169d45Mindy Pereira return true; 932ec8b0edb23c0e0b7f1a8ce9558a919be31169d45Mindy Pereira } 933ec8b0edb23c0e0b7f1a8ce9558a919be31169d45Mindy Pereira 934ec8b0edb23c0e0b7f1a8ce9558a919be31169d45Mindy Pereira @Override 935b47f3e286bcf78e85ab2d3389e38e99020d0634fMindy Pereira public boolean onOptionsItemSelected(MenuItem item) { 936b47f3e286bcf78e85ab2d3389e38e99020d0634fMindy Pereira int id = item.getItemId(); 937b47f3e286bcf78e85ab2d3389e38e99020d0634fMindy Pereira boolean handled = false; 938b47f3e286bcf78e85ab2d3389e38e99020d0634fMindy Pereira switch (id) { 9397b56a61174eeb202eea468b7f68b79729737ded2Mindy Pereira case R.id.add_attachment: 940013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira doAttach(); 9417b56a61174eeb202eea468b7f68b79729737ded2Mindy Pereira break; 942ec8b0edb23c0e0b7f1a8ce9558a919be31169d45Mindy Pereira case R.id.add_cc_bcc: 943ec8b0edb23c0e0b7f1a8ce9558a919be31169d45Mindy Pereira showCcBccViews(); 944b47f3e286bcf78e85ab2d3389e38e99020d0634fMindy Pereira handled = true; 945b47f3e286bcf78e85ab2d3389e38e99020d0634fMindy Pereira break; 946b47f3e286bcf78e85ab2d3389e38e99020d0634fMindy Pereira } 947b47f3e286bcf78e85ab2d3389e38e99020d0634fMindy Pereira return !handled ? super.onOptionsItemSelected(item) : handled; 948b47f3e286bcf78e85ab2d3389e38e99020d0634fMindy Pereira } 949326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira 950013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira public void doAttach() { 951013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira Intent i = new Intent(Intent.ACTION_GET_CONTENT); 952013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira i.addCategory(Intent.CATEGORY_OPENABLE); 953013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira if (Settings.System.getInt( 954013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira getContentResolver(), UIProvider.getAttachmentTypeSetting(), 0) != 0) { 955013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira i.setType("*/*"); 956013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira } else { 957013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira i.setType("image/*"); 958013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira } 959013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira mAddingAttachment = true; 960013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira startActivityForResult(Intent.createChooser(i, 961013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira getText(R.string.select_attachment_type)), RESULT_PICK_ATTACHMENT); 962013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira } 963013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira 964ec8b0edb23c0e0b7f1a8ce9558a919be31169d45Mindy Pereira private void showCcBccViews() { 965a26b54e3a858de409be3746e65591bb8a0d6ea9aMindy Pereira mCcBccView.show(true, true, true); 966ec8b0edb23c0e0b7f1a8ce9558a919be31169d45Mindy Pereira if (mCcBccButton != null) { 967ec8b0edb23c0e0b7f1a8ce9558a919be31169d45Mindy Pereira mCcBccButton.setVisibility(View.GONE); 968ec8b0edb23c0e0b7f1a8ce9558a919be31169d45Mindy Pereira } 969ec8b0edb23c0e0b7f1a8ce9558a919be31169d45Mindy Pereira } 970ec8b0edb23c0e0b7f1a8ce9558a919be31169d45Mindy Pereira 971326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira @Override 972326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira public boolean onNavigationItemSelected(int position, long itemId) { 973a26b54e3a858de409be3746e65591bb8a0d6ea9aMindy Pereira int initialComposeMode = mComposeMode; 974326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira if (position == ComposeActivity.REPLY) { 975326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira mComposeMode = ComposeActivity.REPLY; 976326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } else if (position == ComposeActivity.REPLY_ALL) { 977326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira mComposeMode = ComposeActivity.REPLY_ALL; 978326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } else if (position == ComposeActivity.FORWARD) { 979326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira mComposeMode = ComposeActivity.FORWARD; 980326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } 981a26b54e3a858de409be3746e65591bb8a0d6ea9aMindy Pereira if (initialComposeMode != mComposeMode) { 982a26b54e3a858de409be3746e65591bb8a0d6ea9aMindy Pereira initFromRefMessage(mComposeMode, mAccount); 983a26b54e3a858de409be3746e65591bb8a0d6ea9aMindy Pereira } 984326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira return true; 985326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } 986326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira 987326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira private class ComposeModeAdapter extends ArrayAdapter<String> { 988326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira 989326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira private LayoutInflater mInflater; 990326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira 991326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira public ComposeModeAdapter(Context context) { 992326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira super(context, R.layout.compose_mode_item, R.id.mode, getResources() 993326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira .getStringArray(R.array.compose_modes)); 994326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } 995326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira 996326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira private LayoutInflater getInflater() { 997326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira if (mInflater == null) { 998326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira mInflater = LayoutInflater.from(getContext()); 999326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } 1000326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira return mInflater; 1001326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } 1002326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira 1003326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira @Override 1004326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira public View getView(int position, View convertView, ViewGroup parent) { 1005326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira if (convertView == null) { 1006326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira convertView = getInflater().inflate(R.layout.compose_mode_display_item, null); 1007326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } 1008326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira ((TextView) convertView.findViewById(R.id.mode)).setText(getItem(position)); 1009326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira return super.getView(position, convertView, parent); 1010326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } 1011326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } 101246ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira 101346ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira @Override 101446ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira public void onRespondInline(String text) { 101546ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira appendToBody(text, false); 101646ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira } 101746ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira 101846ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira /** 101946ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira * Append text to the body of the message. If there is no existing body 102046ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira * text, just sets the body to text. 102146ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira * 102246ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira * @param text 102346ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira * @param withSignature True to append a signature. 102446ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira */ 102546ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira public void appendToBody(CharSequence text, boolean withSignature) { 102646ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira Editable bodyText = mBodyText.getEditableText(); 102746ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira if (bodyText != null && bodyText.length() > 0) { 102846ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira bodyText.append(text); 102946ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira } else { 103046ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira setBody(text, withSignature); 103146ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira } 103246ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira } 103346ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira 103446ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira /** 103546ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira * Set the body of the message. 103646ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira * @param text 103746ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira * @param withSignature True to append a signature. 103846ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira */ 103946ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira public void setBody(CharSequence text, boolean withSignature) { 104046ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira mBodyText.setText(text); 104146ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira } 10421a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira 10431a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira @Override 10441a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { 10451a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira // TODO 10461a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira } 10471a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira 10481a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira @Override 10491a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira public void onNothingSelected(AdapterView<?> parent) { 10501a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira // Do nothing. 10511a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira } 10528e9305ec0bbe23cec01eb34a2aee76c55199a10aMindy Pereira}