ComposeActivity.java revision 59e69095bd558a1e6ae890ce79b7b848331d0cc6
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 19326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereiraimport android.app.ActionBar; 205c5fd571b40a15b95ea5a5d6033f377706ffd0fbAndy Huangimport android.app.ActionBar.OnNavigationListener; 215c5fd571b40a15b95ea5a5d6033f377706ffd0fbAndy Huangimport android.app.Activity; 2282cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereiraimport android.app.ActivityManager; 2382cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereiraimport android.app.AlertDialog; 2482cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereiraimport android.app.Dialog; 252558b509117872e539a6eaeb72aa63425529d50bTony Mantlerimport android.app.DialogFragment; 26b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereiraimport android.app.Fragment; 27b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereiraimport android.app.FragmentTransaction; 2896a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereiraimport android.app.LoaderManager; 296349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereiraimport android.content.ContentResolver; 3082cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereiraimport android.content.ContentValues; 316349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereiraimport android.content.Context; 3296a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereiraimport android.content.CursorLoader; 3382cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereiraimport android.content.DialogInterface; 346349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereiraimport android.content.Intent; 3596a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereiraimport android.content.Loader; 3682cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereiraimport android.content.pm.ActivityInfo; 37bc5e0dcf723918eb986d733ef42d64bcf2ec4ed5Andrew Sappersteinimport android.content.res.Resources; 387ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereiraimport android.database.Cursor; 396349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereiraimport android.net.Uri; 408e9305ec0bbe23cec01eb34a2aee76c55199a10aMindy Pereiraimport android.os.Bundle; 4182cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereiraimport android.os.Handler; 4282cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereiraimport android.os.HandlerThread; 433c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrookimport android.os.ParcelFileDescriptor; 441ebc2db723ed29093d724eb5da906a496ee57224Alice Yangimport android.os.Parcelable; 4582cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereiraimport android.provider.BaseColumns; 4646ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereiraimport android.text.Editable; 4782cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereiraimport android.text.Html; 48ed9c2f0e9b6b7d7556c3d048c78c072c21e587a1mindypimport android.text.SpannableString; 4982cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereiraimport android.text.Spanned; 50c182762df95fd382faf8e4a25e5cf7783ea10176Paul Westbrookimport android.text.TextUtils; 5182cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereiraimport android.text.TextWatcher; 5246ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereiraimport android.text.util.Rfc822Token; 53c17d073dd43871df36ea70b3dea55963bdb98384Mindy Pereiraimport android.text.util.Rfc822Tokenizer; 543cd4f40dab2c0810cb5ecd77256abf022863b2b5Mindy Pereiraimport android.view.Gravity; 5562d3ec7f251f6f9a96a859a2702916d07f30a04amindypimport android.view.KeyEvent; 56326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereiraimport android.view.LayoutInflater; 57b47f3e286bcf78e85ab2d3389e38e99020d0634fMindy Pereiraimport android.view.Menu; 58b47f3e286bcf78e85ab2d3389e38e99020d0634fMindy Pereiraimport android.view.MenuInflater; 59b47f3e286bcf78e85ab2d3389e38e99020d0634fMindy Pereiraimport android.view.MenuItem; 608e9305ec0bbe23cec01eb34a2aee76c55199a10aMindy Pereiraimport android.view.View; 618e9305ec0bbe23cec01eb34a2aee76c55199a10aMindy Pereiraimport android.view.View.OnClickListener; 625c5fd571b40a15b95ea5a5d6033f377706ffd0fbAndy Huangimport android.view.ViewGroup; 63b4931c62bffec463df9c3871d83a35bbeb9d5920Paul Westbrookimport android.view.inputmethod.BaseInputConnection; 6462d3ec7f251f6f9a96a859a2702916d07f30a04amindypimport android.view.inputmethod.EditorInfo; 65326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereiraimport android.widget.ArrayAdapter; 668e9305ec0bbe23cec01eb34a2aee76c55199a10aMindy Pereiraimport android.widget.Button; 67433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereiraimport android.widget.EditText; 686349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereiraimport android.widget.TextView; 69013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereiraimport android.widget.Toast; 707b56a61174eeb202eea468b7f68b79729737ded2Mindy Pereira 71c17d073dd43871df36ea70b3dea55963bdb98384Mindy Pereiraimport com.android.common.Rfc822Validator; 729f32423b2e1f7ef6747eb1a27f3faa15f5a3db1cTony Mantlerimport com.android.common.contacts.DataUsageStatUpdater; 735c5fd571b40a15b95ea5a5d6033f377706ffd0fbAndy Huangimport com.android.ex.chips.RecipientEditTextView; 745680ec22f92125cbd95ff0f8d18d5cc04c6f0b81Scott Kennedyimport com.android.mail.MailIntentService; 755c5fd571b40a15b95ea5a5d6033f377706ffd0fbAndy Huangimport com.android.mail.R; 76761522c1ac7a8fa05acde714f0e26fde47f3415fAndy Huangimport com.android.mail.analytics.Analytics; 771ebc2db723ed29093d724eb5da906a496ee57224Alice Yangimport com.android.mail.browse.MessageHeaderView; 7840882430c874ff29890ec6fa31f7649788cbc470mindypimport com.android.mail.compose.AttachmentsView.AttachmentAddedOrDeletedListener; 799932dee248718d2cec993d93b5115973d1389d0aMindy Pereiraimport com.android.mail.compose.AttachmentsView.AttachmentFailureException; 805a85e2b7485a5c407c581219fe1b44417f050529Mindy Pereiraimport com.android.mail.compose.FromAddressSpinner.OnAccountChangedListener; 8130e2c24b056542f3b1b438aeb798305d1226d0c8Andy Huangimport com.android.mail.compose.QuotedTextView.RespondInlineListener; 8233fe908589dca6a7f58aa9f56d73f74a48ac42f6Mindy Pereiraimport com.android.mail.providers.Account; 8330e2c24b056542f3b1b438aeb798305d1226d0c8Andy Huangimport com.android.mail.providers.Address; 8430e2c24b056542f3b1b438aeb798305d1226d0c8Andy Huangimport com.android.mail.providers.Attachment; 855680ec22f92125cbd95ff0f8d18d5cc04c6f0b81Scott Kennedyimport com.android.mail.providers.Folder; 8647d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereiraimport com.android.mail.providers.MailAppProvider; 873ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereiraimport com.android.mail.providers.Message; 8882cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereiraimport com.android.mail.providers.MessageModification; 8992551d057965689f1952faeb06763f0762bc717fMindy Pereiraimport com.android.mail.providers.ReplyFromAccount; 90181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereiraimport com.android.mail.providers.Settings; 9130e2c24b056542f3b1b438aeb798305d1226d0c8Andy Huangimport com.android.mail.providers.UIProvider; 923ca5bad62c075184920c5e331870280fc6acca16Mindy Pereiraimport com.android.mail.providers.UIProvider.AccountCapabilities; 9312575866e5526e45eaf773c6c98c93c3a06fe156Mindy Pereiraimport com.android.mail.providers.UIProvider.DraftType; 941ebc2db723ed29093d724eb5da906a496ee57224Alice Yangimport com.android.mail.ui.AttachmentTile.AttachmentPreview; 9583e6b574cffd06164cad18ee388237a9427ceb3fPaul Westbrookimport com.android.mail.ui.FeedbackEnabledActivity; 96fa20c1a4e36e0da2577baddbbb38a988b2017339Mindy Pereiraimport com.android.mail.ui.MailActivity; 97b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereiraimport com.android.mail.ui.WaitFragment; 9892227f6b35b3bec54609dc0feb9dd6756c2a43e6Paul Westbrookimport com.android.mail.utils.AccountUtils; 99434f294a3ae17a4f76342af38d6376f672a5d9edMark Weiimport com.android.mail.utils.AttachmentUtils; 100febd226e871263aeb21d436bee81eb2f7dec3d03mindypimport com.android.mail.utils.ContentProviderTask; 101b334c9035e9b7a38766bb66c29da2208525d1e11Paul Westbrookimport com.android.mail.utils.LogTag; 10230e2c24b056542f3b1b438aeb798305d1226d0c8Andy Huangimport com.android.mail.utils.LogUtils; 10330e2c24b056542f3b1b438aeb798305d1226d0c8Andy Huangimport com.android.mail.utils.Utils; 10446ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereiraimport com.google.common.annotations.VisibleForTesting; 10582cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereiraimport com.google.common.collect.Lists; 1064a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereiraimport com.google.common.collect.Sets; 1078e9305ec0bbe23cec01eb34a2aee76c55199a10aMindy Pereira 1083c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrookimport java.io.FileNotFoundException; 1093c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrookimport java.io.IOException; 1108eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereiraimport java.io.UnsupportedEncodingException; 1118eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereiraimport java.net.URLDecoder; 11246ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereiraimport java.util.ArrayList; 113bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrookimport java.util.Arrays; 11446ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereiraimport java.util.Collection; 11575f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereiraimport java.util.HashMap; 11646ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereiraimport java.util.HashSet; 11746ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereiraimport java.util.List; 1181c078cff1958b29e280100bfa6221103ec46b555Paul Westbrookimport java.util.Map.Entry; 119bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrookimport java.util.Set; 12082cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereiraimport java.util.concurrent.ConcurrentHashMap; 12146ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira 12246ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereirapublic class ComposeActivity extends Activity implements OnClickListener, OnNavigationListener, 1232558b509117872e539a6eaeb72aa63425529d50bTony Mantler RespondInlineListener, TextWatcher, 124a990a715012379451344246c5156d29938f12886Alice Yang AttachmentAddedOrDeletedListener, OnAccountChangedListener, 125a990a715012379451344246c5156d29938f12886Alice Yang LoaderManager.LoaderCallbacks<Cursor>, TextView.OnEditorActionListener, 126a990a715012379451344246c5156d29938f12886Alice Yang FeedbackEnabledActivity { 1276349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira // Identifiers for which type of composition this is 128bc5e0dcf723918eb986d733ef42d64bcf2ec4ed5Andrew Sapperstein public static final int COMPOSE = -1; 129bc5e0dcf723918eb986d733ef42d64bcf2ec4ed5Andrew Sapperstein public static final int REPLY = 0; 130bc5e0dcf723918eb986d733ef42d64bcf2ec4ed5Andrew Sapperstein public static final int REPLY_ALL = 1; 131bc5e0dcf723918eb986d733ef42d64bcf2ec4ed5Andrew Sapperstein public static final int FORWARD = 2; 132bc5e0dcf723918eb986d733ef42d64bcf2ec4ed5Andrew Sapperstein public static final int EDIT_DRAFT = 3; 1336349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira 1346349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira // Integer extra holding one of the above compose action 13596a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira protected static final String EXTRA_ACTION = "action"; 1366349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira 137326689d531da1d2579fa7daaf6e307e24a05f993Mindy Pereira private static final String EXTRA_SHOW_CC = "showCc"; 138326689d531da1d2579fa7daaf6e307e24a05f993Mindy Pereira private static final String EXTRA_SHOW_BCC = "showBcc"; 1391623f9bfde8ced840a52820da28a0939bcaa32f9mindyp private static final String EXTRA_RESPONDED_INLINE = "respondedInline"; 1401d7e9145fa4f490ba87ade0ed70ce0fa1f33be81mindyp private static final String EXTRA_SAVE_ENABLED = "saveEnabled"; 141a34c9a054c9aef6f83abe56515c132a31d71b3c8Mindy Pereira 1428eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira private static final String UTF8_ENCODING_NAME = "UTF-8"; 1438eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira 1448eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira private static final String MAIL_TO = "mailto"; 1458eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira 1468eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira private static final String EXTRA_SUBJECT = "subject"; 1478eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira 1488eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira private static final String EXTRA_BODY = "body"; 1498eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira 150bc5e0dcf723918eb986d733ef42d64bcf2ec4ed5Andrew Sapperstein /** 151bc5e0dcf723918eb986d733ef42d64bcf2ec4ed5Andrew Sapperstein * Expected to be html formatted text. 152bc5e0dcf723918eb986d733ef42d64bcf2ec4ed5Andrew Sapperstein */ 153bc5e0dcf723918eb986d733ef42d64bcf2ec4ed5Andrew Sapperstein private static final String EXTRA_QUOTED_TEXT = "quotedText"; 154bc5e0dcf723918eb986d733ef42d64bcf2ec4ed5Andrew Sapperstein 155d27b6ea7fcc68b2af200158fab341c6e98727144mindyp protected static final String EXTRA_FROM_ACCOUNT_STRING = "fromAccountString"; 1569a42bb4f11c502dd5c2cf92249ac214a6c2f1a70Mindy Pereira 15762066e47fe69c33b60ed970e46809ba81d044064Mark Wei private static final String EXTRA_ATTACHMENT_PREVIEWS = "attachmentPreviews"; 15862066e47fe69c33b60ed970e46809ba81d044064Mark Wei 1598eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira // Extra that we can get passed from other activities 1608eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira private static final String EXTRA_TO = "to"; 1618eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira private static final String EXTRA_CC = "cc"; 1628eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira private static final String EXTRA_BCC = "bcc"; 1638eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira 16460847256c691b2677772a46919038f9c600fecf7Scott Kennedy /** 16560847256c691b2677772a46919038f9c600fecf7Scott Kennedy * An optional extra containing a {@link ContentValues} of values to be added to 16660847256c691b2677772a46919038f9c600fecf7Scott Kennedy * {@link SendOrSaveMessage#mValues}. 16760847256c691b2677772a46919038f9c600fecf7Scott Kennedy */ 16860847256c691b2677772a46919038f9c600fecf7Scott Kennedy public static final String EXTRA_VALUES = "extra-values"; 16960847256c691b2677772a46919038f9c600fecf7Scott Kennedy 1708eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira // List of all the fields 171bc5e0dcf723918eb986d733ef42d64bcf2ec4ed5Andrew Sapperstein static final String[] ALL_EXTRAS = { EXTRA_SUBJECT, EXTRA_BODY, EXTRA_TO, EXTRA_CC, EXTRA_BCC, 172bc5e0dcf723918eb986d733ef42d64bcf2ec4ed5Andrew Sapperstein EXTRA_QUOTED_TEXT }; 1738eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira 17482cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira private static SendOrSaveCallback sTestSendOrSaveCallback = null; 17582cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira // Map containing information about requests to create new messages, and the id of the 17682cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira // messages that were the result of those requests. 17782cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira // 17882cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira // This map is used when the activity that initiated the save a of a new message, is killed 17982cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira // before the save has completed (and when we know the id of the newly created message). When 18082cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira // a save is completed, the service that is running in the background, will update the map 18182cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira // 18282cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira // When a new ComposeActivity instance is created, it will attempt to use the information in 18382cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira // the previously instantiated map. If ComposeActivity.onCreate() is called, with a bundle 18482cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira // (restoring data from a previous instance), and the map hasn't been created, we will attempt 18582cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira // to populate the map with data stored in shared preferences. 1861f8f4dd8c53e6c18ae642235335ce492c9d1e520Andy Huang // FIXME: values in this map are never read. 18782cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira private static ConcurrentHashMap<Integer, Long> sRequestMessageIdMap = null; 1886349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira /** 1896349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira * Notifies the {@code Activity} that the caller is an Email 1906349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira * {@code Activity}, so that the back behavior may be modified accordingly. 1916349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira * 1926349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira * @see #onAppUpPressed 1936349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira */ 194daecb4b9b20a609b27fc803390ecf4f524b76089Paul Westbrook public static final String EXTRA_FROM_EMAIL_TASK = "fromemail"; 1956349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira 196e011b1d1c8e2e674dfdf1985d9d13da8cc06d803Mindy Pereira public static final String EXTRA_ATTACHMENTS = "attachments"; 197f97588bd03fdcd318e24a9d74a283e73d1fbd37cPaul Westbrook 1985680ec22f92125cbd95ff0f8d18d5cc04c6f0b81Scott Kennedy /** If set, we will clear notifications for this folder. */ 1995680ec22f92125cbd95ff0f8d18d5cc04c6f0b81Scott Kennedy public static final String EXTRA_NOTIFICATION_FOLDER = "extra-notification-folder"; 2005680ec22f92125cbd95ff0f8d18d5cc04c6f0b81Scott Kennedy 2013ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereira // If this is a reply/forward then this extra will hold the original message 20236bbcaeff2a6e57189e4f4818e0ccdf6317ce836Mindy Pereira private static final String EXTRA_IN_REFERENCE_TO_MESSAGE = "in-reference-to-message"; 203b18e5a9341c73541d7201830c513cb0ed247e935Mindy Pereira // If this is a reply/forward then this extra will hold a uri we must query 204b18e5a9341c73541d7201830c513cb0ed247e935Mindy Pereira // to get the original message. 205b18e5a9341c73541d7201830c513cb0ed247e935Mindy Pereira protected static final String EXTRA_IN_REFERENCE_TO_MESSAGE_URI = "in-reference-to-message-uri"; 206434f294a3ae17a4f76342af38d6376f672a5d9edMark Wei // If this is an action to edit an existing draft message, this extra will hold the 207bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook // draft message 208bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook private static final String ORIGINAL_DRAFT_MESSAGE = "original-draft-message"; 2094a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira private static final String END_TOKEN = ", "; 210b334c9035e9b7a38766bb66c29da2208525d1e11Paul Westbrook private static final String LOG_TAG = LogTag.getLogTag(); 211013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira // Request numbers for activities we start 212013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira private static final int RESULT_PICK_ATTACHMENT = 1; 213013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira private static final int RESULT_CREATE_ACCOUNT = 2; 2148eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira // TODO(mindyp) set mime-type for auto send? 215e011b1d1c8e2e674dfdf1985d9d13da8cc06d803Mindy Pereira public static final String AUTO_SEND_ACTION = "com.android.mail.action.AUTO_SEND"; 2168eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira 217e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira private static final String EXTRA_SELECTED_REPLY_FROM_ACCOUNT = "replyFromAccount"; 218e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira private static final String EXTRA_REQUEST_ID = "requestId"; 219e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira private static final String EXTRA_FOCUS_SELECTION_START = "focusSelectionStart"; 220176a1993ab15298de58f0cc988939b2cc1632689Paul Westbrook private static final String EXTRA_FOCUS_SELECTION_END = "focusSelectionEnd"; 221e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira private static final String EXTRA_MESSAGE = "extraMessage"; 22296a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira private static final int REFERENCE_MESSAGE_LOADER = 0; 223b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira private static final int LOADER_ACCOUNT_CURSOR = 1; 224a990a715012379451344246c5156d29938f12886Alice Yang private static final int INIT_DRAFT_USING_REFERENCE_MESSAGE = 2; 22547d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereira private static final String EXTRA_SELECTED_ACCOUNT = "selectedAccount"; 226b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira private static final String TAG_WAIT = "wait-fragment"; 2272db7d4a37b794e1721a5b9416068702aa799c5f8Mindy Pereira private static final String MIME_TYPE_PHOTO = "image/*"; 2282db7d4a37b794e1721a5b9416068702aa799c5f8Mindy Pereira private static final String MIME_TYPE_VIDEO = "video/*"; 2298e9305ec0bbe23cec01eb34a2aee76c55199a10aMindy Pereira 2309f855d667e34fbf0d330845225c26956e540b819Andy Huang private static final String KEY_INNER_SAVED_STATE = "compose_state"; 2319f855d667e34fbf0d330845225c26956e540b819Andy Huang 23282cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira /** 23382cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira * A single thread for running tasks in the background. 23482cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira */ 23582cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira private Handler mSendSaveTaskHandler = null; 236c17d073dd43871df36ea70b3dea55963bdb98384Mindy Pereira private RecipientEditTextView mTo; 237c17d073dd43871df36ea70b3dea55963bdb98384Mindy Pereira private RecipientEditTextView mCc; 238c17d073dd43871df36ea70b3dea55963bdb98384Mindy Pereira private RecipientEditTextView mBcc; 2398e9305ec0bbe23cec01eb34a2aee76c55199a10aMindy Pereira private Button mCcBccButton; 2408e9305ec0bbe23cec01eb34a2aee76c55199a10aMindy Pereira private CcBccView mCcBccView; 2417b56a61174eeb202eea468b7f68b79729737ded2Mindy Pereira private AttachmentsView mAttachmentsView; 24233fe908589dca6a7f58aa9f56d73f74a48ac42f6Mindy Pereira private Account mAccount; 24359e69095bd558a1e6ae890ce79b7b848331d0cc6Tony Mantler protected ReplyFromAccount mReplyFromAccount; 244181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira private Settings mCachedSettings; 24582cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira private Rfc822Validator mValidator; 2466349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira private TextView mSubject; 2476349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira 248326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira private ComposeModeAdapter mComposeModeAdapter; 249326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira private int mComposeMode = -1; 25046ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira private boolean mForward; 25146ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira private QuotedTextView mQuotedTextView; 25259e69095bd558a1e6ae890ce79b7b848331d0cc6Tony Mantler protected EditText mBodyView; 2531a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira private View mFromStatic; 2542eb173211741adf7454bbf1990ba1b9d1e1f6a64Mindy Pereira private TextView mFromStaticText; 255eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira private View mFromSpinnerWrapper; 2561883b346928322a9f045bc5b7426ddcd6af9beb3Mindy Pereira @VisibleForTesting 2571883b346928322a9f045bc5b7426ddcd6af9beb3Mindy Pereira protected FromAddressSpinner mFromSpinner; 258013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira private boolean mAddingAttachment; 259eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira private boolean mAttachmentsChanged; 26082cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira private boolean mTextChanged; 26182cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira private boolean mReplyFromChanged; 26282cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira private MenuItem mSave; 26382cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira private MenuItem mSend; 264b3112a2bf7b805695259e412b0e2bc0e0e73e9d6Mindy Pereira @VisibleForTesting 265b3112a2bf7b805695259e412b0e2bc0e0e73e9d6Mindy Pereira protected Message mRefMessage; 2667ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira private long mDraftId = UIProvider.INVALID_MESSAGE_ID; 2677ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira private Message mDraft; 26844a6339dd80f4b5b9e5d54567021698d92467c5emindyp private ReplyFromAccount mDraftAccount; 2697ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira private Object mDraftLock = new Object(); 27093b079ba1d38d919b557dabcd971e7aa1e3f5cbcmindyp private View mPhotoAttachmentsButton; 27193b079ba1d38d919b557dabcd971e7aa1e3f5cbcmindyp private View mVideoAttachmentsButton; 2723ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereira 273326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira /** 274daecb4b9b20a609b27fc803390ecf4f524b76089Paul Westbrook * Boolean indicating whether ComposeActivity was launched from a Gmail controlled view. 275daecb4b9b20a609b27fc803390ecf4f524b76089Paul Westbrook */ 276daecb4b9b20a609b27fc803390ecf4f524b76089Paul Westbrook private boolean mLaunchedFromEmail = false; 277cbfb75a0f92a3ef5cf10ab94b451e4898cc78bfcMindy Pereira private RecipientTextWatcher mToListener; 278cbfb75a0f92a3ef5cf10ab94b451e4898cc78bfcMindy Pereira private RecipientTextWatcher mCcListener; 279cbfb75a0f92a3ef5cf10ab94b451e4898cc78bfcMindy Pereira private RecipientTextWatcher mBccListener; 280b18e5a9341c73541d7201830c513cb0ed247e935Mindy Pereira private Uri mRefMessageUri; 281a990a715012379451344246c5156d29938f12886Alice Yang private boolean mShowQuotedText = false; 2829f855d667e34fbf0d330845225c26956e540b819Andy Huang private Bundle mInnerSavedState; 28360847256c691b2677772a46919038f9c600fecf7Scott Kennedy private ContentValues mExtraValues = null; 284daecb4b9b20a609b27fc803390ecf4f524b76089Paul Westbrook 2851623f9bfde8ced840a52820da28a0939bcaa32f9mindyp // Array of the outstanding send or save tasks. Access is synchronized 2861623f9bfde8ced840a52820da28a0939bcaa32f9mindyp // with the object itself 2871623f9bfde8ced840a52820da28a0939bcaa32f9mindyp /* package for testing */ 2881623f9bfde8ced840a52820da28a0939bcaa32f9mindyp @VisibleForTesting 2891623f9bfde8ced840a52820da28a0939bcaa32f9mindyp public ArrayList<SendOrSaveTask> mActiveTasks = Lists.newArrayList(); 2901623f9bfde8ced840a52820da28a0939bcaa32f9mindyp // FIXME: this variable is never read. related to sRequestMessageIdMap. 2911623f9bfde8ced840a52820da28a0939bcaa32f9mindyp private int mRequestId; 2921623f9bfde8ced840a52820da28a0939bcaa32f9mindyp private String mSignature; 2931623f9bfde8ced840a52820da28a0939bcaa32f9mindyp private Account[] mAccounts; 2941623f9bfde8ced840a52820da28a0939bcaa32f9mindyp private boolean mRespondedInline; 295dc97bf4509c450c9121b79ec4668e0f9b34f0690Andy Huang private boolean mPerformedSendOrDiscard = false; 2961623f9bfde8ced840a52820da28a0939bcaa32f9mindyp 297daecb4b9b20a609b27fc803390ecf4f524b76089Paul Westbrook /** 298326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira * Can be called from a non-UI thread. 299326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira */ 3003ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereira public static void editDraft(Context launcher, Account account, Message message) { 30160847256c691b2677772a46919038f9c600fecf7Scott Kennedy launch(launcher, account, message, EDIT_DRAFT, null, null, null, null, 30260847256c691b2677772a46919038f9c600fecf7Scott Kennedy null /* extraValues */); 303326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } 304326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira 3056349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira /** 3066349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira * Can be called from a non-UI thread. 3076349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira */ 30833fe908589dca6a7f58aa9f56d73f74a48ac42f6Mindy Pereira public static void compose(Context launcher, Account account) { 30960847256c691b2677772a46919038f9c600fecf7Scott Kennedy launch(launcher, account, null, COMPOSE, null, null, null, null, null /* extraValues */); 3106349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira } 3116349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira 3126349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira /** 3136349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira * Can be called from a non-UI thread. 3146349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira */ 3153de76eca03ed7ec1d40f2cce23cbbbe8e5e6d70fAndrew Sapperstein public static void composeToAddress(Context launcher, Account account, String toAddress) { 31660847256c691b2677772a46919038f9c600fecf7Scott Kennedy launch(launcher, account, null, COMPOSE, toAddress, null, null, null, 31760847256c691b2677772a46919038f9c600fecf7Scott Kennedy null /* extraValues */); 318bc5e0dcf723918eb986d733ef42d64bcf2ec4ed5Andrew Sapperstein } 319bc5e0dcf723918eb986d733ef42d64bcf2ec4ed5Andrew Sapperstein 320bc5e0dcf723918eb986d733ef42d64bcf2ec4ed5Andrew Sapperstein /** 321bc5e0dcf723918eb986d733ef42d64bcf2ec4ed5Andrew Sapperstein * Can be called from a non-UI thread. 322bc5e0dcf723918eb986d733ef42d64bcf2ec4ed5Andrew Sapperstein */ 323bc5e0dcf723918eb986d733ef42d64bcf2ec4ed5Andrew Sapperstein public static void composeWithQuotedText(Context launcher, Account account, 32460847256c691b2677772a46919038f9c600fecf7Scott Kennedy String quotedText, String subject, final ContentValues extraValues) { 32560847256c691b2677772a46919038f9c600fecf7Scott Kennedy launch(launcher, account, null, COMPOSE, null, null, quotedText, subject, extraValues); 3263de76eca03ed7ec1d40f2cce23cbbbe8e5e6d70fAndrew Sapperstein } 3273de76eca03ed7ec1d40f2cce23cbbbe8e5e6d70fAndrew Sapperstein 3283de76eca03ed7ec1d40f2cce23cbbbe8e5e6d70fAndrew Sapperstein /** 3293de76eca03ed7ec1d40f2cce23cbbbe8e5e6d70fAndrew Sapperstein * Can be called from a non-UI thread. 3303de76eca03ed7ec1d40f2cce23cbbbe8e5e6d70fAndrew Sapperstein */ 3310aeaf7d8c2ee4bc882ca901531f985c61b4cc7c7Scott Kennedy public static Intent createReplyIntent(final Context launcher, final Account account, 3320aeaf7d8c2ee4bc882ca901531f985c61b4cc7c7Scott Kennedy final Uri messageUri, final boolean isReplyAll) { 3330aeaf7d8c2ee4bc882ca901531f985c61b4cc7c7Scott Kennedy return createActionIntent(launcher, account, messageUri, isReplyAll ? REPLY_ALL : REPLY); 3340aeaf7d8c2ee4bc882ca901531f985c61b4cc7c7Scott Kennedy } 3350aeaf7d8c2ee4bc882ca901531f985c61b4cc7c7Scott Kennedy 3360aeaf7d8c2ee4bc882ca901531f985c61b4cc7c7Scott Kennedy /** 3370aeaf7d8c2ee4bc882ca901531f985c61b4cc7c7Scott Kennedy * Can be called from a non-UI thread. 3380aeaf7d8c2ee4bc882ca901531f985c61b4cc7c7Scott Kennedy */ 3390aeaf7d8c2ee4bc882ca901531f985c61b4cc7c7Scott Kennedy public static Intent createForwardIntent(final Context launcher, final Account account, 3400aeaf7d8c2ee4bc882ca901531f985c61b4cc7c7Scott Kennedy final Uri messageUri) { 3410aeaf7d8c2ee4bc882ca901531f985c61b4cc7c7Scott Kennedy return createActionIntent(launcher, account, messageUri, FORWARD); 3420aeaf7d8c2ee4bc882ca901531f985c61b4cc7c7Scott Kennedy } 3430aeaf7d8c2ee4bc882ca901531f985c61b4cc7c7Scott Kennedy 3440aeaf7d8c2ee4bc882ca901531f985c61b4cc7c7Scott Kennedy private static Intent createActionIntent(final Context launcher, final Account account, 3450aeaf7d8c2ee4bc882ca901531f985c61b4cc7c7Scott Kennedy final Uri messageUri, final int action) { 3460aeaf7d8c2ee4bc882ca901531f985c61b4cc7c7Scott Kennedy final Intent intent = new Intent(launcher, ComposeActivity.class); 3470aeaf7d8c2ee4bc882ca901531f985c61b4cc7c7Scott Kennedy 3486d2442ba4417717b2a19714b0ac28c7265872ba3Paul Westbrook updateActionIntent(account, messageUri, action, intent); 3496d2442ba4417717b2a19714b0ac28c7265872ba3Paul Westbrook 3506d2442ba4417717b2a19714b0ac28c7265872ba3Paul Westbrook return intent; 3516d2442ba4417717b2a19714b0ac28c7265872ba3Paul Westbrook } 3526d2442ba4417717b2a19714b0ac28c7265872ba3Paul Westbrook 3536d2442ba4417717b2a19714b0ac28c7265872ba3Paul Westbrook @VisibleForTesting 3546d2442ba4417717b2a19714b0ac28c7265872ba3Paul Westbrook static Intent updateActionIntent(Account account, Uri messageUri, int action, Intent intent) { 3550aeaf7d8c2ee4bc882ca901531f985c61b4cc7c7Scott Kennedy intent.putExtra(EXTRA_FROM_EMAIL_TASK, true); 3560aeaf7d8c2ee4bc882ca901531f985c61b4cc7c7Scott Kennedy intent.putExtra(EXTRA_ACTION, action); 3570aeaf7d8c2ee4bc882ca901531f985c61b4cc7c7Scott Kennedy intent.putExtra(Utils.EXTRA_ACCOUNT, account); 3580aeaf7d8c2ee4bc882ca901531f985c61b4cc7c7Scott Kennedy intent.putExtra(EXTRA_IN_REFERENCE_TO_MESSAGE_URI, messageUri); 3590aeaf7d8c2ee4bc882ca901531f985c61b4cc7c7Scott Kennedy 3600aeaf7d8c2ee4bc882ca901531f985c61b4cc7c7Scott Kennedy return intent; 3610aeaf7d8c2ee4bc882ca901531f985c61b4cc7c7Scott Kennedy } 3620aeaf7d8c2ee4bc882ca901531f985c61b4cc7c7Scott Kennedy 3630aeaf7d8c2ee4bc882ca901531f985c61b4cc7c7Scott Kennedy /** 3640aeaf7d8c2ee4bc882ca901531f985c61b4cc7c7Scott Kennedy * Can be called from a non-UI thread. 3650aeaf7d8c2ee4bc882ca901531f985c61b4cc7c7Scott Kennedy */ 3663ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereira public static void reply(Context launcher, Account account, Message message) { 36760847256c691b2677772a46919038f9c600fecf7Scott Kennedy launch(launcher, account, message, REPLY, null, null, null, null, null /* extraValues */); 3686349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira } 3696349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira 3706349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira /** 3716349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira * Can be called from a non-UI thread. 3726349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira */ 3733ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereira public static void replyAll(Context launcher, Account account, Message message) { 37460847256c691b2677772a46919038f9c600fecf7Scott Kennedy launch(launcher, account, message, REPLY_ALL, null, null, null, null, 37560847256c691b2677772a46919038f9c600fecf7Scott Kennedy null /* extraValues */); 3766349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira } 3776349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira 3786349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira /** 3796349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira * Can be called from a non-UI thread. 3806349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira */ 3813ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereira public static void forward(Context launcher, Account account, Message message) { 38260847256c691b2677772a46919038f9c600fecf7Scott Kennedy launch(launcher, account, message, FORWARD, null, null, null, null, null /* extraValues */); 3836349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira } 3846349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira 3851ebc2db723ed29093d724eb5da906a496ee57224Alice Yang public static void reportRenderingFeedback(Context launcher, Account account, Message message, 3861ebc2db723ed29093d724eb5da906a496ee57224Alice Yang String body) { 387bc5e0dcf723918eb986d733ef42d64bcf2ec4ed5Andrew Sapperstein launch(launcher, account, message, FORWARD, 38860847256c691b2677772a46919038f9c600fecf7Scott Kennedy "android-gmail-readability@google.com", body, null, null, null /* extraValues */); 3891ebc2db723ed29093d724eb5da906a496ee57224Alice Yang } 3901ebc2db723ed29093d724eb5da906a496ee57224Alice Yang 3911ebc2db723ed29093d724eb5da906a496ee57224Alice Yang private static void launch(Context launcher, Account account, Message message, int action, 39260847256c691b2677772a46919038f9c600fecf7Scott Kennedy String toAddress, String body, String quotedText, String subject, 39360847256c691b2677772a46919038f9c600fecf7Scott Kennedy final ContentValues extraValues) { 3946349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira Intent intent = new Intent(launcher, ComposeActivity.class); 3956349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira intent.putExtra(EXTRA_FROM_EMAIL_TASK, true); 3966349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira intent.putExtra(EXTRA_ACTION, action); 3976349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira intent.putExtra(Utils.EXTRA_ACCOUNT, account); 398bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook if (action == EDIT_DRAFT) { 399bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook intent.putExtra(ORIGINAL_DRAFT_MESSAGE, message); 400bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook } else { 401bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook intent.putExtra(EXTRA_IN_REFERENCE_TO_MESSAGE, message); 402bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook } 4031ebc2db723ed29093d724eb5da906a496ee57224Alice Yang if (toAddress != null) { 4041ebc2db723ed29093d724eb5da906a496ee57224Alice Yang intent.putExtra(EXTRA_TO, toAddress); 4051ebc2db723ed29093d724eb5da906a496ee57224Alice Yang } 4061ebc2db723ed29093d724eb5da906a496ee57224Alice Yang if (body != null) { 4071ebc2db723ed29093d724eb5da906a496ee57224Alice Yang intent.putExtra(EXTRA_BODY, body); 4081ebc2db723ed29093d724eb5da906a496ee57224Alice Yang } 409bc5e0dcf723918eb986d733ef42d64bcf2ec4ed5Andrew Sapperstein if (quotedText != null) { 410bc5e0dcf723918eb986d733ef42d64bcf2ec4ed5Andrew Sapperstein intent.putExtra(EXTRA_QUOTED_TEXT, quotedText); 411bc5e0dcf723918eb986d733ef42d64bcf2ec4ed5Andrew Sapperstein } 412bc5e0dcf723918eb986d733ef42d64bcf2ec4ed5Andrew Sapperstein if (subject != null) { 413bc5e0dcf723918eb986d733ef42d64bcf2ec4ed5Andrew Sapperstein intent.putExtra(EXTRA_SUBJECT, subject); 414bc5e0dcf723918eb986d733ef42d64bcf2ec4ed5Andrew Sapperstein } 41560847256c691b2677772a46919038f9c600fecf7Scott Kennedy if (extraValues != null) { 41660847256c691b2677772a46919038f9c600fecf7Scott Kennedy LogUtils.d(LOG_TAG, "Launching with extraValues: %s", extraValues.toString()); 41760847256c691b2677772a46919038f9c600fecf7Scott Kennedy intent.putExtra(EXTRA_VALUES, extraValues); 41860847256c691b2677772a46919038f9c600fecf7Scott Kennedy } 4196349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira launcher.startActivity(intent); 4206349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira } 4218e9305ec0bbe23cec01eb34a2aee76c55199a10aMindy Pereira 4228e9305ec0bbe23cec01eb34a2aee76c55199a10aMindy Pereira @Override 423d90639004a3551d7fb7086f318d4c576d54d2b86Scott Kennedy protected void onCreate(Bundle savedInstanceState) { 4248e9305ec0bbe23cec01eb34a2aee76c55199a10aMindy Pereira super.onCreate(savedInstanceState); 4258e9305ec0bbe23cec01eb34a2aee76c55199a10aMindy Pereira setContentView(R.layout.compose); 4269f855d667e34fbf0d330845225c26956e540b819Andy Huang mInnerSavedState = (savedInstanceState != null) ? 4279f855d667e34fbf0d330845225c26956e540b819Andy Huang savedInstanceState.getBundle(KEY_INNER_SAVED_STATE) : null; 428b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira checkValidAccounts(); 429b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira } 430b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira 431b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira private void finishCreate() { 4329f855d667e34fbf0d330845225c26956e540b819Andy Huang final Bundle savedState = mInnerSavedState; 43346ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira findViews(); 434818143e2163648acc0c91f123b84777d65cd70cfMindy Pereira Intent intent = getIntent(); 435e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira Message message; 43662066e47fe69c33b60ed970e46809ba81d044064Mark Wei ArrayList<AttachmentPreview> previews; 437a990a715012379451344246c5156d29938f12886Alice Yang mShowQuotedText = false; 438bc5e0dcf723918eb986d733ef42d64bcf2ec4ed5Andrew Sapperstein CharSequence quotedText = null; 439e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira int action; 44047d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereira // Check for any of the possibly supplied accounts.; 44147d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereira Account account = null; 4429f855d667e34fbf0d330845225c26956e540b819Andy Huang if (hadSavedInstanceStateMessage(savedState)) { 4439f855d667e34fbf0d330845225c26956e540b819Andy Huang action = savedState.getInt(EXTRA_ACTION, COMPOSE); 4449f855d667e34fbf0d330845225c26956e540b819Andy Huang account = savedState.getParcelable(Utils.EXTRA_ACCOUNT); 4459f855d667e34fbf0d330845225c26956e540b819Andy Huang message = (Message) savedState.getParcelable(EXTRA_MESSAGE); 44662066e47fe69c33b60ed970e46809ba81d044064Mark Wei 4479f855d667e34fbf0d330845225c26956e540b819Andy Huang previews = savedState.getParcelableArrayList(EXTRA_ATTACHMENT_PREVIEWS); 4489f855d667e34fbf0d330845225c26956e540b819Andy Huang mRefMessage = (Message) savedState.getParcelable(EXTRA_IN_REFERENCE_TO_MESSAGE); 449bc5e0dcf723918eb986d733ef42d64bcf2ec4ed5Andrew Sapperstein quotedText = savedState.getCharSequence(EXTRA_QUOTED_TEXT); 450e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira } else { 45147d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereira account = obtainAccount(intent); 452e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira action = intent.getIntExtra(EXTRA_ACTION, COMPOSE); 453e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira // Initialize the message from the message in the intent 454e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira message = (Message) intent.getParcelableExtra(ORIGINAL_DRAFT_MESSAGE); 45562066e47fe69c33b60ed970e46809ba81d044064Mark Wei previews = intent.getParcelableArrayListExtra(EXTRA_ATTACHMENT_PREVIEWS); 456e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira mRefMessage = (Message) intent.getParcelableExtra(EXTRA_IN_REFERENCE_TO_MESSAGE); 457b18e5a9341c73541d7201830c513cb0ed247e935Mindy Pereira mRefMessageUri = (Uri) intent.getParcelableExtra(EXTRA_IN_REFERENCE_TO_MESSAGE_URI); 458e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira } 45962066e47fe69c33b60ed970e46809ba81d044064Mark Wei mAttachmentsView.setAttachmentPreviews(previews); 46092227f6b35b3bec54609dc0feb9dd6756c2a43e6Paul Westbrook 46192227f6b35b3bec54609dc0feb9dd6756c2a43e6Paul Westbrook setAccount(account); 462818143e2163648acc0c91f123b84777d65cd70cfMindy Pereira if (mAccount == null) { 463818143e2163648acc0c91f123b84777d65cd70cfMindy Pereira return; 464818143e2163648acc0c91f123b84777d65cd70cfMindy Pereira } 465bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook 466fe853d3427119202562519c2add6873590851705Scott Kennedy initRecipients(); 467fe853d3427119202562519c2add6873590851705Scott Kennedy 4685680ec22f92125cbd95ff0f8d18d5cc04c6f0b81Scott Kennedy // Clear the notification and mark the conversation as seen, if necessary 4695680ec22f92125cbd95ff0f8d18d5cc04c6f0b81Scott Kennedy final Folder notificationFolder = 4705680ec22f92125cbd95ff0f8d18d5cc04c6f0b81Scott Kennedy intent.getParcelableExtra(EXTRA_NOTIFICATION_FOLDER); 4715680ec22f92125cbd95ff0f8d18d5cc04c6f0b81Scott Kennedy if (notificationFolder != null) { 4725680ec22f92125cbd95ff0f8d18d5cc04c6f0b81Scott Kennedy final Intent clearNotifIntent = 4735680ec22f92125cbd95ff0f8d18d5cc04c6f0b81Scott Kennedy new Intent(MailIntentService.ACTION_CLEAR_NEW_MAIL_NOTIFICATIONS); 474d5edd2d02649dffb40065fdb6a16acf91552b800Scott Kennedy clearNotifIntent.setPackage(getPackageName()); 47548cfe4613549cafdf36e2a524afba730522bf291Scott Kennedy clearNotifIntent.putExtra(Utils.EXTRA_ACCOUNT, account); 47648cfe4613549cafdf36e2a524afba730522bf291Scott Kennedy clearNotifIntent.putExtra(Utils.EXTRA_FOLDER, notificationFolder); 4775680ec22f92125cbd95ff0f8d18d5cc04c6f0b81Scott Kennedy 4785680ec22f92125cbd95ff0f8d18d5cc04c6f0b81Scott Kennedy startService(clearNotifIntent); 4795680ec22f92125cbd95ff0f8d18d5cc04c6f0b81Scott Kennedy } 4805680ec22f92125cbd95ff0f8d18d5cc04c6f0b81Scott Kennedy 481daecb4b9b20a609b27fc803390ecf4f524b76089Paul Westbrook if (intent.getBooleanExtra(EXTRA_FROM_EMAIL_TASK, false)) { 482daecb4b9b20a609b27fc803390ecf4f524b76089Paul Westbrook mLaunchedFromEmail = true; 483daecb4b9b20a609b27fc803390ecf4f524b76089Paul Westbrook } else if (Intent.ACTION_SEND.equals(intent.getAction())) { 484daecb4b9b20a609b27fc803390ecf4f524b76089Paul Westbrook final Uri dataUri = intent.getData(); 485daecb4b9b20a609b27fc803390ecf4f524b76089Paul Westbrook if (dataUri != null) { 486daecb4b9b20a609b27fc803390ecf4f524b76089Paul Westbrook final String dataScheme = intent.getData().getScheme(); 487daecb4b9b20a609b27fc803390ecf4f524b76089Paul Westbrook final String accountScheme = mAccount.composeIntentUri.getScheme(); 488daecb4b9b20a609b27fc803390ecf4f524b76089Paul Westbrook mLaunchedFromEmail = TextUtils.equals(dataScheme, accountScheme); 489daecb4b9b20a609b27fc803390ecf4f524b76089Paul Westbrook } 490daecb4b9b20a609b27fc803390ecf4f524b76089Paul Westbrook } 491daecb4b9b20a609b27fc803390ecf4f524b76089Paul Westbrook 49296a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira if (mRefMessageUri != null) { 493a990a715012379451344246c5156d29938f12886Alice Yang mShowQuotedText = true; 494a990a715012379451344246c5156d29938f12886Alice Yang mComposeMode = action; 495a990a715012379451344246c5156d29938f12886Alice Yang getLoaderManager().initLoader(INIT_DRAFT_USING_REFERENCE_MESSAGE, null, this); 49696a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira return; 49796a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira } else if (message != null && action != EDIT_DRAFT) { 498e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira initFromDraftMessage(message); 499e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira initQuotedTextFromRefMessage(mRefMessage, action); 5009f855d667e34fbf0d330845225c26956e540b819Andy Huang showCcBcc(savedState); 501a990a715012379451344246c5156d29938f12886Alice Yang mShowQuotedText = message.appendRefMessageContent; 502bc5e0dcf723918eb986d733ef42d64bcf2ec4ed5Andrew Sapperstein // if we should be showing quoted text but mRefMessage is null 503bc5e0dcf723918eb986d733ef42d64bcf2ec4ed5Andrew Sapperstein // and we have some quotedText, display that 504bc5e0dcf723918eb986d733ef42d64bcf2ec4ed5Andrew Sapperstein if (mShowQuotedText && quotedText != null && mRefMessage == null) { 505bc5e0dcf723918eb986d733ef42d64bcf2ec4ed5Andrew Sapperstein initQuotedText(quotedText, false /* shouldQuoteText */); 506bc5e0dcf723918eb986d733ef42d64bcf2ec4ed5Andrew Sapperstein } 507e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira } else if (action == EDIT_DRAFT) { 508e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira initFromDraftMessage(message); 5098960f0af431bc164003e09b3c8981aab808d9ec1Scott Kennedy boolean showBcc = !TextUtils.isEmpty(message.getBcc()); 5108960f0af431bc164003e09b3c8981aab808d9ec1Scott Kennedy boolean showCc = showBcc || !TextUtils.isEmpty(message.getCc()); 511ef38830943dac17adb4cade670b5ae0c6b4442c6Mindy Pereira mCcBccView.show(false, showCc, showBcc); 512bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook // Update the action to the draft type of the previous draft 513bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook switch (message.draftType) { 514bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook case UIProvider.DraftType.REPLY: 515bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook action = REPLY; 516bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook break; 517bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook case UIProvider.DraftType.REPLY_ALL: 518bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook action = REPLY_ALL; 519bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook break; 520bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook case UIProvider.DraftType.FORWARD: 521bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook action = FORWARD; 522bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook break; 523bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook case UIProvider.DraftType.COMPOSE: 524bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook default: 525bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook action = COMPOSE; 526bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook break; 527bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook } 528a990a715012379451344246c5156d29938f12886Alice Yang LogUtils.d(LOG_TAG, "Previous draft had action type: %d", action); 529a990a715012379451344246c5156d29938f12886Alice Yang 530a990a715012379451344246c5156d29938f12886Alice Yang mShowQuotedText = message.appendRefMessageContent; 531a990a715012379451344246c5156d29938f12886Alice Yang if (message.refMessageUri != null) { 532a990a715012379451344246c5156d29938f12886Alice Yang // If we're editing an existing draft that was in reference to an existing message, 533a990a715012379451344246c5156d29938f12886Alice Yang // still need to load that original message since we might need to refer to the 534a990a715012379451344246c5156d29938f12886Alice Yang // original sender and recipients if user switches "reply <-> reply-all". 535a990a715012379451344246c5156d29938f12886Alice Yang mRefMessageUri = message.refMessageUri; 536a990a715012379451344246c5156d29938f12886Alice Yang mComposeMode = action; 537a990a715012379451344246c5156d29938f12886Alice Yang getLoaderManager().initLoader(REFERENCE_MESSAGE_LOADER, null, this); 538a990a715012379451344246c5156d29938f12886Alice Yang return; 539a990a715012379451344246c5156d29938f12886Alice Yang } 540e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira } else if ((action == REPLY || action == REPLY_ALL || action == FORWARD)) { 541e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira if (mRefMessage != null) { 5420aeaf7d8c2ee4bc882ca901531f985c61b4cc7c7Scott Kennedy initFromRefMessage(action); 543a990a715012379451344246c5156d29938f12886Alice Yang mShowQuotedText = true; 544e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira } 5458eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira } else { 5468eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira initFromExtras(intent); 547bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook } 548a990a715012379451344246c5156d29938f12886Alice Yang 549a990a715012379451344246c5156d29938f12886Alice Yang mComposeMode = action; 5509f855d667e34fbf0d330845225c26956e540b819Andy Huang finishSetup(action, intent, savedState); 55196a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira } 552bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook 553b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira private void checkValidAccounts() { 554faa742fcff868e17fb7e78c4c3f3ffdb01386f57Paul Westbrook final Account[] allAccounts = AccountUtils.getAccounts(this); 555faa742fcff868e17fb7e78c4c3f3ffdb01386f57Paul Westbrook if (allAccounts == null || allAccounts.length == 0) { 556b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira final Intent noAccountIntent = MailAppProvider.getNoAccountIntent(this); 557b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira if (noAccountIntent != null) { 558faa742fcff868e17fb7e78c4c3f3ffdb01386f57Paul Westbrook mAccounts = null; 559b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira startActivityForResult(noAccountIntent, RESULT_CREATE_ACCOUNT); 560b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira } 561b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira } else { 56226d4d2d9c43c499f458808f050ec73ea3c28dec4mindyp // If none of the accounts are syncing, setup a watcher. 563b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira boolean anySyncing = false; 564faa742fcff868e17fb7e78c4c3f3ffdb01386f57Paul Westbrook for (Account a : allAccounts) { 565dfa1dec0cfdc263c51e971dc3c41b90386a24340Paul Westbrook if (a.isAccountReady()) { 566b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira anySyncing = true; 567b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira break; 568b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira } 569b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira } 570b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira if (!anySyncing) { 571b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira // There are accounts, but none are sync'd, which is just like having no accounts. 572b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira mAccounts = null; 573b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira getLoaderManager().initLoader(LOADER_ACCOUNT_CURSOR, null, this); 574b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira return; 575b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira } 576faa742fcff868e17fb7e78c4c3f3ffdb01386f57Paul Westbrook mAccounts = AccountUtils.getSyncingAccounts(this); 577b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira finishCreate(); 578b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira } 579b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira } 580b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira 58147d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereira private Account obtainAccount(Intent intent) { 58247d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereira Account account = null; 58347d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereira Object accountExtra = null; 58447d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereira if (intent != null && intent.getExtras() != null) { 58547d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereira accountExtra = intent.getExtras().get(Utils.EXTRA_ACCOUNT); 58647d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereira if (accountExtra instanceof Account) { 58747d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereira return (Account) accountExtra; 5887ae042ef2a23bf4c87f3edfcd71f7ebc784174abmindyp } else if (accountExtra instanceof String) { 5897ae042ef2a23bf4c87f3edfcd71f7ebc784174abmindyp // This is the Account attached to the widget compose intent. 5907ae042ef2a23bf4c87f3edfcd71f7ebc784174abmindyp account = Account.newinstance((String)accountExtra); 5917ae042ef2a23bf4c87f3edfcd71f7ebc784174abmindyp if (account != null) { 5927ae042ef2a23bf4c87f3edfcd71f7ebc784174abmindyp return account; 5937ae042ef2a23bf4c87f3edfcd71f7ebc784174abmindyp } 59447d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereira } 5955ee9dc48884714e9005a1409e7002a0e04bad313mindyp accountExtra = intent.hasExtra(Utils.EXTRA_ACCOUNT) ? 5965ee9dc48884714e9005a1409e7002a0e04bad313mindyp intent.getStringExtra(Utils.EXTRA_ACCOUNT) : 5975ee9dc48884714e9005a1409e7002a0e04bad313mindyp intent.getStringExtra(EXTRA_SELECTED_ACCOUNT); 59847d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereira } 59947d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereira if (account == null) { 6000617446db14891bffaa2748e1fc98526aac1e06dmindyp MailAppProvider provider = MailAppProvider.getInstance(); 6010617446db14891bffaa2748e1fc98526aac1e06dmindyp String lastAccountUri = provider.getLastSentFromAccount(); 6020617446db14891bffaa2748e1fc98526aac1e06dmindyp if (TextUtils.isEmpty(lastAccountUri)) { 6030617446db14891bffaa2748e1fc98526aac1e06dmindyp lastAccountUri = provider.getLastViewedAccount(); 6040617446db14891bffaa2748e1fc98526aac1e06dmindyp } 60547d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereira if (!TextUtils.isEmpty(lastAccountUri)) { 60647d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereira accountExtra = Uri.parse(lastAccountUri); 60747d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereira } 60847d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereira } 609b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira if (mAccounts != null && mAccounts.length > 0) { 61047d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereira if (accountExtra instanceof String && !TextUtils.isEmpty((String) accountExtra)) { 61147d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereira // For backwards compatibility, we need to check account 61247d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereira // names. 613b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira for (Account a : mAccounts) { 61447d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereira if (a.name.equals(accountExtra)) { 61547d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereira account = a; 61647d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereira } 61747d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereira } 61847d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereira } else if (accountExtra instanceof Uri) { 61947d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereira // The uri of the last viewed account is what is stored in 62047d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereira // the current code base. 621b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira for (Account a : mAccounts) { 62247d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereira if (a.uri.equals(accountExtra)) { 62347d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereira account = a; 62447d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereira } 62547d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereira } 626b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira } 627b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira if (account == null) { 628b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira account = mAccounts[0]; 62947d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereira } 63047d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereira } 63147d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereira return account; 63247d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereira } 63347d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereira 634a990a715012379451344246c5156d29938f12886Alice Yang private void finishSetup(int action, Intent intent, Bundle savedInstanceState) { 63534a3c56570eac4760405b3d5bff5fdc706a22facmindyp setFocus(action); 636f7fc6c339da7f73755041cceb9b8f8447680728aMindy Pereira // Don't bother with the intent if we have procured a message from the 637f7fc6c339da7f73755041cceb9b8f8447680728aMindy Pereira // intent already. 638f7fc6c339da7f73755041cceb9b8f8447680728aMindy Pereira if (!hadSavedInstanceStateMessage(savedInstanceState)) { 639f7fc6c339da7f73755041cceb9b8f8447680728aMindy Pereira initAttachmentsFromIntent(intent); 640f7fc6c339da7f73755041cceb9b8f8447680728aMindy Pereira } 641a990a715012379451344246c5156d29938f12886Alice Yang initActionBar(); 642e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira initFromSpinner(savedInstanceState != null ? savedInstanceState : intent.getExtras(), 643e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira action); 644d4a4866c99ae0ed8c943b6c9ced1e7fbc987c639mindyp 645d4a4866c99ae0ed8c943b6c9ced1e7fbc987c639mindyp // If this is a draft message, the draft account is whatever account was 646d4a4866c99ae0ed8c943b6c9ced1e7fbc987c639mindyp // used to open the draft message in Compose. 647d4a4866c99ae0ed8c943b6c9ced1e7fbc987c639mindyp if (mDraft != null) { 648d4a4866c99ae0ed8c943b6c9ced1e7fbc987c639mindyp mDraftAccount = mReplyFromAccount; 649d4a4866c99ae0ed8c943b6c9ced1e7fbc987c639mindyp } 650d4a4866c99ae0ed8c943b6c9ced1e7fbc987c639mindyp 65175f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira initChangeListeners(); 652326689d531da1d2579fa7daaf6e307e24a05f993Mindy Pereira updateHideOrShowCcBcc(); 653a990a715012379451344246c5156d29938f12886Alice Yang updateHideOrShowQuotedText(mShowQuotedText); 6541623f9bfde8ced840a52820da28a0939bcaa32f9mindyp 6559f855d667e34fbf0d330845225c26956e540b819Andy Huang mRespondedInline = mInnerSavedState != null ? 6569f855d667e34fbf0d330845225c26956e540b819Andy Huang mInnerSavedState.getBoolean(EXTRA_RESPONDED_INLINE) : false; 6571623f9bfde8ced840a52820da28a0939bcaa32f9mindyp if (mRespondedInline) { 6581623f9bfde8ced840a52820da28a0939bcaa32f9mindyp mQuotedTextView.setVisibility(View.GONE); 6591623f9bfde8ced840a52820da28a0939bcaa32f9mindyp } 66071c9e569c06ee362840c14093cf1973ecf297059Mindy Pereira } 66171c9e569c06ee362840c14093cf1973ecf297059Mindy Pereira 662ff8553f20964f4c31b0c503a9e1daff6ae08a9c7Scott Kennedy private static boolean hadSavedInstanceStateMessage(final Bundle savedInstanceState) { 663f7fc6c339da7f73755041cceb9b8f8447680728aMindy Pereira return savedInstanceState != null && savedInstanceState.containsKey(EXTRA_MESSAGE); 664f7fc6c339da7f73755041cceb9b8f8447680728aMindy Pereira } 665f7fc6c339da7f73755041cceb9b8f8447680728aMindy Pereira 66671c9e569c06ee362840c14093cf1973ecf297059Mindy Pereira private void updateHideOrShowQuotedText(boolean showQuotedText) { 66771c9e569c06ee362840c14093cf1973ecf297059Mindy Pereira mQuotedTextView.updateCheckedState(showQuotedText); 66840882430c874ff29890ec6fa31f7649788cbc470mindyp mQuotedTextView.setUpperDividerVisible(mAttachmentsView.getAttachments().size() > 0); 669433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira } 670433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira 671433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira private void setFocus(int action) { 672433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira if (action == EDIT_DRAFT) { 673433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira int type = mDraft.draftType; 674433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira switch (type) { 675433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira case UIProvider.DraftType.COMPOSE: 676433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira case UIProvider.DraftType.FORWARD: 677433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira action = COMPOSE; 678433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira break; 679433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira case UIProvider.DraftType.REPLY: 680433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira case UIProvider.DraftType.REPLY_ALL: 681433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira default: 682433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira action = REPLY; 683433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira break; 684433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira } 685433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira } 686433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira switch (action) { 687433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira case FORWARD: 688433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira case COMPOSE: 6892708306e0b6f8dde22b2571d0dbcc28a53c9f29bmindyp if (TextUtils.isEmpty(mTo.getText())) { 6902708306e0b6f8dde22b2571d0dbcc28a53c9f29bmindyp mTo.requestFocus(); 6912708306e0b6f8dde22b2571d0dbcc28a53c9f29bmindyp break; 6922708306e0b6f8dde22b2571d0dbcc28a53c9f29bmindyp } 693ff8553f20964f4c31b0c503a9e1daff6ae08a9c7Scott Kennedy //$FALL-THROUGH$ 694433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira case REPLY: 695433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira case REPLY_ALL: 696433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira default: 697433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira focusBody(); 698433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira break; 699433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira } 700433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira } 701433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira 702433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira /** 703433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira * Focus the body of the message. 704433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira */ 705433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira public void focusBody() { 706433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira mBodyView.requestFocus(); 707433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira int length = mBodyView.getText().length(); 708433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira 709433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira int signatureStartPos = getSignatureStartPosition( 710433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira mSignature, mBodyView.getText().toString()); 711433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira if (signatureStartPos > -1) { 712433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira // In case the user deleted the newlines... 713433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira mBodyView.setSelection(signatureStartPos); 7148743cfca851058d50385951b111dd903b1fa6c5amindyp } else if (length >= 0) { 715433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira // Move cursor to the end. 716433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira mBodyView.setSelection(length); 717433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira } 7181a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira } 7191a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira 7201a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira @Override 721761522c1ac7a8fa05acde714f0e26fde47f3415fAndy Huang protected void onStart() { 722761522c1ac7a8fa05acde714f0e26fde47f3415fAndy Huang super.onStart(); 723761522c1ac7a8fa05acde714f0e26fde47f3415fAndy Huang 724761522c1ac7a8fa05acde714f0e26fde47f3415fAndy Huang Analytics.getInstance().activityStart(this); 725761522c1ac7a8fa05acde714f0e26fde47f3415fAndy Huang } 726761522c1ac7a8fa05acde714f0e26fde47f3415fAndy Huang 727761522c1ac7a8fa05acde714f0e26fde47f3415fAndy Huang @Override 728761522c1ac7a8fa05acde714f0e26fde47f3415fAndy Huang protected void onStop() { 729761522c1ac7a8fa05acde714f0e26fde47f3415fAndy Huang super.onStop(); 730761522c1ac7a8fa05acde714f0e26fde47f3415fAndy Huang 731761522c1ac7a8fa05acde714f0e26fde47f3415fAndy Huang Analytics.getInstance().activityStop(this); 732761522c1ac7a8fa05acde714f0e26fde47f3415fAndy Huang } 733761522c1ac7a8fa05acde714f0e26fde47f3415fAndy Huang 734761522c1ac7a8fa05acde714f0e26fde47f3415fAndy Huang @Override 7351a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira protected void onResume() { 7361a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira super.onResume(); 7371a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira // Update the from spinner as other accounts 7381a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira // may now be available. 739818143e2163648acc0c91f123b84777d65cd70cfMindy Pereira if (mFromSpinner != null && mAccount != null) { 740c97ec3e157f1b2a30ebdc96ba9c6007f2f719aa6Paul Westbrook mFromSpinner.initialize(mComposeMode, mAccount, mAccounts, mRefMessage); 741818143e2163648acc0c91f123b84777d65cd70cfMindy Pereira } 7421a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira } 7431a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira 744eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira @Override 745eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira protected void onPause() { 746eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira super.onPause(); 747eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira 748a214833a75ba2b27cdd166ceee9a2529b13a17c4Mindy Pereira // When the user exits the compose view, see if this draft needs saving. 7493d7048ea243df4c1ae163bd72971e83e1218e7f0Yorke Lee // Don't save unnecessary drafts if we are only changing the orientation. 7503d7048ea243df4c1ae163bd72971e83e1218e7f0Yorke Lee if (!isChangingConfigurations()) { 751a214833a75ba2b27cdd166ceee9a2529b13a17c4Mindy Pereira saveIfNeeded(); 752dc97bf4509c450c9121b79ec4668e0f9b34f0690Andy Huang 753dc97bf4509c450c9121b79ec4668e0f9b34f0690Andy Huang if (isFinishing() && !mPerformedSendOrDiscard) { 754dc97bf4509c450c9121b79ec4668e0f9b34f0690Andy Huang // log saving upon backing out of activity. (we avoid logging every sendOrSave() 755dc97bf4509c450c9121b79ec4668e0f9b34f0690Andy Huang // because that method can be invoked many times in a single compose session.) 756dc97bf4509c450c9121b79ec4668e0f9b34f0690Andy Huang logSendOrSave(true /* save */); 757dc97bf4509c450c9121b79ec4668e0f9b34f0690Andy Huang } 758a214833a75ba2b27cdd166ceee9a2529b13a17c4Mindy Pereira } 759eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira } 760eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira 761eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira @Override 762eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira protected final void onActivityResult(int request, int result, Intent data) { 763b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira if (request == RESULT_PICK_ATTACHMENT && result == RESULT_OK) { 764eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira addAttachmentAndUpdateView(data); 765b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira mAddingAttachment = false; 766b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira } else if (request == RESULT_CREATE_ACCOUNT) { 767a990a715012379451344246c5156d29938f12886Alice Yang // We were waiting for the user to create an account 768b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira if (result != RESULT_OK) { 769b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira finish(); 770b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira } else { 771b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira // Watch for accounts to show up! 772b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira // restart the loader to get the updated list of accounts 773b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira getLoaderManager().initLoader(LOADER_ACCOUNT_CURSOR, null, this); 774b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira showWaitFragment(null); 775b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira } 776eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira } 777eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira } 778eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira 779eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira @Override 780d90639004a3551d7fb7086f318d4c576d54d2b86Scott Kennedy protected final void onRestoreInstanceState(Bundle savedInstanceState) { 7817bec2b909cb5bba3bf9aae7e977fb1c8931f7230Yorke Lee final boolean hasAccounts = mAccounts != null && mAccounts.length > 0; 7827bec2b909cb5bba3bf9aae7e977fb1c8931f7230Yorke Lee if (hasAccounts) { 7837bec2b909cb5bba3bf9aae7e977fb1c8931f7230Yorke Lee clearChangeListeners(); 7847bec2b909cb5bba3bf9aae7e977fb1c8931f7230Yorke Lee } 785e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira super.onRestoreInstanceState(savedInstanceState); 7869f855d667e34fbf0d330845225c26956e540b819Andy Huang if (mInnerSavedState != null) { 7879f855d667e34fbf0d330845225c26956e540b819Andy Huang if (mInnerSavedState.containsKey(EXTRA_FOCUS_SELECTION_START)) { 7889f855d667e34fbf0d330845225c26956e540b819Andy Huang int selectionStart = mInnerSavedState.getInt(EXTRA_FOCUS_SELECTION_START); 7899f855d667e34fbf0d330845225c26956e540b819Andy Huang int selectionEnd = mInnerSavedState.getInt(EXTRA_FOCUS_SELECTION_END); 790e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira // There should be a focus and it should be an EditText since we 791e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira // only save these extras if these conditions are true. 792e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira EditText focusEditText = (EditText) getCurrentFocus(); 793e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira final int length = focusEditText.getText().length(); 794e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira if (selectionStart < length && selectionEnd < length) { 795e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira focusEditText.setSelection(selectionStart, selectionEnd); 796e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira } 797e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira } 798e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira } 7997bec2b909cb5bba3bf9aae7e977fb1c8931f7230Yorke Lee if (hasAccounts) { 8007bec2b909cb5bba3bf9aae7e977fb1c8931f7230Yorke Lee initChangeListeners(); 8017bec2b909cb5bba3bf9aae7e977fb1c8931f7230Yorke Lee } 802e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira } 803e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira 804e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira @Override 805d90639004a3551d7fb7086f318d4c576d54d2b86Scott Kennedy protected final void onSaveInstanceState(Bundle state) { 806eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira super.onSaveInstanceState(state); 8079f855d667e34fbf0d330845225c26956e540b819Andy Huang final Bundle inner = new Bundle(); 8089f855d667e34fbf0d330845225c26956e540b819Andy Huang saveState(inner); 8099f855d667e34fbf0d330845225c26956e540b819Andy Huang state.putBundle(KEY_INNER_SAVED_STATE, inner); 8109f855d667e34fbf0d330845225c26956e540b819Andy Huang } 8119f855d667e34fbf0d330845225c26956e540b819Andy Huang 8129f855d667e34fbf0d330845225c26956e540b819Andy Huang private void saveState(Bundle state) { 813b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira // We have no accounts so there is nothing to compose, and therefore, nothing to save. 814b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira if (mAccounts == null || mAccounts.length == 0) { 815b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira return; 816b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira } 817e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira // The framework is happy to save and restore the selection but only if it also saves and 818e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira // restores the contents of the edit text. That's a lot of text to put in a bundle so we do 819e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira // this manually. 820e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira View focus = getCurrentFocus(); 821e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira if (focus != null && focus instanceof EditText) { 822e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira EditText focusEditText = (EditText) focus; 823e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira state.putInt(EXTRA_FOCUS_SELECTION_START, focusEditText.getSelectionStart()); 824e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira state.putInt(EXTRA_FOCUS_SELECTION_END, focusEditText.getSelectionEnd()); 825e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira } 8266273e96b7204a33ea44823fb36fd7fc8baf5ba20Paul Westbrook 8276273e96b7204a33ea44823fb36fd7fc8baf5ba20Paul Westbrook final List<ReplyFromAccount> replyFromAccounts = mFromSpinner.getReplyFromAccounts(); 828151f1ad1613ecac0207144472872440517172b5aPaul Westbrook final int selectedPos = mFromSpinner.getSelectedItemPosition(); 829d90f7ac9b1a62e8beefdac3ceda9e4cb75ef000cMindy Pereira final ReplyFromAccount selectedReplyFromAccount = (replyFromAccounts != null 830d90f7ac9b1a62e8beefdac3ceda9e4cb75ef000cMindy Pereira && replyFromAccounts.size() > 0 && replyFromAccounts.size() > selectedPos) ? 831d90f7ac9b1a62e8beefdac3ceda9e4cb75ef000cMindy Pereira replyFromAccounts.get(selectedPos) : null; 832e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira if (selectedReplyFromAccount != null) { 833e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira state.putString(EXTRA_SELECTED_REPLY_FROM_ACCOUNT, selectedReplyFromAccount.serialize() 834e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira .toString()); 835e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira state.putParcelable(Utils.EXTRA_ACCOUNT, selectedReplyFromAccount.account); 836e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira } else { 837e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira state.putParcelable(Utils.EXTRA_ACCOUNT, mAccount); 838e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira } 839eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira 840e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira if (mDraftId == UIProvider.INVALID_MESSAGE_ID && mRequestId !=0) { 841e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira // We don't have a draft id, and we have a request id, 842e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira // save the request id. 843e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira state.putInt(EXTRA_REQUEST_ID, mRequestId); 844e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira } 845e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira 846e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira // We want to restore the current mode after a pause 847e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira // or rotation. 848e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira int mode = getMode(); 849e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira state.putInt(EXTRA_ACTION, mode); 850e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira 851e7b76aac2ad5b12d6b04838ca72011ceaedc8910mindyp final Message message = createMessage(selectedReplyFromAccount, mode); 8521f8f4dd8c53e6c18ae642235335ce492c9d1e520Andy Huang if (mDraft != null) { 853e7b76aac2ad5b12d6b04838ca72011ceaedc8910mindyp message.id = mDraft.id; 854e7b76aac2ad5b12d6b04838ca72011ceaedc8910mindyp message.serverId = mDraft.serverId; 855e7b76aac2ad5b12d6b04838ca72011ceaedc8910mindyp message.uri = mDraft.uri; 8561f8f4dd8c53e6c18ae642235335ce492c9d1e520Andy Huang } 857e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira state.putParcelable(EXTRA_MESSAGE, message); 858e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira 859e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira if (mRefMessage != null) { 860e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira state.putParcelable(EXTRA_IN_REFERENCE_TO_MESSAGE, mRefMessage); 861bc5e0dcf723918eb986d733ef42d64bcf2ec4ed5Andrew Sapperstein } else if (message.appendRefMessageContent) { 862bc5e0dcf723918eb986d733ef42d64bcf2ec4ed5Andrew Sapperstein // If we have no ref message but should be appending 863bc5e0dcf723918eb986d733ef42d64bcf2ec4ed5Andrew Sapperstein // ref message content, we have orphaned quoted text. Save it. 864bc5e0dcf723918eb986d733ef42d64bcf2ec4ed5Andrew Sapperstein state.putCharSequence(EXTRA_QUOTED_TEXT, mQuotedTextView.getQuotedTextIfIncluded()); 865e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira } 866326689d531da1d2579fa7daaf6e307e24a05f993Mindy Pereira state.putBoolean(EXTRA_SHOW_CC, mCcBccView.isCcVisible()); 867326689d531da1d2579fa7daaf6e307e24a05f993Mindy Pereira state.putBoolean(EXTRA_SHOW_BCC, mCcBccView.isBccVisible()); 8681623f9bfde8ced840a52820da28a0939bcaa32f9mindyp state.putBoolean(EXTRA_RESPONDED_INLINE, mRespondedInline); 869816b3f0adc04db073820f04ce379e5126e1cbef1mindyp state.putBoolean(EXTRA_SAVE_ENABLED, mSave != null && mSave.isEnabled()); 87062066e47fe69c33b60ed970e46809ba81d044064Mark Wei state.putParcelableArrayList( 87162066e47fe69c33b60ed970e46809ba81d044064Mark Wei EXTRA_ATTACHMENT_PREVIEWS, mAttachmentsView.getAttachmentPreviews()); 872e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira } 873e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira 874e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira private int getMode() { 875e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira int mode = ComposeActivity.COMPOSE; 876e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira ActionBar actionBar = getActionBar(); 877e011b1d1c8e2e674dfdf1985d9d13da8cc06d803Mindy Pereira if (actionBar != null 878e011b1d1c8e2e674dfdf1985d9d13da8cc06d803Mindy Pereira && actionBar.getNavigationMode() == ActionBar.NAVIGATION_MODE_LIST) { 879e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira mode = actionBar.getSelectedNavigationIndex(); 880e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira } 881e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira return mode; 882e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira } 883e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira 884e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira private Message createMessage(ReplyFromAccount selectedReplyFromAccount, int mode) { 885e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira Message message = new Message(); 886e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira message.id = UIProvider.INVALID_MESSAGE_ID; 887d47877e3860ea4249eddb3f6efefbc6cd39f2320Andy Huang message.serverId = null; 888e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira message.uri = null; 889e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira message.conversationUri = null; 890e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira message.subject = mSubject.getText().toString(); 891e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira message.snippet = null; 8928960f0af431bc164003e09b3c8981aab808d9ec1Scott Kennedy message.setTo(formatSenders(mTo.getText().toString())); 8938960f0af431bc164003e09b3c8981aab808d9ec1Scott Kennedy message.setCc(formatSenders(mCc.getText().toString())); 8948960f0af431bc164003e09b3c8981aab808d9ec1Scott Kennedy message.setBcc(formatSenders(mBcc.getText().toString())); 8958960f0af431bc164003e09b3c8981aab808d9ec1Scott Kennedy message.setReplyTo(null); 896e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira message.dateReceivedMs = 0; 897b4931c62bffec463df9c3871d83a35bbeb9d5920Paul Westbrook final String htmlBody = Html.toHtml(removeComposingSpans(mBodyView.getText())); 898b4931c62bffec463df9c3871d83a35bbeb9d5920Paul Westbrook final StringBuilder fullBody = new StringBuilder(htmlBody); 899e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira message.bodyHtml = fullBody.toString(); 900e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira message.bodyText = mBodyView.getText().toString(); 901e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira message.embedsExternalResources = false; 902a990a715012379451344246c5156d29938f12886Alice Yang message.refMessageUri = mRefMessage != null ? mRefMessage.uri : null; 903e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira message.appendRefMessageContent = mQuotedTextView.getQuotedTextIfIncluded() != null; 904e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira ArrayList<Attachment> attachments = mAttachmentsView.getAttachments(); 905e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira message.hasAttachments = attachments != null && attachments.size() > 0; 906e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira message.attachmentListUri = null; 907e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira message.messageFlags = 0; 908e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira message.alwaysShowImages = false; 909e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira message.attachmentsJson = Attachment.toJSONArray(attachments); 910e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira CharSequence quotedText = mQuotedTextView.getQuotedText(); 911e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira message.quotedTextOffset = !TextUtils.isEmpty(quotedText) ? QuotedTextView 912e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira .getQuotedTextOffset(quotedText.toString()) : -1; 913e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira message.accountUri = null; 9148960f0af431bc164003e09b3c8981aab808d9ec1Scott Kennedy message.setFrom(selectedReplyFromAccount != null ? selectedReplyFromAccount.address 9158960f0af431bc164003e09b3c8981aab808d9ec1Scott Kennedy : mAccount != null ? mAccount.name : null); 9161f8f4dd8c53e6c18ae642235335ce492c9d1e520Andy Huang message.draftType = getDraftType(mode); 917e7b76aac2ad5b12d6b04838ca72011ceaedc8910mindyp return message; 9181f8f4dd8c53e6c18ae642235335ce492c9d1e520Andy Huang } 9191f8f4dd8c53e6c18ae642235335ce492c9d1e520Andy Huang 920ff8553f20964f4c31b0c503a9e1daff6ae08a9c7Scott Kennedy private static String formatSenders(final String string) { 9213c9115813343861a44133b805fb9f55512d20948Mindy Pereira if (!TextUtils.isEmpty(string) && string.charAt(string.length() - 1) == ',') { 9223c9115813343861a44133b805fb9f55512d20948Mindy Pereira return string.substring(0, string.length() - 1); 9233c9115813343861a44133b805fb9f55512d20948Mindy Pereira } 9243c9115813343861a44133b805fb9f55512d20948Mindy Pereira return string; 9253c9115813343861a44133b805fb9f55512d20948Mindy Pereira } 9263c9115813343861a44133b805fb9f55512d20948Mindy Pereira 927818143e2163648acc0c91f123b84777d65cd70cfMindy Pereira @VisibleForTesting 928818143e2163648acc0c91f123b84777d65cd70cfMindy Pereira void setAccount(Account account) { 929bb5217ee950c156d761a086bfd0d1d392d224cf4Mindy Pereira if (account == null) { 930bb5217ee950c156d761a086bfd0d1d392d224cf4Mindy Pereira return; 931bb5217ee950c156d761a086bfd0d1d392d224cf4Mindy Pereira } 93223e9fdec6872f9b4d0fbe675745cb25becf7878cMindy Pereira if (!account.equals(mAccount)) { 93323e9fdec6872f9b4d0fbe675745cb25becf7878cMindy Pereira mAccount = account; 934b1f573c59ec20f9149443e1e0cc8b64ff3a07feaPaul Westbrook mCachedSettings = mAccount.settings; 935b1f573c59ec20f9149443e1e0cc8b64ff3a07feaPaul Westbrook appendSignature(); 93623e9fdec6872f9b4d0fbe675745cb25becf7878cMindy Pereira } 937fa20c1a4e36e0da2577baddbbb38a988b2017339Mindy Pereira if (mAccount != null) { 938f6c00b8304062a17d14b484bd1fc33a83c4a90d7Vikram Aggarwal MailActivity.setNfcMessage(mAccount.name); 939fa20c1a4e36e0da2577baddbbb38a988b2017339Mindy Pereira } 940818143e2163648acc0c91f123b84777d65cd70cfMindy Pereira } 941818143e2163648acc0c91f123b84777d65cd70cfMindy Pereira 942e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira private void initFromSpinner(Bundle bundle, int action) { 943e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira if (action == EDIT_DRAFT && mDraft.draftType == UIProvider.DraftType.COMPOSE) { 94462de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira action = COMPOSE; 94562de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira } 946c97ec3e157f1b2a30ebdc96ba9c6007f2f719aa6Paul Westbrook mFromSpinner.initialize(action, mAccount, mAccounts, mRefMessage); 947c97ec3e157f1b2a30ebdc96ba9c6007f2f719aa6Paul Westbrook 9489a42bb4f11c502dd5c2cf92249ac214a6c2f1a70Mindy Pereira if (bundle != null) { 9499a42bb4f11c502dd5c2cf92249ac214a6c2f1a70Mindy Pereira if (bundle.containsKey(EXTRA_SELECTED_REPLY_FROM_ACCOUNT)) { 9509a42bb4f11c502dd5c2cf92249ac214a6c2f1a70Mindy Pereira mReplyFromAccount = ReplyFromAccount.deserialize(mAccount, 9519a42bb4f11c502dd5c2cf92249ac214a6c2f1a70Mindy Pereira bundle.getString(EXTRA_SELECTED_REPLY_FROM_ACCOUNT)); 9529a42bb4f11c502dd5c2cf92249ac214a6c2f1a70Mindy Pereira } else if (bundle.containsKey(EXTRA_FROM_ACCOUNT_STRING)) { 953c97ec3e157f1b2a30ebdc96ba9c6007f2f719aa6Paul Westbrook final String accountString = bundle.getString(EXTRA_FROM_ACCOUNT_STRING); 9549a42bb4f11c502dd5c2cf92249ac214a6c2f1a70Mindy Pereira mReplyFromAccount = mFromSpinner.getMatchingReplyFromAccount(accountString); 9559a42bb4f11c502dd5c2cf92249ac214a6c2f1a70Mindy Pereira } 956e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira } 957e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira if (mReplyFromAccount == null) { 958e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira if (mDraft != null) { 959e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira mReplyFromAccount = getReplyFromAccountFromDraft(mAccount, mDraft); 960e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira } else if (mRefMessage != null) { 961e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira mReplyFromAccount = getReplyFromAccountForReply(mAccount, mRefMessage); 962e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira } 96362de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira } 96462de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira if (mReplyFromAccount == null) { 965238aa47dbd4426e8bd1c958e68a9d9b70c9be0f7Andy Huang mReplyFromAccount = getDefaultReplyFromAccount(mAccount); 96662de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira } 9679a42bb4f11c502dd5c2cf92249ac214a6c2f1a70Mindy Pereira 96862de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira mFromSpinner.setCurrentAccount(mReplyFromAccount); 9699a42bb4f11c502dd5c2cf92249ac214a6c2f1a70Mindy Pereira 97062de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira if (mFromSpinner.getCount() > 1) { 971a83e708e162ad1f4b04b41738882bf318e217f64Mindy Pereira // If there is only 1 account, just show that account. 972a83e708e162ad1f4b04b41738882bf318e217f64Mindy Pereira // Otherwise, give the user the ability to choose which account to 97362de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira // send mail from / save drafts to. 97462de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira mFromStatic.setVisibility(View.GONE); 975c97ec3e157f1b2a30ebdc96ba9c6007f2f719aa6Paul Westbrook mFromStaticText.setText(mReplyFromAccount.name); 97662de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira mFromSpinnerWrapper.setVisibility(View.VISIBLE); 977a83e708e162ad1f4b04b41738882bf318e217f64Mindy Pereira } else { 978a83e708e162ad1f4b04b41738882bf318e217f64Mindy Pereira mFromStatic.setVisibility(View.VISIBLE); 979c97ec3e157f1b2a30ebdc96ba9c6007f2f719aa6Paul Westbrook mFromStaticText.setText(mReplyFromAccount.name); 980a83e708e162ad1f4b04b41738882bf318e217f64Mindy Pereira mFromSpinnerWrapper.setVisibility(View.GONE); 981a83e708e162ad1f4b04b41738882bf318e217f64Mindy Pereira } 98246ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira } 98346ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira 98462de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira private ReplyFromAccount getReplyFromAccountForReply(Account account, Message refMessage) { 98562de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira if (refMessage.accountUri != null) { 98662de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira // This must be from combined inbox. 98762de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira List<ReplyFromAccount> replyFromAccounts = mFromSpinner.getReplyFromAccounts(); 98862de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira for (ReplyFromAccount from : replyFromAccounts) { 98962de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira if (from.account.uri.equals(refMessage.accountUri)) { 99062de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira return from; 99162de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira } 99262de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira } 99362de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira return null; 99462de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira } else { 99562de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira return getReplyFromAccount(account, refMessage); 99662de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira } 99762de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira } 99862de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira 99962de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira /** 10009016a5e827ae7baff9199811ecc8a9de9690b838Tony Mantler * Given an account and the message we're replying to, 100162de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira * return who the message should be sent from. 100262de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira * @param account Account in which the message arrived. 10039016a5e827ae7baff9199811ecc8a9de9690b838Tony Mantler * @param refMessage Message to analyze for account selection 100462de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira * @return the address from which to reply. 100562de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira */ 100662de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira public ReplyFromAccount getReplyFromAccount(Account account, Message refMessage) { 100762de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira // First see if we are supposed to use the default address or 100862de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira // the address it was sentTo. 1009326689d531da1d2579fa7daaf6e307e24a05f993Mindy Pereira if (mCachedSettings.forceReplyFromDefault) { 101062de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira return getDefaultReplyFromAccount(account); 101162de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira } else { 101289bae5713b830ec1182073de22c3091d3613ac3eMindy Pereira // If we aren't explicitly told which account to look for, look at 101362de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira // all the message recipients and find one that matches 101462de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira // a custom from or account. 101562de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira List<String> allRecipients = new ArrayList<String>(); 10169016a5e827ae7baff9199811ecc8a9de9690b838Tony Mantler allRecipients.addAll(Arrays.asList(refMessage.getToAddressesUnescaped())); 10179016a5e827ae7baff9199811ecc8a9de9690b838Tony Mantler allRecipients.addAll(Arrays.asList(refMessage.getCcAddressesUnescaped())); 101862de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira return getMatchingRecipient(account, allRecipients); 101962de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira } 102062de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira } 102162de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira 102262de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira /** 102362de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira * Compare all the recipients of an email to the current account and all 102462de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira * custom addresses associated with that account. Return the match if there 102562de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira * is one, or the default account if there isn't. 102662de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira */ 102762de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira protected ReplyFromAccount getMatchingRecipient(Account account, List<String> sentTo) { 102862de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira // Tokenize the list and place in a hashmap. 102962de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira ReplyFromAccount matchingReplyFrom = null; 103062de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira Rfc822Token[] tokens; 103162de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira HashSet<String> recipientsMap = new HashSet<String>(); 103262de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira for (String address : sentTo) { 103362de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira tokens = Rfc822Tokenizer.tokenize(address); 103462de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira for (int i = 0; i < tokens.length; i++) { 103562de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira recipientsMap.add(tokens[i].getAddress()); 103662de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira } 103762de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira } 103862de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira 103962de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira int matchingAddressCount = 0; 104062de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira List<ReplyFromAccount> customFroms; 10411617481de7c1f9b8dfcd25ba9828e933cf9d5490Andy Huang customFroms = account.getReplyFroms(); 10421617481de7c1f9b8dfcd25ba9828e933cf9d5490Andy Huang if (customFroms != null) { 10431617481de7c1f9b8dfcd25ba9828e933cf9d5490Andy Huang for (ReplyFromAccount entry : customFroms) { 10441617481de7c1f9b8dfcd25ba9828e933cf9d5490Andy Huang if (recipientsMap.contains(entry.address)) { 10451617481de7c1f9b8dfcd25ba9828e933cf9d5490Andy Huang matchingReplyFrom = entry; 10461617481de7c1f9b8dfcd25ba9828e933cf9d5490Andy Huang matchingAddressCount++; 104762de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira } 104862de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira } 104962de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira } 105062de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira if (matchingAddressCount > 1) { 105162de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira matchingReplyFrom = getDefaultReplyFromAccount(account); 105262de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira } 105362de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira return matchingReplyFrom; 105462de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira } 105562de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira 1056ff8553f20964f4c31b0c503a9e1daff6ae08a9c7Scott Kennedy private static ReplyFromAccount getDefaultReplyFromAccount(final Account account) { 1057ff8553f20964f4c31b0c503a9e1daff6ae08a9c7Scott Kennedy for (final ReplyFromAccount from : account.getReplyFroms()) { 105862de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira if (from.isDefault) { 105962de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira return from; 106062de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira } 106162de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira } 1062cd970ddaba4e212b668588db2104dc46ad3ad793Mindy Pereira return new ReplyFromAccount(account, account.uri, account.name, account.name, account.name, 1063cd970ddaba4e212b668588db2104dc46ad3ad793Mindy Pereira true, false); 106462de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira } 106562de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira 1066e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira private ReplyFromAccount getReplyFromAccountFromDraft(Account account, Message msg) { 10678960f0af431bc164003e09b3c8981aab808d9ec1Scott Kennedy String sender = msg.getFrom(); 106862de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira ReplyFromAccount replyFromAccount = null; 106962de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira List<ReplyFromAccount> replyFromAccounts = mFromSpinner.getReplyFromAccounts(); 107062de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira if (TextUtils.equals(account.name, sender)) { 107162de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira replyFromAccount = new ReplyFromAccount(mAccount, mAccount.uri, mAccount.name, 1072cd970ddaba4e212b668588db2104dc46ad3ad793Mindy Pereira mAccount.name, mAccount.name, true, false); 107362de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira } else { 107462de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira for (ReplyFromAccount fromAccount : replyFromAccounts) { 107562de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira if (TextUtils.equals(fromAccount.name, sender)) { 107662de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira replyFromAccount = fromAccount; 107762de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira break; 107862de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira } 107962de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira } 108062de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira } 108162de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira return replyFromAccount; 108262de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira } 108362de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira 108446ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira private void findViews() { 1085b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira findViewById(R.id.compose).setVisibility(View.VISIBLE); 1086a26b54e3a858de409be3746e65591bb8a0d6ea9aMindy Pereira mCcBccButton = (Button) findViewById(R.id.add_cc_bcc); 10878e9305ec0bbe23cec01eb34a2aee76c55199a10aMindy Pereira if (mCcBccButton != null) { 10888e9305ec0bbe23cec01eb34a2aee76c55199a10aMindy Pereira mCcBccButton.setOnClickListener(this); 10898e9305ec0bbe23cec01eb34a2aee76c55199a10aMindy Pereira } 10908e9305ec0bbe23cec01eb34a2aee76c55199a10aMindy Pereira mCcBccView = (CcBccView) findViewById(R.id.cc_bcc_wrapper); 10917b56a61174eeb202eea468b7f68b79729737ded2Mindy Pereira mAttachmentsView = (AttachmentsView)findViewById(R.id.attachments); 109293b079ba1d38d919b557dabcd971e7aa1e3f5cbcmindyp mPhotoAttachmentsButton = findViewById(R.id.add_photo_attachment); 1093cd0b0b950efebfc3964334067747b97e61c4f027mindyp if (mPhotoAttachmentsButton != null) { 1094cd0b0b950efebfc3964334067747b97e61c4f027mindyp mPhotoAttachmentsButton.setOnClickListener(this); 1095cd0b0b950efebfc3964334067747b97e61c4f027mindyp } 109693b079ba1d38d919b557dabcd971e7aa1e3f5cbcmindyp mVideoAttachmentsButton = findViewById(R.id.add_video_attachment); 1097cd0b0b950efebfc3964334067747b97e61c4f027mindyp if (mVideoAttachmentsButton != null) { 1098cd0b0b950efebfc3964334067747b97e61c4f027mindyp mVideoAttachmentsButton.setOnClickListener(this); 1099cd0b0b950efebfc3964334067747b97e61c4f027mindyp } 1100818143e2163648acc0c91f123b84777d65cd70cfMindy Pereira mTo = (RecipientEditTextView) findViewById(R.id.to); 110141500399a7ee9066319c0b07055638b07312c8acScott Kennedy mTo.setTokenizer(new Rfc822Tokenizer()); 1102818143e2163648acc0c91f123b84777d65cd70cfMindy Pereira mCc = (RecipientEditTextView) findViewById(R.id.cc); 110341500399a7ee9066319c0b07055638b07312c8acScott Kennedy mCc.setTokenizer(new Rfc822Tokenizer()); 1104818143e2163648acc0c91f123b84777d65cd70cfMindy Pereira mBcc = (RecipientEditTextView) findViewById(R.id.bcc); 110541500399a7ee9066319c0b07055638b07312c8acScott Kennedy mBcc.setTokenizer(new Rfc822Tokenizer()); 110682cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira // TODO: add special chips text change watchers before adding 110782cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira // this as a text changed watcher to the to, cc, bcc fields. 11086349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira mSubject = (TextView) findViewById(R.id.subject); 110962d3ec7f251f6f9a96a859a2702916d07f30a04amindyp mSubject.setOnEditorActionListener(this); 111046ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira mQuotedTextView = (QuotedTextView) findViewById(R.id.quoted_text_view); 111146ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira mQuotedTextView.setRespondInlineListener(this); 1112433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira mBodyView = (EditText) findViewById(R.id.body); 11131a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira mFromStatic = findViewById(R.id.static_from_content); 11142eb173211741adf7454bbf1990ba1b9d1e1f6a64Mindy Pereira mFromStaticText = (TextView) findViewById(R.id.from_account_name); 1115eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira mFromSpinnerWrapper = findViewById(R.id.spinner_from_content); 11165a85e2b7485a5c407c581219fe1b44417f050529Mindy Pereira mFromSpinner = (FromAddressSpinner) findViewById(R.id.from_picker); 1117326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } 1118326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira 111962d3ec7f251f6f9a96a859a2702916d07f30a04amindyp @Override 112062d3ec7f251f6f9a96a859a2702916d07f30a04amindyp public boolean onEditorAction(TextView view, int action, KeyEvent keyEvent) { 112162d3ec7f251f6f9a96a859a2702916d07f30a04amindyp if (action == EditorInfo.IME_ACTION_DONE) { 112262d3ec7f251f6f9a96a859a2702916d07f30a04amindyp focusBody(); 112362d3ec7f251f6f9a96a859a2702916d07f30a04amindyp return true; 112462d3ec7f251f6f9a96a859a2702916d07f30a04amindyp } 112562d3ec7f251f6f9a96a859a2702916d07f30a04amindyp return false; 112662d3ec7f251f6f9a96a859a2702916d07f30a04amindyp } 112762d3ec7f251f6f9a96a859a2702916d07f30a04amindyp 1128e011b1d1c8e2e674dfdf1985d9d13da8cc06d803Mindy Pereira protected TextView getBody() { 1129e011b1d1c8e2e674dfdf1985d9d13da8cc06d803Mindy Pereira return mBodyView; 1130e011b1d1c8e2e674dfdf1985d9d13da8cc06d803Mindy Pereira } 1131e011b1d1c8e2e674dfdf1985d9d13da8cc06d803Mindy Pereira 1132e011b1d1c8e2e674dfdf1985d9d13da8cc06d803Mindy Pereira @VisibleForTesting 1133e011b1d1c8e2e674dfdf1985d9d13da8cc06d803Mindy Pereira public Account getFromAccount() { 1134e011b1d1c8e2e674dfdf1985d9d13da8cc06d803Mindy Pereira return mReplyFromAccount != null && mReplyFromAccount.account != null ? 1135e011b1d1c8e2e674dfdf1985d9d13da8cc06d803Mindy Pereira mReplyFromAccount.account : mAccount; 1136e011b1d1c8e2e674dfdf1985d9d13da8cc06d803Mindy Pereira } 1137e011b1d1c8e2e674dfdf1985d9d13da8cc06d803Mindy Pereira 1138cbfb75a0f92a3ef5cf10ab94b451e4898cc78bfcMindy Pereira private void clearChangeListeners() { 1139cbfb75a0f92a3ef5cf10ab94b451e4898cc78bfcMindy Pereira mSubject.removeTextChangedListener(this); 1140cbfb75a0f92a3ef5cf10ab94b451e4898cc78bfcMindy Pereira mBodyView.removeTextChangedListener(this); 1141cbfb75a0f92a3ef5cf10ab94b451e4898cc78bfcMindy Pereira mTo.removeTextChangedListener(mToListener); 1142cbfb75a0f92a3ef5cf10ab94b451e4898cc78bfcMindy Pereira mCc.removeTextChangedListener(mCcListener); 1143cbfb75a0f92a3ef5cf10ab94b451e4898cc78bfcMindy Pereira mBcc.removeTextChangedListener(mBccListener); 1144cbfb75a0f92a3ef5cf10ab94b451e4898cc78bfcMindy Pereira mFromSpinner.setOnAccountChangedListener(null); 1145cbfb75a0f92a3ef5cf10ab94b451e4898cc78bfcMindy Pereira mAttachmentsView.setAttachmentChangesListener(null); 1146cbfb75a0f92a3ef5cf10ab94b451e4898cc78bfcMindy Pereira } 1147cbfb75a0f92a3ef5cf10ab94b451e4898cc78bfcMindy Pereira 114875f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira // Now that the message has been initialized from any existing draft or 114975f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira // ref message data, set up listeners for any changes that occur to the 115075f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira // message. 115175f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira private void initChangeListeners() { 11521d7e9145fa4f490ba87ade0ed70ce0fa1f33be81mindyp // Make sure we only add text changed listeners once! 11531d7e9145fa4f490ba87ade0ed70ce0fa1f33be81mindyp clearChangeListeners(); 115475f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira mSubject.addTextChangedListener(this); 115575f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira mBodyView.addTextChangedListener(this); 1156cbfb75a0f92a3ef5cf10ab94b451e4898cc78bfcMindy Pereira if (mToListener == null) { 1157cbfb75a0f92a3ef5cf10ab94b451e4898cc78bfcMindy Pereira mToListener = new RecipientTextWatcher(mTo, this); 1158cbfb75a0f92a3ef5cf10ab94b451e4898cc78bfcMindy Pereira } 1159cbfb75a0f92a3ef5cf10ab94b451e4898cc78bfcMindy Pereira mTo.addTextChangedListener(mToListener); 1160cbfb75a0f92a3ef5cf10ab94b451e4898cc78bfcMindy Pereira if (mCcListener == null) { 1161cbfb75a0f92a3ef5cf10ab94b451e4898cc78bfcMindy Pereira mCcListener = new RecipientTextWatcher(mCc, this); 1162cbfb75a0f92a3ef5cf10ab94b451e4898cc78bfcMindy Pereira } 1163cbfb75a0f92a3ef5cf10ab94b451e4898cc78bfcMindy Pereira mCc.addTextChangedListener(mCcListener); 1164cbfb75a0f92a3ef5cf10ab94b451e4898cc78bfcMindy Pereira if (mBccListener == null) { 1165cbfb75a0f92a3ef5cf10ab94b451e4898cc78bfcMindy Pereira mBccListener = new RecipientTextWatcher(mBcc, this); 1166cbfb75a0f92a3ef5cf10ab94b451e4898cc78bfcMindy Pereira } 1167cbfb75a0f92a3ef5cf10ab94b451e4898cc78bfcMindy Pereira mBcc.addTextChangedListener(mBccListener); 116875f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira mFromSpinner.setOnAccountChangedListener(this); 1169818143e2163648acc0c91f123b84777d65cd70cfMindy Pereira mAttachmentsView.setAttachmentChangesListener(this); 117075f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira } 117175f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira 1172a990a715012379451344246c5156d29938f12886Alice Yang private void initActionBar() { 1173a990a715012379451344246c5156d29938f12886Alice Yang LogUtils.d(LOG_TAG, "initializing action bar in ComposeActivity"); 1174eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira ActionBar actionBar = getActionBar(); 1175e011b1d1c8e2e674dfdf1985d9d13da8cc06d803Mindy Pereira if (actionBar == null) { 1176e011b1d1c8e2e674dfdf1985d9d13da8cc06d803Mindy Pereira return; 1177e011b1d1c8e2e674dfdf1985d9d13da8cc06d803Mindy Pereira } 1178a990a715012379451344246c5156d29938f12886Alice Yang if (mComposeMode == ComposeActivity.COMPOSE) { 1179eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_STANDARD); 1180eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira actionBar.setTitle(R.string.compose); 1181326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } else { 1182eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira actionBar.setTitle(null); 1183326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira if (mComposeModeAdapter == null) { 1184326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira mComposeModeAdapter = new ComposeModeAdapter(this); 1185326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } 1186eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_LIST); 1187eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira actionBar.setListNavigationCallbacks(mComposeModeAdapter, this); 1188a990a715012379451344246c5156d29938f12886Alice Yang switch (mComposeMode) { 1189326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira case ComposeActivity.REPLY: 1190eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira actionBar.setSelectedNavigationItem(0); 1191326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira break; 1192326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira case ComposeActivity.REPLY_ALL: 1193eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira actionBar.setSelectedNavigationItem(1); 1194326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira break; 1195326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira case ComposeActivity.FORWARD: 1196eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira actionBar.setSelectedNavigationItem(2); 1197326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira break; 1198326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } 11996349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira } 1200fbe4019a262f6b1934a44e598009ae63dc5745eeMindy Pereira actionBar.setDisplayOptions(ActionBar.DISPLAY_HOME_AS_UP | ActionBar.DISPLAY_SHOW_HOME, 1201fbe4019a262f6b1934a44e598009ae63dc5745eeMindy Pereira ActionBar.DISPLAY_HOME_AS_UP | ActionBar.DISPLAY_SHOW_HOME); 1202fbe4019a262f6b1934a44e598009ae63dc5745eeMindy Pereira actionBar.setHomeButtonEnabled(true); 12036349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira } 12046349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira 12050aeaf7d8c2ee4bc882ca901531f985c61b4cc7c7Scott Kennedy private void initFromRefMessage(int action) { 12060aeaf7d8c2ee4bc882ca901531f985c61b4cc7c7Scott Kennedy setFieldsFromRefMessage(action); 12071ebc2db723ed29093d724eb5da906a496ee57224Alice Yang 12081ebc2db723ed29093d724eb5da906a496ee57224Alice Yang // Check if To: address and email body needs to be prefilled based on extras. 12091ebc2db723ed29093d724eb5da906a496ee57224Alice Yang // This is used for reporting rendering feedback. 12101ebc2db723ed29093d724eb5da906a496ee57224Alice Yang if (MessageHeaderView.ENABLE_REPORT_RENDERING_PROBLEM) { 12111ebc2db723ed29093d724eb5da906a496ee57224Alice Yang Intent intent = getIntent(); 12121ebc2db723ed29093d724eb5da906a496ee57224Alice Yang if (intent.getExtras() != null) { 12131ebc2db723ed29093d724eb5da906a496ee57224Alice Yang String toAddresses = intent.getStringExtra(EXTRA_TO); 12141ebc2db723ed29093d724eb5da906a496ee57224Alice Yang if (toAddresses != null) { 12151ebc2db723ed29093d724eb5da906a496ee57224Alice Yang addToAddresses(Arrays.asList(TextUtils.split(toAddresses, ","))); 12161ebc2db723ed29093d724eb5da906a496ee57224Alice Yang } 12171ebc2db723ed29093d724eb5da906a496ee57224Alice Yang String body = intent.getStringExtra(EXTRA_BODY); 12181ebc2db723ed29093d724eb5da906a496ee57224Alice Yang if (body != null) { 12191ebc2db723ed29093d724eb5da906a496ee57224Alice Yang setBody(body, false /* withSignature */); 12201ebc2db723ed29093d724eb5da906a496ee57224Alice Yang } 12211ebc2db723ed29093d724eb5da906a496ee57224Alice Yang } 12221ebc2db723ed29093d724eb5da906a496ee57224Alice Yang } 12231ebc2db723ed29093d724eb5da906a496ee57224Alice Yang 122496a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira if (mRefMessage != null) { 122596a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira // CC field only gets populated when doing REPLY_ALL. 122696a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira // BCC never gets auto-populated, unless the user is editing 122796a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira // a draft with one. 122829a717e1047a2b50574e358c94a8ee8a41f377e9Mindy Pereira if (!TextUtils.isEmpty(mCc.getText()) && action == REPLY_ALL) { 122996a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira mCcBccView.show(false, true, false); 123096a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira } 123196a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira } 123296a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira updateHideOrShowCcBcc(); 123396a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira } 123496a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira 12350aeaf7d8c2ee4bc882ca901531f985c61b4cc7c7Scott Kennedy private void setFieldsFromRefMessage(int action) { 12368eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira setSubject(mRefMessage, action); 12378eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira // Setup recipients 12388eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira if (action == FORWARD) { 12398eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira mForward = true; 12408eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira } 12410aeaf7d8c2ee4bc882ca901531f985c61b4cc7c7Scott Kennedy initRecipientsFromRefMessage(mRefMessage, action); 1242e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira initQuotedTextFromRefMessage(mRefMessage, action); 12438eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira if (action == ComposeActivity.FORWARD || mAttachmentsChanged) { 12448eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira initAttachments(mRefMessage); 12456349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira } 1246c17d073dd43871df36ea70b3dea55963bdb98384Mindy Pereira } 1247c17d073dd43871df36ea70b3dea55963bdb98384Mindy Pereira 1248e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira private void initFromDraftMessage(Message message) { 12491f8f4dd8c53e6c18ae642235335ce492c9d1e520Andy Huang LogUtils.d(LOG_TAG, "Intializing draft from previous draft message: %s", message); 1250bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook 1251bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook mDraft = message; 1252bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook mDraftId = message.id; 1253bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook mSubject.setText(message.subject); 1254bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook mForward = message.draftType == UIProvider.DraftType.FORWARD; 12559016a5e827ae7baff9199811ecc8a9de9690b838Tony Mantler final List<String> toAddresses = Arrays.asList(message.getToAddressesUnescaped()); 1256bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook addToAddresses(toAddresses); 12579016a5e827ae7baff9199811ecc8a9de9690b838Tony Mantler addCcAddresses(Arrays.asList(message.getCcAddressesUnescaped()), toAddresses); 12589016a5e827ae7baff9199811ecc8a9de9690b838Tony Mantler addBccAddresses(Arrays.asList(message.getBccAddressesUnescaped())); 12592421dc8d6d0b4c727ab7ab0e5ce730f415089e86Mindy Pereira if (message.hasAttachments) { 12602421dc8d6d0b4c727ab7ab0e5ce730f415089e86Mindy Pereira List<Attachment> attachments = message.getAttachments(); 12612421dc8d6d0b4c727ab7ab0e5ce730f415089e86Mindy Pereira for (Attachment a : attachments) { 12625c5fd571b40a15b95ea5a5d6033f377706ffd0fbAndy Huang addAttachmentAndUpdateView(a); 12632421dc8d6d0b4c727ab7ab0e5ce730f415089e86Mindy Pereira } 12642421dc8d6d0b4c727ab7ab0e5ce730f415089e86Mindy Pereira } 1265cc8e7db940b2ad6c673e84ca7addae9295c10a33Mindy Pereira int quotedTextIndex = message.appendRefMessageContent ? 1266002ff5244800c32f2d70c96cc1110657020ee65cMindy Pereira message.quotedTextOffset : -1; 1267bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook // Set the body 1268002ff5244800c32f2d70c96cc1110657020ee65cMindy Pereira CharSequence quotedText = null; 1269bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook if (!TextUtils.isEmpty(message.bodyHtml)) { 1270752222d839d9afeb5c4665669eab81645e413495Mindy Pereira CharSequence htmlText = ""; 1271002ff5244800c32f2d70c96cc1110657020ee65cMindy Pereira if (quotedTextIndex > -1) { 1272752222d839d9afeb5c4665669eab81645e413495Mindy Pereira // Find the offset in the htmltext of the actual quoted text and strip it out. 1273752222d839d9afeb5c4665669eab81645e413495Mindy Pereira quotedTextIndex = QuotedTextView.findQuotedTextIndex(message.bodyHtml); 1274752222d839d9afeb5c4665669eab81645e413495Mindy Pereira if (quotedTextIndex > -1) { 1275c59dd8270215f97d39697dae9e69976bcfe3642bmindyp htmlText = Utils.convertHtmlToPlainText(message.bodyHtml.substring(0, 1276c59dd8270215f97d39697dae9e69976bcfe3642bmindyp quotedTextIndex)); 1277752222d839d9afeb5c4665669eab81645e413495Mindy Pereira quotedText = message.bodyHtml.subSequence(quotedTextIndex, 1278752222d839d9afeb5c4665669eab81645e413495Mindy Pereira message.bodyHtml.length()); 1279752222d839d9afeb5c4665669eab81645e413495Mindy Pereira } 12801a6e938c8a97092e332707a55edb5a53996edf98Mindy Pereira } else { 1281c59dd8270215f97d39697dae9e69976bcfe3642bmindyp htmlText = Utils.convertHtmlToPlainText(message.bodyHtml); 1282002ff5244800c32f2d70c96cc1110657020ee65cMindy Pereira } 1283002ff5244800c32f2d70c96cc1110657020ee65cMindy Pereira mBodyView.setText(htmlText); 1284bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook } else { 1285752222d839d9afeb5c4665669eab81645e413495Mindy Pereira final String body = message.bodyText; 1286752222d839d9afeb5c4665669eab81645e413495Mindy Pereira final CharSequence bodyText = !TextUtils.isEmpty(body) ? 1287752222d839d9afeb5c4665669eab81645e413495Mindy Pereira (quotedTextIndex > -1 ? 1288752222d839d9afeb5c4665669eab81645e413495Mindy Pereira message.bodyText.substring(0, quotedTextIndex) : message.bodyText) 1289752222d839d9afeb5c4665669eab81645e413495Mindy Pereira : ""; 1290002ff5244800c32f2d70c96cc1110657020ee65cMindy Pereira if (quotedTextIndex > -1) { 1291752222d839d9afeb5c4665669eab81645e413495Mindy Pereira quotedText = !TextUtils.isEmpty(body) ? message.bodyText.substring(quotedTextIndex) 1292752222d839d9afeb5c4665669eab81645e413495Mindy Pereira : null; 1293002ff5244800c32f2d70c96cc1110657020ee65cMindy Pereira } 1294002ff5244800c32f2d70c96cc1110657020ee65cMindy Pereira mBodyView.setText(bodyText); 1295002ff5244800c32f2d70c96cc1110657020ee65cMindy Pereira } 1296002ff5244800c32f2d70c96cc1110657020ee65cMindy Pereira if (quotedTextIndex > -1 && quotedText != null) { 12973971323f24b15b541f7460c1a4db42d78eb1873bMindy Pereira mQuotedTextView.setQuotedTextFromDraft(quotedText, mForward); 1298bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook } 1299bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook } 1300bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook 13018eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira /** 13028eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira * Fill all the widgets with the content found in the Intent Extra, if any. 13038eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira * Also apply the same style to all widgets. Note: if initFromExtras is 13048eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira * called as a result of switching between reply, reply all, and forward per 13058eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira * the latest revision of Gmail, and the user has already made changes to 13068eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira * attachments on a previous incarnation of the message (as a reply, reply 13078eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira * all, or forward), the original attachments from the message will not be 13088eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira * re-instantiated. The user's changes will be respected. This follows the 13098eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira * web gmail interaction. 13108eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira */ 13118eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira public void initFromExtras(Intent intent) { 13128eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira // If we were invoked with a SENDTO intent, the value 13138eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira // should take precedence 13148eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira final Uri dataUri = intent.getData(); 13158eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira if (dataUri != null) { 13168eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira if (MAIL_TO.equals(dataUri.getScheme())) { 13178eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira initFromMailTo(dataUri.toString()); 13188eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira } else { 13190b4f28ed53a7f1617dadf3b34de8c743a1733ce5Mindy Pereira if (!mAccount.composeIntentUri.equals(dataUri)) { 13208eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira String toText = dataUri.getSchemeSpecificPart(); 13218eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira if (toText != null) { 13228eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira mTo.setText(""); 1323dbe8996d8ba382bfe1a23894abbc4711e36c9daeMindy Pereira addToAddresses(Arrays.asList(TextUtils.split(toText, ","))); 13248eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira } 13258eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira } 13268eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira } 13278eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira } 13288eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira 13298eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira String[] extraStrings = intent.getStringArrayExtra(Intent.EXTRA_EMAIL); 13308eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira if (extraStrings != null) { 13318eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira addToAddresses(Arrays.asList(extraStrings)); 13328eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira } 13338eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira extraStrings = intent.getStringArrayExtra(Intent.EXTRA_CC); 13348eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira if (extraStrings != null) { 13358eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira addCcAddresses(Arrays.asList(extraStrings), null); 13368eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira } 13378eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira extraStrings = intent.getStringArrayExtra(Intent.EXTRA_BCC); 13388eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira if (extraStrings != null) { 13398eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira addBccAddresses(Arrays.asList(extraStrings)); 13408eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira } 13418eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira 13428eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira String extraString = intent.getStringExtra(Intent.EXTRA_SUBJECT); 13438eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira if (extraString != null) { 13448eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira mSubject.setText(extraString); 13458eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira } 13468eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira 134760847256c691b2677772a46919038f9c600fecf7Scott Kennedy mExtraValues = intent.getParcelableExtra(EXTRA_VALUES); 134860847256c691b2677772a46919038f9c600fecf7Scott Kennedy if (mExtraValues != null) { 134960847256c691b2677772a46919038f9c600fecf7Scott Kennedy LogUtils.d(LOG_TAG, "Launched with extra values: %s", mExtraValues.toString()); 135060847256c691b2677772a46919038f9c600fecf7Scott Kennedy } 135160847256c691b2677772a46919038f9c600fecf7Scott Kennedy 13528eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira for (String extra : ALL_EXTRAS) { 13538eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira if (intent.hasExtra(extra)) { 13548eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira String value = intent.getStringExtra(extra); 13558eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira if (EXTRA_TO.equals(extra)) { 1356dbe8996d8ba382bfe1a23894abbc4711e36c9daeMindy Pereira addToAddresses(Arrays.asList(TextUtils.split(value, ","))); 13578eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira } else if (EXTRA_CC.equals(extra)) { 1358dbe8996d8ba382bfe1a23894abbc4711e36c9daeMindy Pereira addCcAddresses(Arrays.asList(TextUtils.split(value, ",")), null); 13598eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira } else if (EXTRA_BCC.equals(extra)) { 1360dbe8996d8ba382bfe1a23894abbc4711e36c9daeMindy Pereira addBccAddresses(Arrays.asList(TextUtils.split(value, ","))); 13618eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira } else if (EXTRA_SUBJECT.equals(extra)) { 13628eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira mSubject.setText(value); 13638eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira } else if (EXTRA_BODY.equals(extra)) { 13648eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira setBody(value, true /* with signature */); 1365bc5e0dcf723918eb986d733ef42d64bcf2ec4ed5Andrew Sapperstein } else if (EXTRA_QUOTED_TEXT.equals(extra)) { 1366bc5e0dcf723918eb986d733ef42d64bcf2ec4ed5Andrew Sapperstein initQuotedText(value, true /* shouldQuoteText */); 13678eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira } 13688eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira } 13698eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira } 13708eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira 13718eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira Bundle extras = intent.getExtras(); 13728eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira if (extras != null) { 13738eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira CharSequence text = extras.getCharSequence(Intent.EXTRA_TEXT); 13748eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira if (text != null) { 13758eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira setBody(text, true /* with signature */); 13768eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira } 1377bc5e0dcf723918eb986d733ef42d64bcf2ec4ed5Andrew Sapperstein 1378bc5e0dcf723918eb986d733ef42d64bcf2ec4ed5Andrew Sapperstein // TODO - support EXTRA_HTML_TEXT 13798eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira } 1380e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira } 1381e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira 1382bc5e0dcf723918eb986d733ef42d64bcf2ec4ed5Andrew Sapperstein 13838eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira @VisibleForTesting 13848eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira protected String decodeEmailInUri(String s) throws UnsupportedEncodingException { 1385a4069f2f16c05c6d2948baa39b0c463be4c7a360Mindy Pereira // TODO: handle the case where there are spaces in the display name as 1386a4069f2f16c05c6d2948baa39b0c463be4c7a360Mindy Pereira // well as the email such as "Guy with spaces <guy+with+spaces@gmail.com>" 1387a4069f2f16c05c6d2948baa39b0c463be4c7a360Mindy Pereira // as they could be encoded ambiguously. 13888eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira // Since URLDecode.decode changes + into ' ', and + is a valid 13898eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira // email character, we need to find/ replace these ourselves before 13908eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira // decoding. 1391a4069f2f16c05c6d2948baa39b0c463be4c7a360Mindy Pereira try { 13927dd05b1b54673fe526ea35aa44e37827e8d38aa5Yorke Lee return URLDecoder.decode(replacePlus(s), UTF8_ENCODING_NAME); 1393a4069f2f16c05c6d2948baa39b0c463be4c7a360Mindy Pereira } catch (IllegalArgumentException e) { 1394a4069f2f16c05c6d2948baa39b0c463be4c7a360Mindy Pereira if (LogUtils.isLoggable(LOG_TAG, LogUtils.VERBOSE)) { 1395a4069f2f16c05c6d2948baa39b0c463be4c7a360Mindy Pereira LogUtils.e(LOG_TAG, "%s while decoding '%s'", e.getMessage(), s); 1396a4069f2f16c05c6d2948baa39b0c463be4c7a360Mindy Pereira } else { 1397a4069f2f16c05c6d2948baa39b0c463be4c7a360Mindy Pereira LogUtils.e(LOG_TAG, e, "Exception while decoding mailto address"); 1398a4069f2f16c05c6d2948baa39b0c463be4c7a360Mindy Pereira } 1399a4069f2f16c05c6d2948baa39b0c463be4c7a360Mindy Pereira return null; 1400a4069f2f16c05c6d2948baa39b0c463be4c7a360Mindy Pereira } 14018eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira } 14028eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira 14038eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira /** 14047dd05b1b54673fe526ea35aa44e37827e8d38aa5Yorke Lee * Replaces all occurrences of '+' with "%2B", to prevent URLDecode.decode from 14057dd05b1b54673fe526ea35aa44e37827e8d38aa5Yorke Lee * changing '+' into ' ' 14067dd05b1b54673fe526ea35aa44e37827e8d38aa5Yorke Lee * 14077dd05b1b54673fe526ea35aa44e37827e8d38aa5Yorke Lee * @param toReplace Input string 14087dd05b1b54673fe526ea35aa44e37827e8d38aa5Yorke Lee * @return The string with all "+" characters replaced with "%2B" 14097dd05b1b54673fe526ea35aa44e37827e8d38aa5Yorke Lee */ 14103b965d78774a42358ce6bbdcc43b4c8df130a60eScott Kennedy private static String replacePlus(String toReplace) { 14117dd05b1b54673fe526ea35aa44e37827e8d38aa5Yorke Lee return toReplace.replace("+", "%2B"); 14127dd05b1b54673fe526ea35aa44e37827e8d38aa5Yorke Lee } 14137dd05b1b54673fe526ea35aa44e37827e8d38aa5Yorke Lee 14147dd05b1b54673fe526ea35aa44e37827e8d38aa5Yorke Lee /** 14158eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira * Initialize the compose view from a String representing a mailTo uri. 14168eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira * @param mailToString The uri as a string. 14178eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira */ 14188eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira public void initFromMailTo(String mailToString) { 14198eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira // We need to disguise this string as a URI in order to parse it 14208eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira // TODO: Remove this hack when http://b/issue?id=1445295 gets fixed 14218eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira Uri uri = Uri.parse("foo://" + mailToString); 14228eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira int index = mailToString.indexOf("?"); 14238eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira int length = "mailto".length() + 1; 14248eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira String to; 14258eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira try { 14268eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira // Extract the recipient after mailto: 14278eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira if (index == -1) { 14288eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira to = decodeEmailInUri(mailToString.substring(length)); 14298eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira } else { 14308eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira to = decodeEmailInUri(mailToString.substring(length, index)); 14318eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira } 1432a4069f2f16c05c6d2948baa39b0c463be4c7a360Mindy Pereira if (!TextUtils.isEmpty(to)) { 1433a4069f2f16c05c6d2948baa39b0c463be4c7a360Mindy Pereira addToAddresses(Arrays.asList(TextUtils.split(to, ","))); 1434a4069f2f16c05c6d2948baa39b0c463be4c7a360Mindy Pereira } 14358eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira } catch (UnsupportedEncodingException e) { 14368eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira if (LogUtils.isLoggable(LOG_TAG, LogUtils.VERBOSE)) { 14378eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira LogUtils.e(LOG_TAG, "%s while decoding '%s'", e.getMessage(), mailToString); 14388eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira } else { 14398eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira LogUtils.e(LOG_TAG, e, "Exception while decoding mailto address"); 14408eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira } 14418eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira } 14428eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira 14438eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira List<String> cc = uri.getQueryParameters("cc"); 14448eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira addCcAddresses(Arrays.asList(cc.toArray(new String[cc.size()])), null); 14458eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira 14468eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira List<String> otherTo = uri.getQueryParameters("to"); 14478eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira addToAddresses(Arrays.asList(otherTo.toArray(new String[otherTo.size()]))); 14488eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira 14498eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira List<String> bcc = uri.getQueryParameters("bcc"); 14508eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira addBccAddresses(Arrays.asList(bcc.toArray(new String[bcc.size()]))); 14518eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira 14528eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira List<String> subject = uri.getQueryParameters("subject"); 14538eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira if (subject.size() > 0) { 14548eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira try { 14557dd05b1b54673fe526ea35aa44e37827e8d38aa5Yorke Lee mSubject.setText(URLDecoder.decode(replacePlus(subject.get(0)), 14567dd05b1b54673fe526ea35aa44e37827e8d38aa5Yorke Lee UTF8_ENCODING_NAME)); 14578eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira } catch (UnsupportedEncodingException e) { 14588eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira LogUtils.e(LOG_TAG, "%s while decoding subject '%s'", 14598eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira e.getMessage(), subject); 14608eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira } 14618eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira } 14628eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira 14638eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira List<String> body = uri.getQueryParameters("body"); 14648eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira if (body.size() > 0) { 14658eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira try { 14667dd05b1b54673fe526ea35aa44e37827e8d38aa5Yorke Lee setBody(URLDecoder.decode(replacePlus(body.get(0)), UTF8_ENCODING_NAME), 14678eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira true /* with signature */); 14688eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira } catch (UnsupportedEncodingException e) { 14698eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira LogUtils.e(LOG_TAG, "%s while decoding body '%s'", e.getMessage(), body); 14708eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira } 14718eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira } 14728eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira } 14738eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira 1474bddd6f39f34aa15fed2e757f7d3e4163272ca02cMindy Pereira @VisibleForTesting 1475bddd6f39f34aa15fed2e757f7d3e4163272ca02cMindy Pereira protected void initAttachments(Message refMessage) { 1476434f294a3ae17a4f76342af38d6376f672a5d9edMark Wei addAttachments(refMessage.getAttachments()); 1477434f294a3ae17a4f76342af38d6376f672a5d9edMark Wei } 1478434f294a3ae17a4f76342af38d6376f672a5d9edMark Wei 1479434f294a3ae17a4f76342af38d6376f672a5d9edMark Wei public long addAttachments(List<Attachment> attachments) { 1480434f294a3ae17a4f76342af38d6376f672a5d9edMark Wei long size = 0; 1481434f294a3ae17a4f76342af38d6376f672a5d9edMark Wei AttachmentFailureException error = null; 1482434f294a3ae17a4f76342af38d6376f672a5d9edMark Wei for (Attachment a : attachments) { 1483434f294a3ae17a4f76342af38d6376f672a5d9edMark Wei try { 1484434f294a3ae17a4f76342af38d6376f672a5d9edMark Wei size += mAttachmentsView.addAttachment(mAccount, a); 1485434f294a3ae17a4f76342af38d6376f672a5d9edMark Wei } catch (AttachmentFailureException e) { 1486434f294a3ae17a4f76342af38d6376f672a5d9edMark Wei error = e; 1487434f294a3ae17a4f76342af38d6376f672a5d9edMark Wei } 1488434f294a3ae17a4f76342af38d6376f672a5d9edMark Wei } 1489434f294a3ae17a4f76342af38d6376f672a5d9edMark Wei if (error != null) { 1490434f294a3ae17a4f76342af38d6376f672a5d9edMark Wei LogUtils.e(LOG_TAG, error, "Error adding attachment"); 1491434f294a3ae17a4f76342af38d6376f672a5d9edMark Wei if (attachments.size() > 1) { 1492434f294a3ae17a4f76342af38d6376f672a5d9edMark Wei showAttachmentTooBigToast(R.string.too_large_to_attach_multiple); 1493434f294a3ae17a4f76342af38d6376f672a5d9edMark Wei } else { 1494434f294a3ae17a4f76342af38d6376f672a5d9edMark Wei showAttachmentTooBigToast(error.getErrorRes()); 1495434f294a3ae17a4f76342af38d6376f672a5d9edMark Wei } 14963cd4f40dab2c0810cb5ecd77256abf022863b2b5Mindy Pereira } 1497434f294a3ae17a4f76342af38d6376f672a5d9edMark Wei return size; 14983cd4f40dab2c0810cb5ecd77256abf022863b2b5Mindy Pereira } 14993cd4f40dab2c0810cb5ecd77256abf022863b2b5Mindy Pereira 15003cd4f40dab2c0810cb5ecd77256abf022863b2b5Mindy Pereira /** 15013cd4f40dab2c0810cb5ecd77256abf022863b2b5Mindy Pereira * When an attachment is too large to be added to a message, show a toast. 15023cd4f40dab2c0810cb5ecd77256abf022863b2b5Mindy Pereira * This method also updates the position of the toast so that it is shown 15033cd4f40dab2c0810cb5ecd77256abf022863b2b5Mindy Pereira * clearly above they keyboard if it happens to be open. 15043cd4f40dab2c0810cb5ecd77256abf022863b2b5Mindy Pereira */ 1505434f294a3ae17a4f76342af38d6376f672a5d9edMark Wei private void showAttachmentTooBigToast(int errorRes) { 1506434f294a3ae17a4f76342af38d6376f672a5d9edMark Wei String maxSize = AttachmentUtils.convertToHumanReadableSize( 1507434f294a3ae17a4f76342af38d6376f672a5d9edMark Wei getApplicationContext(), mAccount.settings.getMaxAttachmentSize()); 1508434f294a3ae17a4f76342af38d6376f672a5d9edMark Wei showErrorToast(getString(errorRes, maxSize)); 15093cd4f40dab2c0810cb5ecd77256abf022863b2b5Mindy Pereira } 15103cd4f40dab2c0810cb5ecd77256abf022863b2b5Mindy Pereira 1511434f294a3ae17a4f76342af38d6376f672a5d9edMark Wei private void showErrorToast(String message) { 1512434f294a3ae17a4f76342af38d6376f672a5d9edMark Wei Toast t = Toast.makeText(this, message, Toast.LENGTH_LONG); 1513434f294a3ae17a4f76342af38d6376f672a5d9edMark Wei t.setText(message); 15143cd4f40dab2c0810cb5ecd77256abf022863b2b5Mindy Pereira t.setGravity(Gravity.CENTER_HORIZONTAL, 0, 15153cd4f40dab2c0810cb5ecd77256abf022863b2b5Mindy Pereira getResources().getDimensionPixelSize(R.dimen.attachment_toast_yoffset)); 15163cd4f40dab2c0810cb5ecd77256abf022863b2b5Mindy Pereira t.show(); 1517eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira } 1518eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira 1519f97588bd03fdcd318e24a9d74a283e73d1fbd37cPaul Westbrook private void initAttachmentsFromIntent(Intent intent) { 152003ee971afd8d766dea81b72fe77593e3be3ab798Paul Westbrook Bundle extras = intent.getExtras(); 152103ee971afd8d766dea81b72fe77593e3be3ab798Paul Westbrook if (extras == null) { 152203ee971afd8d766dea81b72fe77593e3be3ab798Paul Westbrook extras = Bundle.EMPTY; 152303ee971afd8d766dea81b72fe77593e3be3ab798Paul Westbrook } 1524f97588bd03fdcd318e24a9d74a283e73d1fbd37cPaul Westbrook final String action = intent.getAction(); 1525f97588bd03fdcd318e24a9d74a283e73d1fbd37cPaul Westbrook if (!mAttachmentsChanged) { 1526f97588bd03fdcd318e24a9d74a283e73d1fbd37cPaul Westbrook long totalSize = 0; 1527f97588bd03fdcd318e24a9d74a283e73d1fbd37cPaul Westbrook if (extras.containsKey(EXTRA_ATTACHMENTS)) { 1528f97588bd03fdcd318e24a9d74a283e73d1fbd37cPaul Westbrook String[] uris = (String[]) extras.getSerializable(EXTRA_ATTACHMENTS); 1529f97588bd03fdcd318e24a9d74a283e73d1fbd37cPaul Westbrook for (String uriString : uris) { 1530f97588bd03fdcd318e24a9d74a283e73d1fbd37cPaul Westbrook final Uri uri = Uri.parse(uriString); 1531f97588bd03fdcd318e24a9d74a283e73d1fbd37cPaul Westbrook long size = 0; 1532f97588bd03fdcd318e24a9d74a283e73d1fbd37cPaul Westbrook try { 15335c5fd571b40a15b95ea5a5d6033f377706ffd0fbAndy Huang size = mAttachmentsView.addAttachment(mAccount, uri); 1534f97588bd03fdcd318e24a9d74a283e73d1fbd37cPaul Westbrook } catch (AttachmentFailureException e) { 1535f97588bd03fdcd318e24a9d74a283e73d1fbd37cPaul Westbrook LogUtils.e(LOG_TAG, e, "Error adding attachment"); 1536434f294a3ae17a4f76342af38d6376f672a5d9edMark Wei showAttachmentTooBigToast(e.getErrorRes()); 1537f97588bd03fdcd318e24a9d74a283e73d1fbd37cPaul Westbrook } 1538f97588bd03fdcd318e24a9d74a283e73d1fbd37cPaul Westbrook totalSize += size; 1539f97588bd03fdcd318e24a9d74a283e73d1fbd37cPaul Westbrook } 1540f97588bd03fdcd318e24a9d74a283e73d1fbd37cPaul Westbrook } 15419a9e8d698ce11fb5fa8e7afecf587147f1a4e02amindyp if (extras.containsKey(Intent.EXTRA_STREAM)) { 15429a9e8d698ce11fb5fa8e7afecf587147f1a4e02amindyp if (Intent.ACTION_SEND_MULTIPLE.equals(action)) { 15439a9e8d698ce11fb5fa8e7afecf587147f1a4e02amindyp ArrayList<Parcelable> uris = extras 15449a9e8d698ce11fb5fa8e7afecf587147f1a4e02amindyp .getParcelableArrayList(Intent.EXTRA_STREAM); 15459a9e8d698ce11fb5fa8e7afecf587147f1a4e02amindyp ArrayList<Attachment> attachments = new ArrayList<Attachment>(); 15469a9e8d698ce11fb5fa8e7afecf587147f1a4e02amindyp for (Parcelable uri : uris) { 15479a9e8d698ce11fb5fa8e7afecf587147f1a4e02amindyp try { 15489a9e8d698ce11fb5fa8e7afecf587147f1a4e02amindyp attachments.add(mAttachmentsView.generateLocalAttachment((Uri) uri)); 15499a9e8d698ce11fb5fa8e7afecf587147f1a4e02amindyp } catch (AttachmentFailureException e) { 15509a9e8d698ce11fb5fa8e7afecf587147f1a4e02amindyp LogUtils.e(LOG_TAG, e, "Error adding attachment"); 15519a9e8d698ce11fb5fa8e7afecf587147f1a4e02amindyp String maxSize = AttachmentUtils.convertToHumanReadableSize( 15529a9e8d698ce11fb5fa8e7afecf587147f1a4e02amindyp getApplicationContext(), 15539a9e8d698ce11fb5fa8e7afecf587147f1a4e02amindyp mAccount.settings.getMaxAttachmentSize()); 15549a9e8d698ce11fb5fa8e7afecf587147f1a4e02amindyp showErrorToast(getString 15559a9e8d698ce11fb5fa8e7afecf587147f1a4e02amindyp (R.string.generic_attachment_problem, maxSize)); 15569a9e8d698ce11fb5fa8e7afecf587147f1a4e02amindyp } 15579a9e8d698ce11fb5fa8e7afecf587147f1a4e02amindyp } 15589a9e8d698ce11fb5fa8e7afecf587147f1a4e02amindyp totalSize += addAttachments(attachments); 15599a9e8d698ce11fb5fa8e7afecf587147f1a4e02amindyp } else { 15609a9e8d698ce11fb5fa8e7afecf587147f1a4e02amindyp final Uri uri = (Uri) extras.getParcelable(Intent.EXTRA_STREAM); 15619a9e8d698ce11fb5fa8e7afecf587147f1a4e02amindyp long size = 0; 1562f97588bd03fdcd318e24a9d74a283e73d1fbd37cPaul Westbrook try { 15639a9e8d698ce11fb5fa8e7afecf587147f1a4e02amindyp size = mAttachmentsView.addAttachment(mAccount, uri); 1564f97588bd03fdcd318e24a9d74a283e73d1fbd37cPaul Westbrook } catch (AttachmentFailureException e) { 1565f97588bd03fdcd318e24a9d74a283e73d1fbd37cPaul Westbrook LogUtils.e(LOG_TAG, e, "Error adding attachment"); 15669a9e8d698ce11fb5fa8e7afecf587147f1a4e02amindyp showAttachmentTooBigToast(e.getErrorRes()); 1567f97588bd03fdcd318e24a9d74a283e73d1fbd37cPaul Westbrook } 15689a9e8d698ce11fb5fa8e7afecf587147f1a4e02amindyp totalSize += size; 1569f97588bd03fdcd318e24a9d74a283e73d1fbd37cPaul Westbrook } 1570f97588bd03fdcd318e24a9d74a283e73d1fbd37cPaul Westbrook } 1571f97588bd03fdcd318e24a9d74a283e73d1fbd37cPaul Westbrook 1572f97588bd03fdcd318e24a9d74a283e73d1fbd37cPaul Westbrook if (totalSize > 0) { 1573f97588bd03fdcd318e24a9d74a283e73d1fbd37cPaul Westbrook mAttachmentsChanged = true; 1574f97588bd03fdcd318e24a9d74a283e73d1fbd37cPaul Westbrook updateSaveUi(); 1575f97588bd03fdcd318e24a9d74a283e73d1fbd37cPaul Westbrook } 1576f97588bd03fdcd318e24a9d74a283e73d1fbd37cPaul Westbrook } 1577f97588bd03fdcd318e24a9d74a283e73d1fbd37cPaul Westbrook } 1578f97588bd03fdcd318e24a9d74a283e73d1fbd37cPaul Westbrook 1579bc5e0dcf723918eb986d733ef42d64bcf2ec4ed5Andrew Sapperstein private void initQuotedText(CharSequence quotedText, boolean shouldQuoteText) { 1580bc5e0dcf723918eb986d733ef42d64bcf2ec4ed5Andrew Sapperstein mQuotedTextView.setQuotedTextFromHtml(quotedText, shouldQuoteText); 1581bc5e0dcf723918eb986d733ef42d64bcf2ec4ed5Andrew Sapperstein mShowQuotedText = true; 1582bc5e0dcf723918eb986d733ef42d64bcf2ec4ed5Andrew Sapperstein } 1583f97588bd03fdcd318e24a9d74a283e73d1fbd37cPaul Westbrook 1584e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira private void initQuotedTextFromRefMessage(Message refMessage, int action) { 1585e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira if (mRefMessage != null && (action == REPLY || action == REPLY_ALL || action == FORWARD)) { 15869932dee248718d2cec993d93b5115973d1389d0aMindy Pereira mQuotedTextView.setQuotedText(action, refMessage, action != FORWARD); 15879932dee248718d2cec993d93b5115973d1389d0aMindy Pereira } 158846ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira } 158946ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira 159046ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira private void updateHideOrShowCcBcc() { 1591ec8b0edb23c0e0b7f1a8ce9558a919be31169d45Mindy Pereira // Its possible there is a menu item OR a button. 1592326689d531da1d2579fa7daaf6e307e24a05f993Mindy Pereira boolean ccVisible = mCcBccView.isCcVisible(); 1593326689d531da1d2579fa7daaf6e307e24a05f993Mindy Pereira boolean bccVisible = mCcBccView.isBccVisible(); 1594ec8b0edb23c0e0b7f1a8ce9558a919be31169d45Mindy Pereira if (mCcBccButton != null) { 1595326689d531da1d2579fa7daaf6e307e24a05f993Mindy Pereira if (!ccVisible || !bccVisible) { 1596ec8b0edb23c0e0b7f1a8ce9558a919be31169d45Mindy Pereira mCcBccButton.setVisibility(View.VISIBLE); 1597326689d531da1d2579fa7daaf6e307e24a05f993Mindy Pereira mCcBccButton.setText(getString(!ccVisible ? R.string.add_cc_label 1598ec8b0edb23c0e0b7f1a8ce9558a919be31169d45Mindy Pereira : R.string.add_bcc_label)); 1599ec8b0edb23c0e0b7f1a8ce9558a919be31169d45Mindy Pereira } else { 1600cd0b0b950efebfc3964334067747b97e61c4f027mindyp mCcBccButton.setVisibility(View.INVISIBLE); 1601ec8b0edb23c0e0b7f1a8ce9558a919be31169d45Mindy Pereira } 1602ec8b0edb23c0e0b7f1a8ce9558a919be31169d45Mindy Pereira } 160346ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira } 160446ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira 1605a34c9a054c9aef6f83abe56515c132a31d71b3c8Mindy Pereira private void showCcBcc(Bundle state) { 1606326689d531da1d2579fa7daaf6e307e24a05f993Mindy Pereira if (state != null && state.containsKey(EXTRA_SHOW_CC)) { 1607326689d531da1d2579fa7daaf6e307e24a05f993Mindy Pereira boolean showCc = state.getBoolean(EXTRA_SHOW_CC); 1608326689d531da1d2579fa7daaf6e307e24a05f993Mindy Pereira boolean showBcc = state.getBoolean(EXTRA_SHOW_BCC); 1609326689d531da1d2579fa7daaf6e307e24a05f993Mindy Pereira if (showCc || showBcc) { 1610326689d531da1d2579fa7daaf6e307e24a05f993Mindy Pereira mCcBccView.show(false, showCc, showBcc); 1611326689d531da1d2579fa7daaf6e307e24a05f993Mindy Pereira } 1612326689d531da1d2579fa7daaf6e307e24a05f993Mindy Pereira } 1613326689d531da1d2579fa7daaf6e307e24a05f993Mindy Pereira } 1614326689d531da1d2579fa7daaf6e307e24a05f993Mindy Pereira 1615013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira /** 1616013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira * Add attachment and update the compose area appropriately. 1617013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira * @param data 1618013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira */ 1619013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira public void addAttachmentAndUpdateView(Intent data) { 16202421dc8d6d0b4c727ab7ab0e5ce730f415089e86Mindy Pereira addAttachmentAndUpdateView(data != null ? data.getData() : (Uri) null); 16212421dc8d6d0b4c727ab7ab0e5ce730f415089e86Mindy Pereira } 16222421dc8d6d0b4c727ab7ab0e5ce730f415089e86Mindy Pereira 16235c5fd571b40a15b95ea5a5d6033f377706ffd0fbAndy Huang public void addAttachmentAndUpdateView(Uri contentUri) { 16245c5fd571b40a15b95ea5a5d6033f377706ffd0fbAndy Huang if (contentUri == null) { 16252421dc8d6d0b4c727ab7ab0e5ce730f415089e86Mindy Pereira return; 16262421dc8d6d0b4c727ab7ab0e5ce730f415089e86Mindy Pereira } 1627013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira try { 16285c5fd571b40a15b95ea5a5d6033f377706ffd0fbAndy Huang addAttachmentAndUpdateView(mAttachmentsView.generateLocalAttachment(contentUri)); 16295c5fd571b40a15b95ea5a5d6033f377706ffd0fbAndy Huang } catch (AttachmentFailureException e) { 16305c5fd571b40a15b95ea5a5d6033f377706ffd0fbAndy Huang LogUtils.e(LOG_TAG, e, "Error adding attachment"); 1631434f294a3ae17a4f76342af38d6376f672a5d9edMark Wei showErrorToast(getResources().getString( 1632434f294a3ae17a4f76342af38d6376f672a5d9edMark Wei e.getErrorRes(), 1633434f294a3ae17a4f76342af38d6376f672a5d9edMark Wei AttachmentUtils.convertToHumanReadableSize( 1634434f294a3ae17a4f76342af38d6376f672a5d9edMark Wei getApplicationContext(), mAccount.settings.getMaxAttachmentSize()))); 16355c5fd571b40a15b95ea5a5d6033f377706ffd0fbAndy Huang } 16365c5fd571b40a15b95ea5a5d6033f377706ffd0fbAndy Huang } 16375c5fd571b40a15b95ea5a5d6033f377706ffd0fbAndy Huang 16385c5fd571b40a15b95ea5a5d6033f377706ffd0fbAndy Huang public void addAttachmentAndUpdateView(Attachment attachment) { 16395c5fd571b40a15b95ea5a5d6033f377706ffd0fbAndy Huang try { 1640434f294a3ae17a4f76342af38d6376f672a5d9edMark Wei long size = mAttachmentsView.addAttachment(mAccount, attachment); 16419932dee248718d2cec993d93b5115973d1389d0aMindy Pereira if (size > 0) { 16429932dee248718d2cec993d93b5115973d1389d0aMindy Pereira mAttachmentsChanged = true; 16439932dee248718d2cec993d93b5115973d1389d0aMindy Pereira updateSaveUi(); 1644013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira } 16459932dee248718d2cec993d93b5115973d1389d0aMindy Pereira } catch (AttachmentFailureException e) { 16469932dee248718d2cec993d93b5115973d1389d0aMindy Pereira LogUtils.e(LOG_TAG, e, "Error adding attachment"); 1647434f294a3ae17a4f76342af38d6376f672a5d9edMark Wei showAttachmentTooBigToast(e.getErrorRes()); 1648013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira } 1649013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira } 1650013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira 16510aeaf7d8c2ee4bc882ca901531f985c61b4cc7c7Scott Kennedy void initRecipientsFromRefMessage(Message refMessage, int action) { 16524a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira // Don't populate the address if this is a forward. 16534a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira if (action == ComposeActivity.FORWARD) { 16544a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira return; 16554a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira } 1656ff8553f20964f4c31b0c503a9e1daff6ae08a9c7Scott Kennedy initReplyRecipients(refMessage, action); 16574a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira } 16584a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira 16596d2442ba4417717b2a19714b0ac28c7265872ba3Paul Westbrook // TODO: This should be private. This method shouldn't be used by ComposeActivityTests, as 16606d2442ba4417717b2a19714b0ac28c7265872ba3Paul Westbrook // it doesn't setup the state of the activity correctly 1661818143e2163648acc0c91f123b84777d65cd70cfMindy Pereira @VisibleForTesting 1662ff8553f20964f4c31b0c503a9e1daff6ae08a9c7Scott Kennedy void initReplyRecipients(final Message refMessage, final int action) { 16639016a5e827ae7baff9199811ecc8a9de9690b838Tony Mantler String[] sentToAddresses = refMessage.getToAddressesUnescaped(); 1664a26b54e3a858de409be3746e65591bb8a0d6ea9aMindy Pereira final Collection<String> toAddresses; 166589de9eb1933bb2df287b74a93f6de5b1d19895aeTony Mantler final String[] replyToAddresses = refMessage.getReplyToAddressesUnescaped(); 166689de9eb1933bb2df287b74a93f6de5b1d19895aeTony Mantler String replyToAddress = replyToAddresses.length > 0 ? replyToAddresses[0] : null; 166789de9eb1933bb2df287b74a93f6de5b1d19895aeTony Mantler final String[] fromAddresses = refMessage.getFromAddressesUnescaped(); 166889de9eb1933bb2df287b74a93f6de5b1d19895aeTony Mantler final String fromAddress = fromAddresses.length > 0 ? fromAddresses[0] : null; 166989de9eb1933bb2df287b74a93f6de5b1d19895aeTony Mantler 167065b06f52e5b6336493388923be88bdd2ded4e1d1mindyp // If there is no reply to address, the reply to address is the sender. 167189de9eb1933bb2df287b74a93f6de5b1d19895aeTony Mantler if (TextUtils.isEmpty(replyToAddress)) { 167289de9eb1933bb2df287b74a93f6de5b1d19895aeTony Mantler replyToAddress = fromAddress; 167365b06f52e5b6336493388923be88bdd2ded4e1d1mindyp } 16744a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira 16754a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira // If this is a reply, the Cc list is empty. If this is a reply-all, the 16764a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira // Cc list is the union of the To and Cc recipients of the original 16774a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira // message, excluding the current user's email address and any addresses 1678a26b54e3a858de409be3746e65591bb8a0d6ea9aMindy Pereira // already on the To list. 1679a26b54e3a858de409be3746e65591bb8a0d6ea9aMindy Pereira if (action == ComposeActivity.REPLY) { 168089de9eb1933bb2df287b74a93f6de5b1d19895aeTony Mantler toAddresses = initToRecipients(fromAddress, replyToAddress, sentToAddresses); 1681a26b54e3a858de409be3746e65591bb8a0d6ea9aMindy Pereira addToAddresses(toAddresses); 1682a26b54e3a858de409be3746e65591bb8a0d6ea9aMindy Pereira } else if (action == ComposeActivity.REPLY_ALL) { 16834a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira final Set<String> ccAddresses = Sets.newHashSet(); 168489de9eb1933bb2df287b74a93f6de5b1d19895aeTony Mantler toAddresses = initToRecipients(fromAddress, replyToAddress, sentToAddresses); 1685154386a287a9bfffb2eb3a4c05445f2774e1d4f0Mindy Pereira addToAddresses(toAddresses); 1686ff8553f20964f4c31b0c503a9e1daff6ae08a9c7Scott Kennedy addRecipients(ccAddresses, sentToAddresses); 16879016a5e827ae7baff9199811ecc8a9de9690b838Tony Mantler addRecipients(ccAddresses, refMessage.getCcAddressesUnescaped()); 16884a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira addCcAddresses(ccAddresses, toAddresses); 16894a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira } 16904a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira } 16914a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira 16924a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira private void addToAddresses(Collection<String> addresses) { 16934a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira addAddressesToList(addresses, mTo); 16944a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira } 16954a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira 16964a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira private void addCcAddresses(Collection<String> addresses, Collection<String> toAddresses) { 16978eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira addCcAddressesToList(tokenizeAddressList(addresses), 16988eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira toAddresses != null ? tokenizeAddressList(toAddresses) : null, mCc); 16994a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira } 17004a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira 1701bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook private void addBccAddresses(Collection<String> addresses) { 1702bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook addAddressesToList(addresses, mBcc); 1703bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook } 1704bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook 17054a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira @VisibleForTesting 17064a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira protected void addCcAddressesToList(List<Rfc822Token[]> addresses, 17074a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira List<Rfc822Token[]> compareToList, RecipientEditTextView list) { 17084a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira String address; 17094a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira 17108eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira if (compareToList == null) { 17118eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira for (Rfc822Token[] tokens : addresses) { 17128eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira for (int i = 0; i < tokens.length; i++) { 17138eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira address = tokens[i].toString(); 17144a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira list.append(address + END_TOKEN); 17154a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira } 17164a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira } 17178eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira } else { 17188eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira HashSet<String> compareTo = convertToHashSet(compareToList); 17198eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira for (Rfc822Token[] tokens : addresses) { 17208eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira for (int i = 0; i < tokens.length; i++) { 17218eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira address = tokens[i].toString(); 17228eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira // Check if this is a duplicate: 17238eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira if (!compareTo.contains(tokens[i].getAddress())) { 17248eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira // Get the address here 17258eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira list.append(address + END_TOKEN); 17268eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira } 17278eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira } 17288eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira } 17294a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira } 17304a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira } 17314a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira 1732ff8553f20964f4c31b0c503a9e1daff6ae08a9c7Scott Kennedy private static HashSet<String> convertToHashSet(final List<Rfc822Token[]> list) { 1733ff8553f20964f4c31b0c503a9e1daff6ae08a9c7Scott Kennedy final HashSet<String> hash = new HashSet<String>(); 1734ff8553f20964f4c31b0c503a9e1daff6ae08a9c7Scott Kennedy for (final Rfc822Token[] tokens : list) { 17354a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira for (int i = 0; i < tokens.length; i++) { 17364a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira hash.add(tokens[i].getAddress()); 17374a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira } 17384a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira } 17394a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira return hash; 17404a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira } 17414a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira 17424a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira protected List<Rfc822Token[]> tokenizeAddressList(Collection<String> addresses) { 17434a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira @VisibleForTesting 17444a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira List<Rfc822Token[]> tokenized = new ArrayList<Rfc822Token[]>(); 17454a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira 17464a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira for (String address: addresses) { 17474a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira tokenized.add(Rfc822Tokenizer.tokenize(address)); 17484a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira } 17494a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira return tokenized; 17504a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira } 17514a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira 17524a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira @VisibleForTesting 17534a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira void addAddressesToList(Collection<String> addresses, RecipientEditTextView list) { 17544a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira for (String address : addresses) { 17554a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira addAddressToList(address, list); 17564a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira } 17574a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira } 17584a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira 1759ff8553f20964f4c31b0c503a9e1daff6ae08a9c7Scott Kennedy private static void addAddressToList(final String address, final RecipientEditTextView list) { 17604a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira if (address == null || list == null) 17614a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira return; 17624a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira 1763ff8553f20964f4c31b0c503a9e1daff6ae08a9c7Scott Kennedy final Rfc822Token[] tokens = Rfc822Tokenizer.tokenize(address); 17644a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira 17654a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira for (int i = 0; i < tokens.length; i++) { 17664a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira list.append(tokens[i] + END_TOKEN); 17674a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira } 17684a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira } 17694a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira 17704a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira @VisibleForTesting 1771ff8553f20964f4c31b0c503a9e1daff6ae08a9c7Scott Kennedy protected Collection<String> initToRecipients(final String fullSenderAddress, 1772ff8553f20964f4c31b0c503a9e1daff6ae08a9c7Scott Kennedy final String replyToAddress, final String[] inToAddresses) { 17734a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira // The To recipient is the reply-to address specified in the original 17744a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira // message, unless it is: 17754a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira // the current user OR a custom from of the current user, in which case 17764a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira // it's the To recipient list of the original message. 17774a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira // OR missing, in which case use the sender of the original message 17784a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira Set<String> toAddresses = Sets.newHashSet(); 177965b06f52e5b6336493388923be88bdd2ded4e1d1mindyp if (!TextUtils.isEmpty(replyToAddress) && !recipientMatchesThisAccount(replyToAddress)) { 17803ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereira toAddresses.add(replyToAddress); 17814a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira } else { 178265b06f52e5b6336493388923be88bdd2ded4e1d1mindyp // In this case, the user is replying to a message in which their 178365b06f52e5b6336493388923be88bdd2ded4e1d1mindyp // current account or one of their custom from addresses is the only 178465b06f52e5b6336493388923be88bdd2ded4e1d1mindyp // recipient and they sent the original message. 178565b06f52e5b6336493388923be88bdd2ded4e1d1mindyp if (inToAddresses.length == 1 && recipientMatchesThisAccount(fullSenderAddress) 178665b06f52e5b6336493388923be88bdd2ded4e1d1mindyp && recipientMatchesThisAccount(inToAddresses[0])) { 178765b06f52e5b6336493388923be88bdd2ded4e1d1mindyp toAddresses.add(inToAddresses[0]); 178865b06f52e5b6336493388923be88bdd2ded4e1d1mindyp return toAddresses; 178965b06f52e5b6336493388923be88bdd2ded4e1d1mindyp } 179065b06f52e5b6336493388923be88bdd2ded4e1d1mindyp // This happens if the user replies to a message they originally 179165b06f52e5b6336493388923be88bdd2ded4e1d1mindyp // wrote. In this case, "reply" really means "re-send," so we 179265b06f52e5b6336493388923be88bdd2ded4e1d1mindyp // target the original recipients. This works as expected even 179365b06f52e5b6336493388923be88bdd2ded4e1d1mindyp // if the user sent the original message to themselves. 179465b06f52e5b6336493388923be88bdd2ded4e1d1mindyp for (String address : inToAddresses) { 179565b06f52e5b6336493388923be88bdd2ded4e1d1mindyp if (!recipientMatchesThisAccount(address)) { 179665b06f52e5b6336493388923be88bdd2ded4e1d1mindyp toAddresses.add(address); 1797fe8557b7a3aca8c41d85edbc9a094d96aacb08e5mindyp } 17981469b4e00ea101bc86adef274cf6b4705425b7fcMindy Pereira } 17994a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira } 18004a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira return toAddresses; 18014a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira } 18024a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira 1803ff8553f20964f4c31b0c503a9e1daff6ae08a9c7Scott Kennedy private void addRecipients(final Set<String> recipients, final String[] addresses) { 1804ff8553f20964f4c31b0c503a9e1daff6ae08a9c7Scott Kennedy for (final String email : addresses) { 1805cecc54a913a665af3556f3fcc11cfae4d54cb3beMindy Pereira // Do not add this account, or any of its custom from addresses, to 1806cecc54a913a665af3556f3fcc11cfae4d54cb3beMindy Pereira // the list of recipients. 18074a20b708dd9ff3fb2b96f29b0b59012194c6fa34Mindy Pereira final String recipientAddress = Address.getEmailAddress(email).getAddress(); 18085ee5d69dc7ddbef52c6c62947757b3d86ac89f23mindyp if (!recipientMatchesThisAccount(recipientAddress)) { 18094a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira recipients.add(email.replace("\"\"", "")); 18104a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira } 18114a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira } 181246ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira } 181346ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira 1814cecc54a913a665af3556f3fcc11cfae4d54cb3beMindy Pereira /** 1815cecc54a913a665af3556f3fcc11cfae4d54cb3beMindy Pereira * A recipient matches this account if it has the same address as the 1816cecc54a913a665af3556f3fcc11cfae4d54cb3beMindy Pereira * currently selected account OR one of the custom from addresses associated 1817cecc54a913a665af3556f3fcc11cfae4d54cb3beMindy Pereira * with the currently selected account. 1818cecc54a913a665af3556f3fcc11cfae4d54cb3beMindy Pereira * @param recipientAddress address we are comparing with the currently selected account 1819cecc54a913a665af3556f3fcc11cfae4d54cb3beMindy Pereira * @return 1820cecc54a913a665af3556f3fcc11cfae4d54cb3beMindy Pereira */ 18215ee5d69dc7ddbef52c6c62947757b3d86ac89f23mindyp protected boolean recipientMatchesThisAccount(String recipientAddress) { 18225ee5d69dc7ddbef52c6c62947757b3d86ac89f23mindyp return ReplyFromAccount.matchesAccountOrCustomFrom(mAccount, recipientAddress, 1823fe8557b7a3aca8c41d85edbc9a094d96aacb08e5mindyp mAccount.getReplyFroms()); 1824cecc54a913a665af3556f3fcc11cfae4d54cb3beMindy Pereira } 1825cecc54a913a665af3556f3fcc11cfae4d54cb3beMindy Pereira 1826bc5e0dcf723918eb986d733ef42d64bcf2ec4ed5Andrew Sapperstein /** 1827bc5e0dcf723918eb986d733ef42d64bcf2ec4ed5Andrew Sapperstein * Returns a formatted subject string with the appropriate prefix for the action type. 1828bc5e0dcf723918eb986d733ef42d64bcf2ec4ed5Andrew Sapperstein * E.g., "FWD: " is prepended if action is {@link ComposeActivity#FORWARD}. 1829bc5e0dcf723918eb986d733ef42d64bcf2ec4ed5Andrew Sapperstein */ 1830bc5e0dcf723918eb986d733ef42d64bcf2ec4ed5Andrew Sapperstein public static String buildFormattedSubject(Resources res, String subject, int action) { 183146ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira String prefix; 183246ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira String correctedSubject = null; 183346ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira if (action == ComposeActivity.COMPOSE) { 183446ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira prefix = ""; 183546ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira } else if (action == ComposeActivity.FORWARD) { 1836bc5e0dcf723918eb986d733ef42d64bcf2ec4ed5Andrew Sapperstein prefix = res.getString(R.string.forward_subject_label); 183746ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira } else { 1838bc5e0dcf723918eb986d733ef42d64bcf2ec4ed5Andrew Sapperstein prefix = res.getString(R.string.reply_subject_label); 183946ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira } 184046ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira 184146ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira // Don't duplicate the prefix 1842c7a36999abb396ac965a981e0a3f658b537213acMindy Pereira if (!TextUtils.isEmpty(subject) 1843c7a36999abb396ac965a981e0a3f658b537213acMindy Pereira && subject.toLowerCase().startsWith(prefix.toLowerCase())) { 184446ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira correctedSubject = subject; 184546ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira } else { 1846bc5e0dcf723918eb986d733ef42d64bcf2ec4ed5Andrew Sapperstein correctedSubject = String.format( 1847bc5e0dcf723918eb986d733ef42d64bcf2ec4ed5Andrew Sapperstein res.getString(R.string.formatted_subject), prefix, subject); 184846ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira } 1849bc5e0dcf723918eb986d733ef42d64bcf2ec4ed5Andrew Sapperstein 1850bc5e0dcf723918eb986d733ef42d64bcf2ec4ed5Andrew Sapperstein return correctedSubject; 1851bc5e0dcf723918eb986d733ef42d64bcf2ec4ed5Andrew Sapperstein } 1852bc5e0dcf723918eb986d733ef42d64bcf2ec4ed5Andrew Sapperstein 1853bc5e0dcf723918eb986d733ef42d64bcf2ec4ed5Andrew Sapperstein private void setSubject(Message refMessage, int action) { 1854bc5e0dcf723918eb986d733ef42d64bcf2ec4ed5Andrew Sapperstein mSubject.setText(buildFormattedSubject(getResources(), refMessage.subject, action)); 185546ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira } 185646ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira 1857818143e2163648acc0c91f123b84777d65cd70cfMindy Pereira private void initRecipients() { 1858818143e2163648acc0c91f123b84777d65cd70cfMindy Pereira setupRecipients(mTo); 1859818143e2163648acc0c91f123b84777d65cd70cfMindy Pereira setupRecipients(mCc); 1860818143e2163648acc0c91f123b84777d65cd70cfMindy Pereira setupRecipients(mBcc); 1861eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira } 1862eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira 1863818143e2163648acc0c91f123b84777d65cd70cfMindy Pereira private void setupRecipients(RecipientEditTextView view) { 1864679a8cc895ec75d3b578dbc77db1e9c04dd7f8b0Paul Westbrook view.setAdapter(new RecipientAdapter(this, mAccount)); 186582cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira if (mValidator == null) { 1866679a8cc895ec75d3b578dbc77db1e9c04dd7f8b0Paul Westbrook final String accountName = mAccount.name; 186733fe908589dca6a7f58aa9f56d73f74a48ac42f6Mindy Pereira int offset = accountName.indexOf("@") + 1; 186833fe908589dca6a7f58aa9f56d73f74a48ac42f6Mindy Pereira String account = accountName; 1869c17d073dd43871df36ea70b3dea55963bdb98384Mindy Pereira if (offset > -1) { 187033fe908589dca6a7f58aa9f56d73f74a48ac42f6Mindy Pereira account = account.substring(accountName.indexOf("@") + 1); 1871c17d073dd43871df36ea70b3dea55963bdb98384Mindy Pereira } 187282cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira mValidator = new Rfc822Validator(account); 1873c17d073dd43871df36ea70b3dea55963bdb98384Mindy Pereira } 187482cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira view.setValidator(mValidator); 18758e9305ec0bbe23cec01eb34a2aee76c55199a10aMindy Pereira } 18768e9305ec0bbe23cec01eb34a2aee76c55199a10aMindy Pereira 18778e9305ec0bbe23cec01eb34a2aee76c55199a10aMindy Pereira @Override 18788e9305ec0bbe23cec01eb34a2aee76c55199a10aMindy Pereira public void onClick(View v) { 18792b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy final int id = v.getId(); 18802b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy if (id == R.id.add_cc_bcc) { 18812b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy // Verify that cc/ bcc aren't showing. 18822b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy // Animate in cc/bcc. 18832b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy showCcBccViews(); 18842b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy } else if (id == R.id.add_photo_attachment) { 18852b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy doAttach(MIME_TYPE_PHOTO); 18862b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy } else if (id == R.id.add_video_attachment) { 18872b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy doAttach(MIME_TYPE_VIDEO); 18888e9305ec0bbe23cec01eb34a2aee76c55199a10aMindy Pereira } 18898e9305ec0bbe23cec01eb34a2aee76c55199a10aMindy Pereira } 1890b47f3e286bcf78e85ab2d3389e38e99020d0634fMindy Pereira 1891b47f3e286bcf78e85ab2d3389e38e99020d0634fMindy Pereira @Override 1892b47f3e286bcf78e85ab2d3389e38e99020d0634fMindy Pereira public boolean onCreateOptionsMenu(Menu menu) { 1893b47f3e286bcf78e85ab2d3389e38e99020d0634fMindy Pereira super.onCreateOptionsMenu(menu); 1894b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira // Don't render any menu items when there are no accounts. 1895b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira if (mAccounts == null || mAccounts.length == 0) { 1896b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira return true; 1897b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira } 1898b47f3e286bcf78e85ab2d3389e38e99020d0634fMindy Pereira MenuInflater inflater = getMenuInflater(); 1899b47f3e286bcf78e85ab2d3389e38e99020d0634fMindy Pereira inflater.inflate(R.menu.compose_menu, menu); 19001d7e9145fa4f490ba87ade0ed70ce0fa1f33be81mindyp 19011d7e9145fa4f490ba87ade0ed70ce0fa1f33be81mindyp /* 19021d7e9145fa4f490ba87ade0ed70ce0fa1f33be81mindyp * Start save in the correct enabled state. 19031d7e9145fa4f490ba87ade0ed70ce0fa1f33be81mindyp * 1) If a user launches compose from within gmail, save is disabled 19041d7e9145fa4f490ba87ade0ed70ce0fa1f33be81mindyp * until they add something, at which point, save is enabled, auto save 19051d7e9145fa4f490ba87ade0ed70ce0fa1f33be81mindyp * on exit; if the user empties everything, save is disabled, exiting does not 19061d7e9145fa4f490ba87ade0ed70ce0fa1f33be81mindyp * auto-save 19071d7e9145fa4f490ba87ade0ed70ce0fa1f33be81mindyp * 2) if a user replies/ reply all/ forwards from within gmail, save is 19081d7e9145fa4f490ba87ade0ed70ce0fa1f33be81mindyp * disabled until they change something, at which point, save is 19091d7e9145fa4f490ba87ade0ed70ce0fa1f33be81mindyp * enabled, auto save on exit; if the user empties everything, save is 19101d7e9145fa4f490ba87ade0ed70ce0fa1f33be81mindyp * disabled, exiting does not auto-save. 19111d7e9145fa4f490ba87ade0ed70ce0fa1f33be81mindyp * 3) If a user launches compose from another application and something 19121d7e9145fa4f490ba87ade0ed70ce0fa1f33be81mindyp * gets populated (attachments, recipients, body, subject, etc), save is 19131d7e9145fa4f490ba87ade0ed70ce0fa1f33be81mindyp * enabled, auto save on exit; if the user empties everything, save is 19141d7e9145fa4f490ba87ade0ed70ce0fa1f33be81mindyp * disabled, exiting does not auto-save 19151d7e9145fa4f490ba87ade0ed70ce0fa1f33be81mindyp */ 191682cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira mSave = menu.findItem(R.id.save); 19171d7e9145fa4f490ba87ade0ed70ce0fa1f33be81mindyp String action = getIntent() != null ? getIntent().getAction() : null; 19189f855d667e34fbf0d330845225c26956e540b819Andy Huang enableSave(mInnerSavedState != null ? 19199f855d667e34fbf0d330845225c26956e540b819Andy Huang mInnerSavedState.getBoolean(EXTRA_SAVE_ENABLED) 19201d7e9145fa4f490ba87ade0ed70ce0fa1f33be81mindyp : (Intent.ACTION_SEND.equals(action) 19211d7e9145fa4f490ba87ade0ed70ce0fa1f33be81mindyp || Intent.ACTION_SEND_MULTIPLE.equals(action) 19221d7e9145fa4f490ba87ade0ed70ce0fa1f33be81mindyp || Intent.ACTION_SENDTO.equals(action) 19231d7e9145fa4f490ba87ade0ed70ce0fa1f33be81mindyp || shouldSave())); 19241d7e9145fa4f490ba87ade0ed70ce0fa1f33be81mindyp 192582cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira mSend = menu.findItem(R.id.send); 19263ca5bad62c075184920c5e331870280fc6acca16Mindy Pereira MenuItem helpItem = menu.findItem(R.id.help_info_menu_item); 19273ca5bad62c075184920c5e331870280fc6acca16Mindy Pereira MenuItem sendFeedbackItem = menu.findItem(R.id.feedback_menu_item); 19283ca5bad62c075184920c5e331870280fc6acca16Mindy Pereira if (helpItem != null) { 19293ca5bad62c075184920c5e331870280fc6acca16Mindy Pereira helpItem.setVisible(mAccount != null 19303ca5bad62c075184920c5e331870280fc6acca16Mindy Pereira && mAccount.supportsCapability(AccountCapabilities.HELP_CONTENT)); 19313ca5bad62c075184920c5e331870280fc6acca16Mindy Pereira } 19323ca5bad62c075184920c5e331870280fc6acca16Mindy Pereira if (sendFeedbackItem != null) { 19333ca5bad62c075184920c5e331870280fc6acca16Mindy Pereira sendFeedbackItem.setVisible(mAccount != null 19343ca5bad62c075184920c5e331870280fc6acca16Mindy Pereira && mAccount.supportsCapability(AccountCapabilities.SEND_FEEDBACK)); 19353ca5bad62c075184920c5e331870280fc6acca16Mindy Pereira } 1936b47f3e286bcf78e85ab2d3389e38e99020d0634fMindy Pereira return true; 1937b47f3e286bcf78e85ab2d3389e38e99020d0634fMindy Pereira } 1938b47f3e286bcf78e85ab2d3389e38e99020d0634fMindy Pereira 1939b47f3e286bcf78e85ab2d3389e38e99020d0634fMindy Pereira @Override 1940ec8b0edb23c0e0b7f1a8ce9558a919be31169d45Mindy Pereira public boolean onPrepareOptionsMenu(Menu menu) { 1941ec8b0edb23c0e0b7f1a8ce9558a919be31169d45Mindy Pereira MenuItem ccBcc = menu.findItem(R.id.add_cc_bcc); 1942818143e2163648acc0c91f123b84777d65cd70cfMindy Pereira if (ccBcc != null && mCc != null) { 1943ec8b0edb23c0e0b7f1a8ce9558a919be31169d45Mindy Pereira // Its possible there is a menu item OR a button. 1944ec8b0edb23c0e0b7f1a8ce9558a919be31169d45Mindy Pereira boolean ccFieldVisible = mCc.isShown(); 1945ec8b0edb23c0e0b7f1a8ce9558a919be31169d45Mindy Pereira boolean bccFieldVisible = mBcc.isShown(); 1946ec8b0edb23c0e0b7f1a8ce9558a919be31169d45Mindy Pereira if (!ccFieldVisible || !bccFieldVisible) { 1947ec8b0edb23c0e0b7f1a8ce9558a919be31169d45Mindy Pereira ccBcc.setVisible(true); 1948ec8b0edb23c0e0b7f1a8ce9558a919be31169d45Mindy Pereira ccBcc.setTitle(getString(!ccFieldVisible ? R.string.add_cc_label 1949ec8b0edb23c0e0b7f1a8ce9558a919be31169d45Mindy Pereira : R.string.add_bcc_label)); 1950ec8b0edb23c0e0b7f1a8ce9558a919be31169d45Mindy Pereira } else { 1951ec8b0edb23c0e0b7f1a8ce9558a919be31169d45Mindy Pereira ccBcc.setVisible(false); 1952ec8b0edb23c0e0b7f1a8ce9558a919be31169d45Mindy Pereira } 1953ec8b0edb23c0e0b7f1a8ce9558a919be31169d45Mindy Pereira } 1954ec8b0edb23c0e0b7f1a8ce9558a919be31169d45Mindy Pereira return true; 1955ec8b0edb23c0e0b7f1a8ce9558a919be31169d45Mindy Pereira } 1956ec8b0edb23c0e0b7f1a8ce9558a919be31169d45Mindy Pereira 1957ec8b0edb23c0e0b7f1a8ce9558a919be31169d45Mindy Pereira @Override 1958b47f3e286bcf78e85ab2d3389e38e99020d0634fMindy Pereira public boolean onOptionsItemSelected(MenuItem item) { 19592b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy final int id = item.getItemId(); 1960dc97bf4509c450c9121b79ec4668e0f9b34f0690Andy Huang 1961dc97bf4509c450c9121b79ec4668e0f9b34f0690Andy Huang Analytics.getInstance().sendMenuItemEvent(Analytics.EVENT_CATEGORY_MENU_ITEM, id, null, 0); 1962dc97bf4509c450c9121b79ec4668e0f9b34f0690Andy Huang 196375f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira boolean handled = true; 19642b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy if (id == R.id.add_photo_attachment) { 19652b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy doAttach(MIME_TYPE_PHOTO); 19662b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy } else if (id == R.id.add_video_attachment) { 19672b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy doAttach(MIME_TYPE_VIDEO); 19682b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy } else if (id == R.id.add_cc_bcc) { 19692b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy showCcBccViews(); 19702b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy } else if (id == R.id.save) { 19712b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy doSave(true); 19722b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy } else if (id == R.id.send) { 19732b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy doSend(); 19742b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy } else if (id == R.id.discard) { 19752b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy doDiscard(); 19762b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy } else if (id == R.id.settings) { 19772b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy Utils.showSettings(this, mAccount); 19782b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy } else if (id == android.R.id.home) { 19792b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy onAppUpPressed(); 19802b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy } else if (id == R.id.help_info_menu_item) { 19812b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy Utils.showHelp(this, mAccount, getString(R.string.compose_help_context)); 19822b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy } else if (id == R.id.feedback_menu_item) { 19832b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy Utils.sendFeedback(this, mAccount, false); 19842b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy } else { 19852b9d80eb16156173f11a02eae4f770d8c975927cScott Kennedy handled = false; 1986b47f3e286bcf78e85ab2d3389e38e99020d0634fMindy Pereira } 1987b47f3e286bcf78e85ab2d3389e38e99020d0634fMindy Pereira return !handled ? super.onOptionsItemSelected(item) : handled; 1988b47f3e286bcf78e85ab2d3389e38e99020d0634fMindy Pereira } 1989326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira 1990b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira @Override 1991b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira public void onBackPressed() { 1992b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira // If we are showing the wait fragment, just exit. 1993b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira if (getWaitFragment() != null) { 1994b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira finish(); 1995b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira } else { 1996b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira super.onBackPressed(); 1997b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira } 1998b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira } 1999b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira 20001672ff8ed6741df5c245e55f7a4e847f6ccb8c52Vikram Aggarwal /** 20011672ff8ed6741df5c245e55f7a4e847f6ccb8c52Vikram Aggarwal * Carries out the "up" action in the action bar. 20021672ff8ed6741df5c245e55f7a4e847f6ccb8c52Vikram Aggarwal */ 2003daecb4b9b20a609b27fc803390ecf4f524b76089Paul Westbrook private void onAppUpPressed() { 2004daecb4b9b20a609b27fc803390ecf4f524b76089Paul Westbrook if (mLaunchedFromEmail) { 2005daecb4b9b20a609b27fc803390ecf4f524b76089Paul Westbrook // If this was started from Gmail, simply treat app up as the system back button, so 2006daecb4b9b20a609b27fc803390ecf4f524b76089Paul Westbrook // that the last view is restored. 2007daecb4b9b20a609b27fc803390ecf4f524b76089Paul Westbrook onBackPressed(); 2008daecb4b9b20a609b27fc803390ecf4f524b76089Paul Westbrook return; 2009daecb4b9b20a609b27fc803390ecf4f524b76089Paul Westbrook } 2010daecb4b9b20a609b27fc803390ecf4f524b76089Paul Westbrook 2011daecb4b9b20a609b27fc803390ecf4f524b76089Paul Westbrook // Fire the main activity to ensure it launches the "top" screen of mail. 2012daecb4b9b20a609b27fc803390ecf4f524b76089Paul Westbrook // Since the main Activity is singleTask, it should revive that task if it was already 2013daecb4b9b20a609b27fc803390ecf4f524b76089Paul Westbrook // started. 20140c3c2058f75487713c64634c7f08025fd78ba012Vikram Aggarwal final Intent mailIntent = Utils.createViewInboxIntent(mAccount); 2015daecb4b9b20a609b27fc803390ecf4f524b76089Paul Westbrook mailIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK | 2016daecb4b9b20a609b27fc803390ecf4f524b76089Paul Westbrook Intent.FLAG_ACTIVITY_TASK_ON_HOME); 2017daecb4b9b20a609b27fc803390ecf4f524b76089Paul Westbrook startActivity(mailIntent); 2018daecb4b9b20a609b27fc803390ecf4f524b76089Paul Westbrook finish(); 2019daecb4b9b20a609b27fc803390ecf4f524b76089Paul Westbrook } 2020daecb4b9b20a609b27fc803390ecf4f524b76089Paul Westbrook 202133fe908589dca6a7f58aa9f56d73f74a48ac42f6Mindy Pereira private void doSend() { 2022dd19b63d3f560aba8962435ed5a2e1f5ae794351Mark Wei sendOrSaveWithSanityChecks(false, true, false, false); 2023dc97bf4509c450c9121b79ec4668e0f9b34f0690Andy Huang logSendOrSave(false /* save */); 2024dc97bf4509c450c9121b79ec4668e0f9b34f0690Andy Huang mPerformedSendOrDiscard = true; 202533fe908589dca6a7f58aa9f56d73f74a48ac42f6Mindy Pereira } 202633fe908589dca6a7f58aa9f56d73f74a48ac42f6Mindy Pereira 202748e31b07b5ac7c83dc3a009242fa915afccddb9eMindy Pereira private void doSave(boolean showToast) { 2028dd19b63d3f560aba8962435ed5a2e1f5ae794351Mark Wei sendOrSaveWithSanityChecks(true, showToast, false, false); 202948e31b07b5ac7c83dc3a009242fa915afccddb9eMindy Pereira } 203048e31b07b5ac7c83dc3a009242fa915afccddb9eMindy Pereira 2031e011b1d1c8e2e674dfdf1985d9d13da8cc06d803Mindy Pereira @VisibleForTesting 2032e011b1d1c8e2e674dfdf1985d9d13da8cc06d803Mindy Pereira public interface SendOrSaveCallback { 203382cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira public void initializeSendOrSave(SendOrSaveTask sendOrSaveTask); 20347ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira public void notifyMessageIdAllocated(SendOrSaveMessage sendOrSaveMessage, Message message); 20357ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira public Message getMessage(); 203682cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira public void sendOrSaveFinished(SendOrSaveTask sendOrSaveTask, boolean success); 203782cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira } 203882cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira 2039e011b1d1c8e2e674dfdf1985d9d13da8cc06d803Mindy Pereira @VisibleForTesting 2040e011b1d1c8e2e674dfdf1985d9d13da8cc06d803Mindy Pereira public static class SendOrSaveTask implements Runnable { 204182cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira private final Context mContext; 204282cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira @VisibleForTesting 2043e011b1d1c8e2e674dfdf1985d9d13da8cc06d803Mindy Pereira public final SendOrSaveCallback mSendOrSaveCallback; 2044e011b1d1c8e2e674dfdf1985d9d13da8cc06d803Mindy Pereira @VisibleForTesting 2045e011b1d1c8e2e674dfdf1985d9d13da8cc06d803Mindy Pereira public final SendOrSaveMessage mSendOrSaveMessage; 204644a6339dd80f4b5b9e5d54567021698d92467c5emindyp private ReplyFromAccount mExistingDraftAccount; 204782cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira 204882cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira public SendOrSaveTask(Context context, SendOrSaveMessage message, 204944a6339dd80f4b5b9e5d54567021698d92467c5emindyp SendOrSaveCallback callback, ReplyFromAccount draftAccount) { 205082cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira mContext = context; 205182cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira mSendOrSaveCallback = callback; 205282cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira mSendOrSaveMessage = message; 205344a6339dd80f4b5b9e5d54567021698d92467c5emindyp mExistingDraftAccount = draftAccount; 205482cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira } 205582cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira 205682cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira @Override 205782cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira public void run() { 20587ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira final SendOrSaveMessage sendOrSaveMessage = mSendOrSaveMessage; 205982cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira 206092551d057965689f1952faeb06763f0762bc717fMindy Pereira final ReplyFromAccount selectedAccount = sendOrSaveMessage.mAccount; 20617ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira Message message = mSendOrSaveCallback.getMessage(); 20627ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira long messageId = message != null ? message.id : UIProvider.INVALID_MESSAGE_ID; 206382cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira // If a previous draft has been saved, in an account that is different 206482cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira // than what the user wants to send from, remove the old draft, and treat this 206582cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira // as a new message 206644a6339dd80f4b5b9e5d54567021698d92467c5emindyp if (mExistingDraftAccount != null 206744a6339dd80f4b5b9e5d54567021698d92467c5emindyp && !selectedAccount.account.uri.equals(mExistingDraftAccount.account.uri)) { 206882cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira if (messageId != UIProvider.INVALID_MESSAGE_ID) { 206982cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira ContentResolver resolver = mContext.getContentResolver(); 207082cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira ContentValues values = new ContentValues(); 207182cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira values.put(BaseColumns._ID, messageId); 2072febd226e871263aeb21d436bee81eb2f7dec3d03mindyp if (mExistingDraftAccount.account.expungeMessageUri != null) { 2073febd226e871263aeb21d436bee81eb2f7dec3d03mindyp new ContentProviderTask.UpdateTask() 2074febd226e871263aeb21d436bee81eb2f7dec3d03mindyp .run(resolver, mExistingDraftAccount.account.expungeMessageUri, 2075febd226e871263aeb21d436bee81eb2f7dec3d03mindyp values, null, null); 2076cfb7f33ff8ef9dc60b9143af32de64c7a3d71f36Mindy Pereira } else { 2077cfb7f33ff8ef9dc60b9143af32de64c7a3d71f36Mindy Pereira // TODO(mindyp) delete the conversation. 2078eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira } 207982cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira // reset messageId to 0, so a new message will be created 208082cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira messageId = UIProvider.INVALID_MESSAGE_ID; 208182cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira } 208282cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira } 208382cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira 208482cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira final long messageIdToSave = messageId; 2085ff8553f20964f4c31b0c503a9e1daff6ae08a9c7Scott Kennedy sendOrSaveMessage(messageIdToSave, sendOrSaveMessage, selectedAccount); 208672e2ea860f66f496537e37ebc0ddd2c670d4c651Paul Westbrook 208772e2ea860f66f496537e37ebc0ddd2c670d4c651Paul Westbrook if (!sendOrSaveMessage.mSave) { 20889f32423b2e1f7ef6747eb1a27f3faa15f5a3db1cTony Mantler incrementRecipientsTimesContacted(mContext, 208972e2ea860f66f496537e37ebc0ddd2c670d4c651Paul Westbrook (String) sendOrSaveMessage.mValues.get(UIProvider.MessageColumns.TO)); 20909f32423b2e1f7ef6747eb1a27f3faa15f5a3db1cTony Mantler incrementRecipientsTimesContacted(mContext, 209172e2ea860f66f496537e37ebc0ddd2c670d4c651Paul Westbrook (String) sendOrSaveMessage.mValues.get(UIProvider.MessageColumns.CC)); 20929f32423b2e1f7ef6747eb1a27f3faa15f5a3db1cTony Mantler incrementRecipientsTimesContacted(mContext, 209372e2ea860f66f496537e37ebc0ddd2c670d4c651Paul Westbrook (String) sendOrSaveMessage.mValues.get(UIProvider.MessageColumns.BCC)); 209472e2ea860f66f496537e37ebc0ddd2c670d4c651Paul Westbrook } 209572e2ea860f66f496537e37ebc0ddd2c670d4c651Paul Westbrook mSendOrSaveCallback.sendOrSaveFinished(SendOrSaveTask.this, true); 209672e2ea860f66f496537e37ebc0ddd2c670d4c651Paul Westbrook } 209772e2ea860f66f496537e37ebc0ddd2c670d4c651Paul Westbrook 20989f32423b2e1f7ef6747eb1a27f3faa15f5a3db1cTony Mantler private static void incrementRecipientsTimesContacted(final Context context, 20999f32423b2e1f7ef6747eb1a27f3faa15f5a3db1cTony Mantler final String addressString) { 21009f32423b2e1f7ef6747eb1a27f3faa15f5a3db1cTony Mantler if (TextUtils.isEmpty(addressString)) { 21019f32423b2e1f7ef6747eb1a27f3faa15f5a3db1cTony Mantler return; 21029f32423b2e1f7ef6747eb1a27f3faa15f5a3db1cTony Mantler } 21039f32423b2e1f7ef6747eb1a27f3faa15f5a3db1cTony Mantler final Rfc822Token[] tokens = Rfc822Tokenizer.tokenize(addressString); 21049f32423b2e1f7ef6747eb1a27f3faa15f5a3db1cTony Mantler final ArrayList<String> recipients = new ArrayList<String>(tokens.length); 21059f32423b2e1f7ef6747eb1a27f3faa15f5a3db1cTony Mantler for (int i = 0; i < tokens.length;i++) { 21069f32423b2e1f7ef6747eb1a27f3faa15f5a3db1cTony Mantler recipients.add(tokens[i].getAddress()); 21079f32423b2e1f7ef6747eb1a27f3faa15f5a3db1cTony Mantler } 21089f32423b2e1f7ef6747eb1a27f3faa15f5a3db1cTony Mantler final DataUsageStatUpdater statsUpdater = new DataUsageStatUpdater(context); 21099f32423b2e1f7ef6747eb1a27f3faa15f5a3db1cTony Mantler statsUpdater.updateWithAddress(recipients); 21109f32423b2e1f7ef6747eb1a27f3faa15f5a3db1cTony Mantler } 21119f32423b2e1f7ef6747eb1a27f3faa15f5a3db1cTony Mantler 211272e2ea860f66f496537e37ebc0ddd2c670d4c651Paul Westbrook /** 211372e2ea860f66f496537e37ebc0ddd2c670d4c651Paul Westbrook * Send or Save a message. 211472e2ea860f66f496537e37ebc0ddd2c670d4c651Paul Westbrook */ 2115ff8553f20964f4c31b0c503a9e1daff6ae08a9c7Scott Kennedy private void sendOrSaveMessage(final long messageIdToSave, 2116ff8553f20964f4c31b0c503a9e1daff6ae08a9c7Scott Kennedy final SendOrSaveMessage sendOrSaveMessage, final ReplyFromAccount selectedAccount) { 211772e2ea860f66f496537e37ebc0ddd2c670d4c651Paul Westbrook final ContentResolver resolver = mContext.getContentResolver(); 211872e2ea860f66f496537e37ebc0ddd2c670d4c651Paul Westbrook final boolean updateExistingMessage = messageIdToSave != UIProvider.INVALID_MESSAGE_ID; 211972e2ea860f66f496537e37ebc0ddd2c670d4c651Paul Westbrook 212072e2ea860f66f496537e37ebc0ddd2c670d4c651Paul Westbrook final String accountMethod = sendOrSaveMessage.mSave ? 212172e2ea860f66f496537e37ebc0ddd2c670d4c651Paul Westbrook UIProvider.AccountCallMethods.SAVE_MESSAGE : 212272e2ea860f66f496537e37ebc0ddd2c670d4c651Paul Westbrook UIProvider.AccountCallMethods.SEND_MESSAGE; 212372e2ea860f66f496537e37ebc0ddd2c670d4c651Paul Westbrook 21243c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook try { 21253c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook if (updateExistingMessage) { 21263c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook sendOrSaveMessage.mValues.put(BaseColumns._ID, messageIdToSave); 21273c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook 2128013a23c75cf8a71c51ad1580aa84f2a8e06b6761Paul Westbrook callAccountSendSaveMethod(resolver, 21293c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook selectedAccount.account, accountMethod, sendOrSaveMessage); 213072e2ea860f66f496537e37ebc0ddd2c670d4c651Paul Westbrook } else { 2131013a23c75cf8a71c51ad1580aa84f2a8e06b6761Paul Westbrook Uri messageUri = null; 21323c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook final Bundle result = callAccountSendSaveMethod(resolver, 21333c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook selectedAccount.account, accountMethod, sendOrSaveMessage); 21343c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook if (result != null) { 21353c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook // If a non-null value was returned, then the provider handled the call 21363c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook // method 21373c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook messageUri = result.getParcelable(UIProvider.MessageColumns.URI); 21383c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook } 21393c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook if (sendOrSaveMessage.mSave && messageUri != null) { 21403c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook final Cursor messageCursor = resolver.query(messageUri, 21413c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook UIProvider.MESSAGE_PROJECTION, null, null, null); 21423c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook if (messageCursor != null) { 21433c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook try { 21443c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook if (messageCursor.moveToFirst()) { 21453c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook // Broadcast notification that a new message has 21463c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook // been allocated 21473c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook mSendOrSaveCallback.notifyMessageIdAllocated(sendOrSaveMessage, 21483c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook new Message(messageCursor)); 21493c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook } 21503c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook } finally { 21513c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook messageCursor.close(); 21523c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook } 21533c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook } 21543c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook } 215572e2ea860f66f496537e37ebc0ddd2c670d4c651Paul Westbrook } 21563c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook } finally { 21573c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook // Close any opened file descriptors 21583c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook closeOpenedAttachmentFds(sendOrSaveMessage); 21593c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook } 21603c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook } 21613c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook 2162ff8553f20964f4c31b0c503a9e1daff6ae08a9c7Scott Kennedy private static void closeOpenedAttachmentFds(final SendOrSaveMessage sendOrSaveMessage) { 21633c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook final Bundle openedFds = sendOrSaveMessage.attachmentFds(); 21643c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook if (openedFds != null) { 21653c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook final Set<String> keys = openedFds.keySet(); 2166ff8553f20964f4c31b0c503a9e1daff6ae08a9c7Scott Kennedy for (final String key : keys) { 21673c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook final ParcelFileDescriptor fd = openedFds.getParcelable(key); 21683c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook if (fd != null) { 2169ba5584836c0a63c8dac96b10b569465bd56d5f7aPaul Westbrook try { 21703c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook fd.close(); 21713c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook } catch (IOException e) { 21723c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook // Do nothing 2173ba5584836c0a63c8dac96b10b569465bd56d5f7aPaul Westbrook } 21747ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira } 21757ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira } 217682cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira } 217772e2ea860f66f496537e37ebc0ddd2c670d4c651Paul Westbrook } 217882cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira 217972e2ea860f66f496537e37ebc0ddd2c670d4c651Paul Westbrook /** 2180bc5e0dcf723918eb986d733ef42d64bcf2ec4ed5Andrew Sapperstein * Use the {@link ContentResolver#call} method to send or save the message. 218172e2ea860f66f496537e37ebc0ddd2c670d4c651Paul Westbrook * 218272e2ea860f66f496537e37ebc0ddd2c670d4c651Paul Westbrook * If this was successful, this method will return an non-null Bundle instance 218372e2ea860f66f496537e37ebc0ddd2c670d4c651Paul Westbrook */ 2184ff8553f20964f4c31b0c503a9e1daff6ae08a9c7Scott Kennedy private static Bundle callAccountSendSaveMethod(final ContentResolver resolver, 2185ff8553f20964f4c31b0c503a9e1daff6ae08a9c7Scott Kennedy final Account account, final String method, 2186ff8553f20964f4c31b0c503a9e1daff6ae08a9c7Scott Kennedy final SendOrSaveMessage sendOrSaveMessage) { 218772e2ea860f66f496537e37ebc0ddd2c670d4c651Paul Westbrook // Copy all of the values from the content values to the bundle 218872e2ea860f66f496537e37ebc0ddd2c670d4c651Paul Westbrook final Bundle methodExtras = new Bundle(sendOrSaveMessage.mValues.size()); 218972e2ea860f66f496537e37ebc0ddd2c670d4c651Paul Westbrook final Set<Entry<String, Object>> valueSet = sendOrSaveMessage.mValues.valueSet(); 219072e2ea860f66f496537e37ebc0ddd2c670d4c651Paul Westbrook 219172e2ea860f66f496537e37ebc0ddd2c670d4c651Paul Westbrook for (Entry<String, Object> entry : valueSet) { 219272e2ea860f66f496537e37ebc0ddd2c670d4c651Paul Westbrook final Object entryValue = entry.getValue(); 219372e2ea860f66f496537e37ebc0ddd2c670d4c651Paul Westbrook final String key = entry.getKey(); 219472e2ea860f66f496537e37ebc0ddd2c670d4c651Paul Westbrook if (entryValue instanceof String) { 219572e2ea860f66f496537e37ebc0ddd2c670d4c651Paul Westbrook methodExtras.putString(key, (String)entryValue); 219672e2ea860f66f496537e37ebc0ddd2c670d4c651Paul Westbrook } else if (entryValue instanceof Boolean) { 219772e2ea860f66f496537e37ebc0ddd2c670d4c651Paul Westbrook methodExtras.putBoolean(key, (Boolean)entryValue); 219872e2ea860f66f496537e37ebc0ddd2c670d4c651Paul Westbrook } else if (entryValue instanceof Integer) { 219972e2ea860f66f496537e37ebc0ddd2c670d4c651Paul Westbrook methodExtras.putInt(key, (Integer)entryValue); 220072e2ea860f66f496537e37ebc0ddd2c670d4c651Paul Westbrook } else if (entryValue instanceof Long) { 220172e2ea860f66f496537e37ebc0ddd2c670d4c651Paul Westbrook methodExtras.putLong(key, (Long)entryValue); 220272e2ea860f66f496537e37ebc0ddd2c670d4c651Paul Westbrook } else { 220372e2ea860f66f496537e37ebc0ddd2c670d4c651Paul Westbrook LogUtils.wtf(LOG_TAG, "Unexpected object type: %s", 220472e2ea860f66f496537e37ebc0ddd2c670d4c651Paul Westbrook entryValue.getClass().getName()); 220572e2ea860f66f496537e37ebc0ddd2c670d4c651Paul Westbrook } 220682cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira } 220772e2ea860f66f496537e37ebc0ddd2c670d4c651Paul Westbrook 22083c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook // If the SendOrSaveMessage has some opened fds, add them to the bundle 22093c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook final Bundle fdMap = sendOrSaveMessage.attachmentFds(); 22103c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook if (fdMap != null) { 22113c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook methodExtras.putParcelable( 22123c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook UIProvider.SendOrSaveMethodParamKeys.OPENED_FD_MAP, fdMap); 22133c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook } 22143c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook 221572e2ea860f66f496537e37ebc0ddd2c670d4c651Paul Westbrook return resolver.call(account.uri, method, account.uri.toString(), methodExtras); 221682cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira } 221782cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira } 221882cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira 2219e011b1d1c8e2e674dfdf1985d9d13da8cc06d803Mindy Pereira @VisibleForTesting 2220e011b1d1c8e2e674dfdf1985d9d13da8cc06d803Mindy Pereira public static class SendOrSaveMessage { 222192551d057965689f1952faeb06763f0762bc717fMindy Pereira final ReplyFromAccount mAccount; 222282cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira final ContentValues mValues; 22233ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereira final String mRefMessageId; 2224e011b1d1c8e2e674dfdf1985d9d13da8cc06d803Mindy Pereira @VisibleForTesting 2225e011b1d1c8e2e674dfdf1985d9d13da8cc06d803Mindy Pereira public final boolean mSave; 222682cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira final int mRequestId; 22273c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook private final Bundle mAttachmentFds; 222882cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira 22293c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook public SendOrSaveMessage(Context context, ReplyFromAccount account, ContentValues values, 22303c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook String refMessageId, List<Attachment> attachments, boolean save) { 223182cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira mAccount = account; 223282cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira mValues = values; 223382cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira mRefMessageId = refMessageId; 223482cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira mSave = save; 223582cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira mRequestId = mValues.hashCode() ^ hashCode(); 22363c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook 22373c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook mAttachmentFds = initializeAttachmentFds(context, attachments); 223882cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira } 223982cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira 224082cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira int requestId() { 224182cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira return mRequestId; 224282cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira } 22433c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook 22443c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook Bundle attachmentFds() { 22453c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook return mAttachmentFds; 22463c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook } 22473c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook 22483c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook /** 22493c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook * Opens {@link ParcelFileDescriptor} for each of the attachments. This method must be 22503c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook * called before the ComposeActivity finishes. 22513c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook * Note: The caller is responsible for closing these file descriptors. 22523c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook */ 2253ff8553f20964f4c31b0c503a9e1daff6ae08a9c7Scott Kennedy private static Bundle initializeAttachmentFds(final Context context, 2254ff8553f20964f4c31b0c503a9e1daff6ae08a9c7Scott Kennedy final List<Attachment> attachments) { 22553c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook if (attachments == null || attachments.size() == 0) { 22563c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook return null; 22573c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook } 22583c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook 22593c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook final Bundle result = new Bundle(attachments.size()); 22603c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook final ContentResolver resolver = context.getContentResolver(); 22613c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook 22623c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook for (Attachment attachment : attachments) { 22633c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook if (attachment == null || Utils.isEmpty(attachment.contentUri)) { 22643c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook continue; 22653c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook } 22663c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook 22673c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook ParcelFileDescriptor fileDescriptor; 22683c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook try { 22693c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook fileDescriptor = resolver.openFileDescriptor(attachment.contentUri, "r"); 22703c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook } catch (FileNotFoundException e) { 22713c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook LogUtils.e(LOG_TAG, e, "Exception attempting to open attachment"); 22723c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook fileDescriptor = null; 2273c537fd4729cb7545d09245bdaad033e676f29396Paul Westbrook } catch (SecurityException e) { 2274c537fd4729cb7545d09245bdaad033e676f29396Paul Westbrook // We have encountered a security exception when attempting to open the file 2275c537fd4729cb7545d09245bdaad033e676f29396Paul Westbrook // specified by the content uri. If the attachment has been cached, this 2276c537fd4729cb7545d09245bdaad033e676f29396Paul Westbrook // isn't a problem, as even through the original permission may have been 2277c537fd4729cb7545d09245bdaad033e676f29396Paul Westbrook // revoked, we have cached the file. This will happen when saving/sending 2278c537fd4729cb7545d09245bdaad033e676f29396Paul Westbrook // a previously saved draft. 2279c537fd4729cb7545d09245bdaad033e676f29396Paul Westbrook // TODO(markwei): Expose whether the attachment has been cached through the 2280c537fd4729cb7545d09245bdaad033e676f29396Paul Westbrook // attachment object. This would allow us to limit when the log is made, as 2281c537fd4729cb7545d09245bdaad033e676f29396Paul Westbrook // if the attachment has been cached, this really isn't an error 2282c537fd4729cb7545d09245bdaad033e676f29396Paul Westbrook LogUtils.e(LOG_TAG, e, "Security Exception attempting to open attachment"); 2283c537fd4729cb7545d09245bdaad033e676f29396Paul Westbrook // Just set the file descriptor to null, as the underlying provider needs 2284c537fd4729cb7545d09245bdaad033e676f29396Paul Westbrook // to handle the file descriptor not being set. 2285c537fd4729cb7545d09245bdaad033e676f29396Paul Westbrook fileDescriptor = null; 22863c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook } 22873c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook 22883c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook if (fileDescriptor != null) { 22893c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook result.putParcelable(attachment.contentUri.toString(), fileDescriptor); 22903c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook } 22913c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook } 22923c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook 22933c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook return result; 22943c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook } 229582cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira } 229682cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira 229782cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira /** 229882cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira * Get the to recipients. 229982cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira */ 230082cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira public String[] getToAddresses() { 230182cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira return getAddressesFromList(mTo); 230282cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira } 230382cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira 230482cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira /** 230582cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira * Get the cc recipients. 230682cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira */ 230782cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira public String[] getCcAddresses() { 230882cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira return getAddressesFromList(mCc); 230982cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira } 231082cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira 231182cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira /** 231282cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira * Get the bcc recipients. 231382cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira */ 231482cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira public String[] getBccAddresses() { 231582cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira return getAddressesFromList(mBcc); 231682cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira } 231782cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira 231882cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira public String[] getAddressesFromList(RecipientEditTextView list) { 231982cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira if (list == null) { 232082cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira return new String[0]; 232182cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira } 232282cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira Rfc822Token[] tokens = Rfc822Tokenizer.tokenize(list.getText()); 232382cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira int count = tokens.length; 232482cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira String[] result = new String[count]; 232582cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira for (int i = 0; i < count; i++) { 232682cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira result[i] = tokens[i].toString(); 232782cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira } 232882cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira return result; 232982cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira } 233082cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira 233182cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira /** 233282cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira * Check for invalid email addresses. 233382cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira * @param to String array of email addresses to check. 233482cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira * @param wrongEmailsOut Emails addresses that were invalid. 233582cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira */ 2336ff8553f20964f4c31b0c503a9e1daff6ae08a9c7Scott Kennedy public void checkInvalidEmails(final String[] to, final List<String> wrongEmailsOut) { 2337e5f20bf1c293497625b0f2865302e6712a854959Mindy Pereira if (mValidator == null) { 2338e5f20bf1c293497625b0f2865302e6712a854959Mindy Pereira return; 2339e5f20bf1c293497625b0f2865302e6712a854959Mindy Pereira } 2340ff8553f20964f4c31b0c503a9e1daff6ae08a9c7Scott Kennedy for (final String email : to) { 234182cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira if (!mValidator.isValid(email)) { 234282cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira wrongEmailsOut.add(email); 234382cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira } 234482cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira } 234582cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira } 234682cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira 23472558b509117872e539a6eaeb72aa63425529d50bTony Mantler public static class RecipientErrorDialogFragment extends DialogFragment { 2348f0ea4849bf7a2c11f99ca0b42307ae8ba665b1dcPaul Westbrook // Public no-args constructor needed for fragment re-instantiation 2349f0ea4849bf7a2c11f99ca0b42307ae8ba665b1dcPaul Westbrook public RecipientErrorDialogFragment() {} 2350f0ea4849bf7a2c11f99ca0b42307ae8ba665b1dcPaul Westbrook 23512558b509117872e539a6eaeb72aa63425529d50bTony Mantler public static RecipientErrorDialogFragment newInstance(final String message) { 23522558b509117872e539a6eaeb72aa63425529d50bTony Mantler final RecipientErrorDialogFragment frag = new RecipientErrorDialogFragment(); 23532558b509117872e539a6eaeb72aa63425529d50bTony Mantler final Bundle args = new Bundle(1); 23542558b509117872e539a6eaeb72aa63425529d50bTony Mantler args.putString("message", message); 23552558b509117872e539a6eaeb72aa63425529d50bTony Mantler frag.setArguments(args); 23562558b509117872e539a6eaeb72aa63425529d50bTony Mantler return frag; 23572558b509117872e539a6eaeb72aa63425529d50bTony Mantler } 23582558b509117872e539a6eaeb72aa63425529d50bTony Mantler 23592558b509117872e539a6eaeb72aa63425529d50bTony Mantler @Override 23602558b509117872e539a6eaeb72aa63425529d50bTony Mantler public Dialog onCreateDialog(Bundle savedInstanceState) { 23612558b509117872e539a6eaeb72aa63425529d50bTony Mantler final String message = getArguments().getString("message"); 23622558b509117872e539a6eaeb72aa63425529d50bTony Mantler return new AlertDialog.Builder(getActivity()).setMessage(message).setTitle( 23632558b509117872e539a6eaeb72aa63425529d50bTony Mantler R.string.recipient_error_dialog_title) 23642558b509117872e539a6eaeb72aa63425529d50bTony Mantler .setIconAttribute(android.R.attr.alertDialogIcon) 23652558b509117872e539a6eaeb72aa63425529d50bTony Mantler .setPositiveButton( 23662558b509117872e539a6eaeb72aa63425529d50bTony Mantler R.string.ok, new Dialog.OnClickListener() { 23672558b509117872e539a6eaeb72aa63425529d50bTony Mantler @Override 23682558b509117872e539a6eaeb72aa63425529d50bTony Mantler public void onClick(DialogInterface dialog, int which) { 23692558b509117872e539a6eaeb72aa63425529d50bTony Mantler ((ComposeActivity)getActivity()).finishRecipientErrorDialog(); 23702558b509117872e539a6eaeb72aa63425529d50bTony Mantler } 23712558b509117872e539a6eaeb72aa63425529d50bTony Mantler }).create(); 23722558b509117872e539a6eaeb72aa63425529d50bTony Mantler } 23732558b509117872e539a6eaeb72aa63425529d50bTony Mantler } 23742558b509117872e539a6eaeb72aa63425529d50bTony Mantler 23752558b509117872e539a6eaeb72aa63425529d50bTony Mantler private void finishRecipientErrorDialog() { 23762558b509117872e539a6eaeb72aa63425529d50bTony Mantler // after the user dismisses the recipient error 23772558b509117872e539a6eaeb72aa63425529d50bTony Mantler // dialog we want to make sure to refocus the 23782558b509117872e539a6eaeb72aa63425529d50bTony Mantler // recipient to field so they can fix the issue 23792558b509117872e539a6eaeb72aa63425529d50bTony Mantler // easily 23802558b509117872e539a6eaeb72aa63425529d50bTony Mantler if (mTo != null) { 23812558b509117872e539a6eaeb72aa63425529d50bTony Mantler mTo.requestFocus(); 23822558b509117872e539a6eaeb72aa63425529d50bTony Mantler } 23832558b509117872e539a6eaeb72aa63425529d50bTony Mantler } 23842558b509117872e539a6eaeb72aa63425529d50bTony Mantler 238582cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira /** 238682cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira * Show an error because the user has entered an invalid recipient. 238782cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira * @param message 238882cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira */ 23892558b509117872e539a6eaeb72aa63425529d50bTony Mantler private void showRecipientErrorDialog(final String message) { 23902558b509117872e539a6eaeb72aa63425529d50bTony Mantler final DialogFragment frag = RecipientErrorDialogFragment.newInstance(message); 23912558b509117872e539a6eaeb72aa63425529d50bTony Mantler frag.show(getFragmentManager(), "recipient error"); 239282cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira } 239382cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira 239482cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira /** 239582cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira * Update the state of the UI based on whether or not the current draft 239682cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira * needs to be saved and the message is not empty. 239782cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira */ 2398eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira public void updateSaveUi() { 239982cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira if (mSave != null) { 240082cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira mSave.setEnabled((shouldSave() && !isBlank())); 240182cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira } 240282cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira } 240382cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira 240482cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira /** 240582cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira * Returns true if we need to save the current draft. 240682cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira */ 240782cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira private boolean shouldSave() { 24087ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira synchronized (mDraftLock) { 240982cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira // The message should only be saved if: 241082cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira // It hasn't been sent AND 241182cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira // Some text has been added to the message OR 241282cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira // an attachment has been added or removed 2413a214833a75ba2b27cdd166ceee9a2529b13a17c4Mindy Pereira // AND there is actually something in the draft to save. 2414d47877e3860ea4249eddb3f6efefbc6cd39f2320Andy Huang return (mTextChanged || mAttachmentsChanged || mReplyFromChanged) 2415a214833a75ba2b27cdd166ceee9a2529b13a17c4Mindy Pereira && !isBlank(); 241682cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira } 241782cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira } 241882cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira 241982cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira /** 2420bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira * Check if all fields are blank. 242182cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira * @return boolean 242282cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira */ 242382cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira public boolean isBlank() { 242482cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira return mSubject.getText().length() == 0 2425bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira && (mBodyView.getText().length() == 0 || getSignatureStartPosition(mSignature, 2426bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira mBodyView.getText().toString()) == 0) 2427bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira && mTo.length() == 0 2428bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira && mCc.length() == 0 && mBcc.length() == 0 2429bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira && mAttachmentsView.getAttachments().size() == 0; 2430bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira } 2431bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira 2432bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira @VisibleForTesting 2433bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira protected int getSignatureStartPosition(String signature, String bodyText) { 2434bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira int startPos = -1; 2435bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira 2436bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira if (TextUtils.isEmpty(signature) || TextUtils.isEmpty(bodyText)) { 2437bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira return startPos; 2438bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira } 2439bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira 2440bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira int bodyLength = bodyText.length(); 2441bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira int signatureLength = signature.length(); 2442bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira String printableVersion = convertToPrintableSignature(signature); 2443bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira int printableLength = printableVersion.length(); 2444bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira 2445bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira if (bodyLength >= printableLength 2446bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira && bodyText.substring(bodyLength - printableLength) 2447bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira .equals(printableVersion)) { 2448bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira startPos = bodyLength - printableLength; 2449bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira } else if (bodyLength >= signatureLength 2450bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira && bodyText.substring(bodyLength - signatureLength) 2451bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira .equals(signature)) { 2452bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira startPos = bodyLength - signatureLength; 2453bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira } 2454bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira return startPos; 245582cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira } 245682cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira 245782cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira /** 245882cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira * Allows any changes made by the user to be ignored. Called when the user 245982cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira * decides to discard a draft. 246082cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira */ 246182cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira private void discardChanges() { 246282cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira mTextChanged = false; 2463eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira mAttachmentsChanged = false; 246482cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira mReplyFromChanged = false; 246533fe908589dca6a7f58aa9f56d73f74a48ac42f6Mindy Pereira } 246633fe908589dca6a7f58aa9f56d73f74a48ac42f6Mindy Pereira 246782cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira /** 2468181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira * @param save 2469181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira * @param showToast 2470181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira * @return Whether the send or save succeeded. 2471181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira */ 2472181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira protected boolean sendOrSaveWithSanityChecks(final boolean save, final boolean showToast, 2473dd19b63d3f560aba8962435ed5a2e1f5ae794351Mark Wei final boolean orientationChanged, final boolean autoSend) { 2474009b3712ff1657fa839049826451321fdd938d32Mark Wei if (mAccounts == null || mAccount == null) { 2475009b3712ff1657fa839049826451321fdd938d32Mark Wei Toast.makeText(this, R.string.send_failed, Toast.LENGTH_SHORT).show(); 2476dd19b63d3f560aba8962435ed5a2e1f5ae794351Mark Wei if (autoSend) { 2477dd19b63d3f560aba8962435ed5a2e1f5ae794351Mark Wei finish(); 2478dd19b63d3f560aba8962435ed5a2e1f5ae794351Mark Wei } 2479009b3712ff1657fa839049826451321fdd938d32Mark Wei return false; 2480009b3712ff1657fa839049826451321fdd938d32Mark Wei } 2481009b3712ff1657fa839049826451321fdd938d32Mark Wei 2482ff8553f20964f4c31b0c503a9e1daff6ae08a9c7Scott Kennedy final String[] to, cc, bcc; 2483181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira if (orientationChanged) { 2484181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira to = cc = bcc = new String[0]; 2485181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira } else { 2486181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira to = getToAddresses(); 2487181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira cc = getCcAddresses(); 2488181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira bcc = getBccAddresses(); 2489181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira } 2490181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira 2491181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira // Don't let the user send to nobody (but it's okay to save a message 2492181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira // with no recipients) 2493181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira if (!save && (to.length == 0 && cc.length == 0 && bcc.length == 0)) { 2494181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira showRecipientErrorDialog(getString(R.string.recipient_needed)); 2495181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira return false; 2496181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira } 2497181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira 2498181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira List<String> wrongEmails = new ArrayList<String>(); 2499181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira if (!save) { 2500181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira checkInvalidEmails(to, wrongEmails); 2501181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira checkInvalidEmails(cc, wrongEmails); 2502181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira checkInvalidEmails(bcc, wrongEmails); 2503181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira } 2504181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira 2505181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira // Don't let the user send an email with invalid recipients 2506181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira if (wrongEmails.size() > 0) { 2507181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira String errorText = String.format(getString(R.string.invalid_recipient), 2508181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira wrongEmails.get(0)); 2509181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira showRecipientErrorDialog(errorText); 2510181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira return false; 2511181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira } 2512181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira 2513181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira // Show a warning before sending only if there are no attachments. 2514181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira if (!save) { 2515181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira if (mAttachmentsView.getAttachments().isEmpty() && showEmptyTextWarnings()) { 2516181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira boolean warnAboutEmptySubject = isSubjectEmpty(); 25172558b509117872e539a6eaeb72aa63425529d50bTony Mantler boolean emptyBody = TextUtils.getTrimmedLength(mBodyView.getEditableText()) == 0; 2518181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira 2519181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira // A warning about an empty body may not be warranted when 2520181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira // forwarding mails, since a common use case is to forward 2521181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira // quoted text and not append any more text. 2522181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira boolean warnAboutEmptyBody = emptyBody && (!mForward || isBodyEmpty()); 2523181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira 2524181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira // When we bring up a dialog warning the user about a send, 2525181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira // assume that they accept sending the message. If they do not, 2526181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira // the dialog listener is required to enable sending again. 2527181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira if (warnAboutEmptySubject) { 25282558b509117872e539a6eaeb72aa63425529d50bTony Mantler showSendConfirmDialog(R.string.confirm_send_message_with_no_subject, save, 25292558b509117872e539a6eaeb72aa63425529d50bTony Mantler showToast); 2530181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira return true; 2531181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira } 2532181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira 2533181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira if (warnAboutEmptyBody) { 25342558b509117872e539a6eaeb72aa63425529d50bTony Mantler showSendConfirmDialog(R.string.confirm_send_message_with_no_body, save, 25352558b509117872e539a6eaeb72aa63425529d50bTony Mantler showToast); 2536181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira return true; 2537181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira } 2538181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira } 2539181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira // Ask for confirmation to send (if always required) 2540181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira if (showSendConfirmation()) { 25412558b509117872e539a6eaeb72aa63425529d50bTony Mantler showSendConfirmDialog(R.string.confirm_send_message, save, showToast); 2542181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira return true; 2543181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira } 2544181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira } 2545181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira 25462558b509117872e539a6eaeb72aa63425529d50bTony Mantler sendOrSave(save, showToast); 2547181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira return true; 2548181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira } 2549181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira 2550181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira /** 2551181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira * Returns a boolean indicating whether warnings should be shown for empty 2552181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira * subject and body fields 25535c5fd571b40a15b95ea5a5d6033f377706ffd0fbAndy Huang * 2554181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira * @return True if a warning should be shown for empty text fields 2555181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira */ 2556181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira protected boolean showEmptyTextWarnings() { 2557181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira return mAttachmentsView.getAttachments().size() == 0; 2558181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira } 2559181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira 2560181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira /** 2561181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira * Returns a boolean indicating whether the user should confirm each send 2562181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira * 2563181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira * @return True if a warning should be on each send 2564181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira */ 2565181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira protected boolean showSendConfirmation() { 2566181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira return mCachedSettings != null ? mCachedSettings.confirmSend : false; 2567181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira } 2568181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira 25692558b509117872e539a6eaeb72aa63425529d50bTony Mantler public static class SendConfirmDialogFragment extends DialogFragment { 2570f0ea4849bf7a2c11f99ca0b42307ae8ba665b1dcPaul Westbrook // Public no-args constructor needed for fragment re-instantiation 2571f0ea4849bf7a2c11f99ca0b42307ae8ba665b1dcPaul Westbrook public SendConfirmDialogFragment() {} 2572f0ea4849bf7a2c11f99ca0b42307ae8ba665b1dcPaul Westbrook 25732558b509117872e539a6eaeb72aa63425529d50bTony Mantler public static SendConfirmDialogFragment newInstance(final int messageId, 25742558b509117872e539a6eaeb72aa63425529d50bTony Mantler final boolean save, final boolean showToast) { 25752558b509117872e539a6eaeb72aa63425529d50bTony Mantler final SendConfirmDialogFragment frag = new SendConfirmDialogFragment(); 25762558b509117872e539a6eaeb72aa63425529d50bTony Mantler final Bundle args = new Bundle(3); 25772558b509117872e539a6eaeb72aa63425529d50bTony Mantler args.putInt("messageId", messageId); 25782558b509117872e539a6eaeb72aa63425529d50bTony Mantler args.putBoolean("save", save); 25792558b509117872e539a6eaeb72aa63425529d50bTony Mantler args.putBoolean("showToast", showToast); 25802558b509117872e539a6eaeb72aa63425529d50bTony Mantler frag.setArguments(args); 25812558b509117872e539a6eaeb72aa63425529d50bTony Mantler return frag; 2582181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira } 25832558b509117872e539a6eaeb72aa63425529d50bTony Mantler 25842558b509117872e539a6eaeb72aa63425529d50bTony Mantler @Override 25852558b509117872e539a6eaeb72aa63425529d50bTony Mantler public Dialog onCreateDialog(Bundle savedInstanceState) { 25862558b509117872e539a6eaeb72aa63425529d50bTony Mantler final int messageId = getArguments().getInt("messageId"); 25872558b509117872e539a6eaeb72aa63425529d50bTony Mantler final boolean save = getArguments().getBoolean("save"); 25882558b509117872e539a6eaeb72aa63425529d50bTony Mantler final boolean showToast = getArguments().getBoolean("showToast"); 25892558b509117872e539a6eaeb72aa63425529d50bTony Mantler 25902558b509117872e539a6eaeb72aa63425529d50bTony Mantler return new AlertDialog.Builder(getActivity()) 25912558b509117872e539a6eaeb72aa63425529d50bTony Mantler .setMessage(messageId) 25922558b509117872e539a6eaeb72aa63425529d50bTony Mantler .setTitle(R.string.confirm_send_title) 25932558b509117872e539a6eaeb72aa63425529d50bTony Mantler .setIconAttribute(android.R.attr.alertDialogIcon) 25942558b509117872e539a6eaeb72aa63425529d50bTony Mantler .setPositiveButton(R.string.send, 25952558b509117872e539a6eaeb72aa63425529d50bTony Mantler new DialogInterface.OnClickListener() { 2596aa27bc0e1c3bb6be4609b00007637a9d3e960f5eScott Kennedy @Override 25972558b509117872e539a6eaeb72aa63425529d50bTony Mantler public void onClick(DialogInterface dialog, int whichButton) { 25982558b509117872e539a6eaeb72aa63425529d50bTony Mantler ((ComposeActivity)getActivity()).finishSendConfirmDialog(save, 25992558b509117872e539a6eaeb72aa63425529d50bTony Mantler showToast); 26002558b509117872e539a6eaeb72aa63425529d50bTony Mantler } 26012558b509117872e539a6eaeb72aa63425529d50bTony Mantler }) 26022558b509117872e539a6eaeb72aa63425529d50bTony Mantler .create(); 26032558b509117872e539a6eaeb72aa63425529d50bTony Mantler } 26042558b509117872e539a6eaeb72aa63425529d50bTony Mantler } 26052558b509117872e539a6eaeb72aa63425529d50bTony Mantler 26062558b509117872e539a6eaeb72aa63425529d50bTony Mantler private void finishSendConfirmDialog(final boolean save, final boolean showToast) { 26072558b509117872e539a6eaeb72aa63425529d50bTony Mantler sendOrSave(save, showToast); 26082558b509117872e539a6eaeb72aa63425529d50bTony Mantler } 26092558b509117872e539a6eaeb72aa63425529d50bTony Mantler 26102558b509117872e539a6eaeb72aa63425529d50bTony Mantler private void showSendConfirmDialog(final int messageId, final boolean save, 26112558b509117872e539a6eaeb72aa63425529d50bTony Mantler final boolean showToast) { 26122558b509117872e539a6eaeb72aa63425529d50bTony Mantler final DialogFragment frag = SendConfirmDialogFragment.newInstance(messageId, save, 26132558b509117872e539a6eaeb72aa63425529d50bTony Mantler showToast); 26142558b509117872e539a6eaeb72aa63425529d50bTony Mantler frag.show(getFragmentManager(), "send confirm"); 2615181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira } 2616181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira 2617181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira /** 2618181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira * Returns whether the ComposeArea believes there is any text in the body of 2619181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira * the composition. TODO: When ComposeArea controls the Body as well, add 2620181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira * that here. 2621181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira */ 2622181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira public boolean isBodyEmpty() { 2623181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira return !mQuotedTextView.isTextIncluded(); 2624181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira } 2625181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira 2626181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira /** 2627181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira * Test to see if the subject is empty. 2628181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira * 2629181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira * @return boolean. 2630181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira */ 2631181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira // TODO: this will likely go away when composeArea.focus() is implemented 2632181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira // after all the widget control is moved over. 2633181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira public boolean isSubjectEmpty() { 2634181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira return TextUtils.getTrimmedLength(mSubject.getText()) == 0; 2635181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira } 2636181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira 2637181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira /* package */ 2638e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira static int sendOrSaveInternal(Context context, ReplyFromAccount replyFromAccount, 263905b92b8ff275f85edae525623c71b65805ca3a51Paul Westbrook Message message, final Message refMessage, Spanned body, final CharSequence quotedText, 264044a6339dd80f4b5b9e5d54567021698d92467c5emindyp SendOrSaveCallback callback, Handler handler, boolean save, int composeMode, 264160847256c691b2677772a46919038f9c600fecf7Scott Kennedy ReplyFromAccount draftAccount, final ContentValues extraValues) { 2642b4931c62bffec463df9c3871d83a35bbeb9d5920Paul Westbrook final ContentValues values = new ContentValues(); 264329ef1b89b158281ffb693dd5f2c5291a894109fcMindy Pereira 2644b4931c62bffec463df9c3871d83a35bbeb9d5920Paul Westbrook final String refMessageId = refMessage != null ? refMessage.uri.toString() : ""; 2645c203197908a95f707e93621e5eb5f0fb8bfc7d1fMindy Pereira 2646e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira MessageModification.putToAddresses(values, message.getToAddresses()); 2647e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira MessageModification.putCcAddresses(values, message.getCcAddresses()); 2648e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira MessageModification.putBccAddresses(values, message.getBccAddresses()); 264929ef1b89b158281ffb693dd5f2c5291a894109fcMindy Pereira 26508960f0af431bc164003e09b3c8981aab808d9ec1Scott Kennedy MessageModification.putCustomFromAddress(values, message.getFrom()); 265192551d057965689f1952faeb06763f0762bc717fMindy Pereira 2652e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira MessageModification.putSubject(values, message.subject); 2653b4931c62bffec463df9c3871d83a35bbeb9d5920Paul Westbrook // Make sure to remove only the composing spans from the Spannable before saving. 2654b4931c62bffec463df9c3871d83a35bbeb9d5920Paul Westbrook final String htmlBody = Html.toHtml(removeComposingSpans(body)); 265505b92b8ff275f85edae525623c71b65805ca3a51Paul Westbrook 265629ef1b89b158281ffb693dd5f2c5291a894109fcMindy Pereira boolean includeQuotedText = !TextUtils.isEmpty(quotedText); 265729ef1b89b158281ffb693dd5f2c5291a894109fcMindy Pereira StringBuilder fullBody = new StringBuilder(htmlBody); 265829ef1b89b158281ffb693dd5f2c5291a894109fcMindy Pereira if (includeQuotedText) { 2659e8caf1279a1c6ae720215405f678172a5cbf68d7Mindy Pereira // HTML gets converted to text for now 2660e8caf1279a1c6ae720215405f678172a5cbf68d7Mindy Pereira final String text = quotedText.toString(); 2661e8caf1279a1c6ae720215405f678172a5cbf68d7Mindy Pereira if (QuotedTextView.containsQuotedText(text)) { 2662e8caf1279a1c6ae720215405f678172a5cbf68d7Mindy Pereira int pos = QuotedTextView.getQuotedTextOffset(text); 266355271cf624269a5a19bb1989e5904df7adec7ef7Paul Westbrook final int quoteStartPos = fullBody.length() + pos; 266455271cf624269a5a19bb1989e5904df7adec7ef7Paul Westbrook fullBody.append(text); 266555271cf624269a5a19bb1989e5904df7adec7ef7Paul Westbrook MessageModification.putQuoteStartPos(values, quoteStartPos); 266612575866e5526e45eaf773c6c98c93c3a06fe156Mindy Pereira MessageModification.putForward(values, composeMode == ComposeActivity.FORWARD); 2667e8caf1279a1c6ae720215405f678172a5cbf68d7Mindy Pereira MessageModification.putAppendRefMessageContent(values, includeQuotedText); 266829ef1b89b158281ffb693dd5f2c5291a894109fcMindy Pereira } else { 2669e8caf1279a1c6ae720215405f678172a5cbf68d7Mindy Pereira LogUtils.w(LOG_TAG, "Couldn't find quoted text"); 2670e8caf1279a1c6ae720215405f678172a5cbf68d7Mindy Pereira // This shouldn't happen, but just use what we have, 2671e8caf1279a1c6ae720215405f678172a5cbf68d7Mindy Pereira // and don't do server-side expansion 2672e8caf1279a1c6ae720215405f678172a5cbf68d7Mindy Pereira fullBody.append(text); 267329ef1b89b158281ffb693dd5f2c5291a894109fcMindy Pereira } 267429ef1b89b158281ffb693dd5f2c5291a894109fcMindy Pereira } 2675002ff5244800c32f2d70c96cc1110657020ee65cMindy Pereira int draftType = getDraftType(composeMode); 267612575866e5526e45eaf773c6c98c93c3a06fe156Mindy Pereira MessageModification.putDraftType(values, draftType); 2677c6f1e2a8690bd3d4722a2e9386cdc98691135063Mindy Pereira if (refMessage != null) { 2678c6f1e2a8690bd3d4722a2e9386cdc98691135063Mindy Pereira if (!TextUtils.isEmpty(refMessage.bodyHtml)) { 2679c6f1e2a8690bd3d4722a2e9386cdc98691135063Mindy Pereira MessageModification.putBodyHtml(values, fullBody.toString()); 2680c6f1e2a8690bd3d4722a2e9386cdc98691135063Mindy Pereira } 2681c6f1e2a8690bd3d4722a2e9386cdc98691135063Mindy Pereira if (!TextUtils.isEmpty(refMessage.bodyText)) { 2682c59dd8270215f97d39697dae9e69976bcfe3642bmindyp MessageModification.putBody(values, 2683c59dd8270215f97d39697dae9e69976bcfe3642bmindyp Utils.convertHtmlToPlainText(fullBody.toString()).toString()); 2684c6f1e2a8690bd3d4722a2e9386cdc98691135063Mindy Pereira } 2685c6f1e2a8690bd3d4722a2e9386cdc98691135063Mindy Pereira } else { 2686c203197908a95f707e93621e5eb5f0fb8bfc7d1fMindy Pereira MessageModification.putBodyHtml(values, fullBody.toString()); 2687c59dd8270215f97d39697dae9e69976bcfe3642bmindyp MessageModification.putBody(values, Utils.convertHtmlToPlainText(fullBody.toString()) 2688c59dd8270215f97d39697dae9e69976bcfe3642bmindyp .toString()); 2689c203197908a95f707e93621e5eb5f0fb8bfc7d1fMindy Pereira } 2690e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira MessageModification.putAttachments(values, message.getAttachments()); 269112575866e5526e45eaf773c6c98c93c3a06fe156Mindy Pereira if (!TextUtils.isEmpty(refMessageId)) { 269212575866e5526e45eaf773c6c98c93c3a06fe156Mindy Pereira MessageModification.putRefMessageId(values, refMessageId); 269312575866e5526e45eaf773c6c98c93c3a06fe156Mindy Pereira } 269460847256c691b2677772a46919038f9c600fecf7Scott Kennedy if (extraValues != null) { 269560847256c691b2677772a46919038f9c600fecf7Scott Kennedy values.putAll(extraValues); 269660847256c691b2677772a46919038f9c600fecf7Scott Kennedy } 26973c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook SendOrSaveMessage sendOrSaveMessage = new SendOrSaveMessage(context, replyFromAccount, 26983c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook values, refMessageId, message.getAttachments(), save); 269944a6339dd80f4b5b9e5d54567021698d92467c5emindyp SendOrSaveTask sendOrSaveTask = new SendOrSaveTask(context, sendOrSaveMessage, callback, 270044a6339dd80f4b5b9e5d54567021698d92467c5emindyp draftAccount); 270182cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira 2702181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira callback.initializeSendOrSave(sendOrSaveTask); 2703181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira // Do the send/save action on the specified handler to avoid possible 2704181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira // ANRs 2705181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira handler.post(sendOrSaveTask); 270682cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira 2707181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira return sendOrSaveMessage.requestId(); 2708181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira } 270982cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira 2710b4931c62bffec463df9c3871d83a35bbeb9d5920Paul Westbrook /** 2711b4931c62bffec463df9c3871d83a35bbeb9d5920Paul Westbrook * Removes any composing spans from the specified string. This will create a new 2712b4931c62bffec463df9c3871d83a35bbeb9d5920Paul Westbrook * SpannableString instance, as to not modify the behavior of the EditText view. 2713b4931c62bffec463df9c3871d83a35bbeb9d5920Paul Westbrook */ 2714b4931c62bffec463df9c3871d83a35bbeb9d5920Paul Westbrook private static SpannableString removeComposingSpans(Spanned body) { 2715b4931c62bffec463df9c3871d83a35bbeb9d5920Paul Westbrook final SpannableString messageBody = new SpannableString(body); 2716b4931c62bffec463df9c3871d83a35bbeb9d5920Paul Westbrook BaseInputConnection.removeComposingSpans(messageBody); 2717b4931c62bffec463df9c3871d83a35bbeb9d5920Paul Westbrook return messageBody; 2718b4931c62bffec463df9c3871d83a35bbeb9d5920Paul Westbrook } 2719b4931c62bffec463df9c3871d83a35bbeb9d5920Paul Westbrook 2720002ff5244800c32f2d70c96cc1110657020ee65cMindy Pereira private static int getDraftType(int mode) { 2721002ff5244800c32f2d70c96cc1110657020ee65cMindy Pereira int draftType = -1; 2722002ff5244800c32f2d70c96cc1110657020ee65cMindy Pereira switch (mode) { 2723002ff5244800c32f2d70c96cc1110657020ee65cMindy Pereira case ComposeActivity.COMPOSE: 2724002ff5244800c32f2d70c96cc1110657020ee65cMindy Pereira draftType = DraftType.COMPOSE; 2725002ff5244800c32f2d70c96cc1110657020ee65cMindy Pereira break; 2726002ff5244800c32f2d70c96cc1110657020ee65cMindy Pereira case ComposeActivity.REPLY: 2727002ff5244800c32f2d70c96cc1110657020ee65cMindy Pereira draftType = DraftType.REPLY; 2728002ff5244800c32f2d70c96cc1110657020ee65cMindy Pereira break; 2729002ff5244800c32f2d70c96cc1110657020ee65cMindy Pereira case ComposeActivity.REPLY_ALL: 2730002ff5244800c32f2d70c96cc1110657020ee65cMindy Pereira draftType = DraftType.REPLY_ALL; 2731002ff5244800c32f2d70c96cc1110657020ee65cMindy Pereira break; 2732002ff5244800c32f2d70c96cc1110657020ee65cMindy Pereira case ComposeActivity.FORWARD: 2733002ff5244800c32f2d70c96cc1110657020ee65cMindy Pereira draftType = DraftType.FORWARD; 2734002ff5244800c32f2d70c96cc1110657020ee65cMindy Pereira break; 2735002ff5244800c32f2d70c96cc1110657020ee65cMindy Pereira } 2736002ff5244800c32f2d70c96cc1110657020ee65cMindy Pereira return draftType; 2737002ff5244800c32f2d70c96cc1110657020ee65cMindy Pereira } 2738002ff5244800c32f2d70c96cc1110657020ee65cMindy Pereira 27392558b509117872e539a6eaeb72aa63425529d50bTony Mantler private void sendOrSave(final boolean save, final boolean showToast) { 2740181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira // Check if user is a monkey. Monkeys can compose and hit send 2741181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira // button but are not allowed to send anything off the device. 27423ae824c79ffba25b0cda8b0300f41a28cfbfca7fPaul Westbrook if (ActivityManager.isUserAMonkey()) { 2743181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira return; 2744181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira } 274582cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira 27462558b509117872e539a6eaeb72aa63425529d50bTony Mantler final Spanned body = mBodyView.getEditableText(); 27472558b509117872e539a6eaeb72aa63425529d50bTony Mantler 2748181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira SendOrSaveCallback callback = new SendOrSaveCallback() { 27491f8f4dd8c53e6c18ae642235335ce492c9d1e520Andy Huang // FIXME: unused 275082cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira private int mRestoredRequestId; 275182cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira 27520bbc858506c95005f2840fa5dff495a9216d2665Marc Blank @Override 275382cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira public void initializeSendOrSave(SendOrSaveTask sendOrSaveTask) { 2754181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira synchronized (mActiveTasks) { 2755181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira int numTasks = mActiveTasks.size(); 2756181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira if (numTasks == 0) { 2757181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira // Start service so we won't be killed if this app is 2758181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira // put in the background. 2759181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira startService(new Intent(ComposeActivity.this, EmptyService.class)); 2760181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira } 2761181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira 2762181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira mActiveTasks.add(sendOrSaveTask); 2763181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira } 2764181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira if (sTestSendOrSaveCallback != null) { 2765181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira sTestSendOrSaveCallback.initializeSendOrSave(sendOrSaveTask); 2766181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira } 2767181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira } 276882cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira 27690bbc858506c95005f2840fa5dff495a9216d2665Marc Blank @Override 27707ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira public void notifyMessageIdAllocated(SendOrSaveMessage sendOrSaveMessage, 27717ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira Message message) { 2772181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira synchronized (mDraftLock) { 277344a6339dd80f4b5b9e5d54567021698d92467c5emindyp mDraftAccount = sendOrSaveMessage.mAccount; 2774181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira mDraftId = message.id; 2775181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira mDraft = message; 27767ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira if (sRequestMessageIdMap != null) { 27777ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira sRequestMessageIdMap.put(sendOrSaveMessage.requestId(), mDraftId); 27787ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira } 2779181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira // Cache request message map, in case the process is killed 2780181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira saveRequestMap(); 2781181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira } 2782181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira if (sTestSendOrSaveCallback != null) { 27837ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira sTestSendOrSaveCallback.notifyMessageIdAllocated(sendOrSaveMessage, message); 2784181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira } 2785181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira } 278682cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira 27870bbc858506c95005f2840fa5dff495a9216d2665Marc Blank @Override 27887ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira public Message getMessage() { 27897ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira synchronized (mDraftLock) { 27907ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira return mDraft; 27917ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira } 27927ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira } 279382cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira 27940bbc858506c95005f2840fa5dff495a9216d2665Marc Blank @Override 27957ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira public void sendOrSaveFinished(SendOrSaveTask task, boolean success) { 279647d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereira // Update the last sent from account. 279747d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereira if (mAccount != null) { 279847d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereira MailAppProvider.getInstance().setLastSentFromAccount(mAccount.uri.toString()); 279947d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereira } 28007ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira if (success) { 28017ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira // Successfully sent or saved so reset change markers 28027ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira discardChanges(); 28037ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira } else { 28047ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira // A failure happened with saving/sending the draft 28057ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira // TODO(pwestbro): add a better string that should be used 28067ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira // when failing to send or save 28077ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira Toast.makeText(ComposeActivity.this, R.string.send_failed, Toast.LENGTH_SHORT) 28087ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira .show(); 28097ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira } 281082cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira 28117ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira int numTasks; 28127ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira synchronized (mActiveTasks) { 28137ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira // Remove the task from the list of active tasks 28147ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira mActiveTasks.remove(task); 28157ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira numTasks = mActiveTasks.size(); 28167ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira } 281782cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira 28187ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira if (numTasks == 0) { 28197ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira // Stop service so we can be killed. 28207ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira stopService(new Intent(ComposeActivity.this, EmptyService.class)); 28217ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira } 28227ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira if (sTestSendOrSaveCallback != null) { 28237ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira sTestSendOrSaveCallback.sendOrSaveFinished(task, success); 28247ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira } 28257ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira } 2826181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira }; 2827181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira 28281e05a1eedd720aac611c6402c3655ec92c23a43bTony Mantler setAccount(mReplyFromAccount.account); 2829181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira 2830181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira if (mSendSaveTaskHandler == null) { 2831181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira HandlerThread handlerThread = new HandlerThread("Send Message Task Thread"); 2832181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira handlerThread.start(); 2833181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira 2834181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira mSendSaveTaskHandler = new Handler(handlerThread.getLooper()); 2835181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira } 2836181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira 2837e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira Message msg = createMessage(mReplyFromAccount, getMode()); 283805b92b8ff275f85edae525623c71b65805ca3a51Paul Westbrook mRequestId = sendOrSaveInternal(this, mReplyFromAccount, msg, mRefMessage, body, 283905b92b8ff275f85edae525623c71b65805ca3a51Paul Westbrook mQuotedTextView.getQuotedTextIfIncluded(), callback, 284060847256c691b2677772a46919038f9c600fecf7Scott Kennedy mSendSaveTaskHandler, save, mComposeMode, mDraftAccount, mExtraValues); 2841181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira 2842181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira // Don't display the toast if the user is just changing the orientation, 2843181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira // but we still need to save the draft to the cursor because this is how we restore 2844181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira // the attachments when the configuration change completes. 2845181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira if (showToast && (getChangingConfigurations() & ActivityInfo.CONFIG_ORIENTATION) == 0) { 2846181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira Toast.makeText(this, save ? R.string.message_saved : R.string.sending_message, 2847181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira Toast.LENGTH_LONG).show(); 2848181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira } 2849181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira 2850181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira // Need to update variables here because the send or save completes 2851181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira // asynchronously even though the toast shows right away. 2852181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira discardChanges(); 2853181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira updateSaveUi(); 2854181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira 2855181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira // If we are sending, finish the activity 2856181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira if (!save) { 2857181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira finish(); 2858181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira } 2859181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira } 2860181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira 2861181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira /** 2862181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira * Save the state of the request messageid map. This allows for the Gmail 2863181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira * process to be killed, but and still allow for ComposeActivity instances 2864181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira * to be recreated correctly. 2865181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira */ 2866181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira private void saveRequestMap() { 2867181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira // TODO: store the request map in user preferences. 2868181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira } 286982cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira 28702db7d4a37b794e1721a5b9416068702aa799c5f8Mindy Pereira private void doAttach(String type) { 2871013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira Intent i = new Intent(Intent.ACTION_GET_CONTENT); 2872013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira i.addCategory(Intent.CATEGORY_OPENABLE); 2873d6a9a3f94c69d05f23349a09d71cd36c6fb03613Paul Westbrook i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET); 28742db7d4a37b794e1721a5b9416068702aa799c5f8Mindy Pereira i.setType(type); 2875013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira mAddingAttachment = true; 2876181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira startActivityForResult(Intent.createChooser(i, getText(R.string.select_attachment_type)), 2877181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira RESULT_PICK_ATTACHMENT); 2878013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira } 2879013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira 2880ec8b0edb23c0e0b7f1a8ce9558a919be31169d45Mindy Pereira private void showCcBccViews() { 2881a26b54e3a858de409be3746e65591bb8a0d6ea9aMindy Pereira mCcBccView.show(true, true, true); 2882ec8b0edb23c0e0b7f1a8ce9558a919be31169d45Mindy Pereira if (mCcBccButton != null) { 2883cd0b0b950efebfc3964334067747b97e61c4f027mindyp mCcBccButton.setVisibility(View.INVISIBLE); 2884ec8b0edb23c0e0b7f1a8ce9558a919be31169d45Mindy Pereira } 2885ec8b0edb23c0e0b7f1a8ce9558a919be31169d45Mindy Pereira } 2886ec8b0edb23c0e0b7f1a8ce9558a919be31169d45Mindy Pereira 2887dc97bf4509c450c9121b79ec4668e0f9b34f0690Andy Huang private void logSendOrSave(boolean save) { 2888dc97bf4509c450c9121b79ec4668e0f9b34f0690Andy Huang final String category = (save) ? "message_save" : "message_send"; 2889dc97bf4509c450c9121b79ec4668e0f9b34f0690Andy Huang final int attachmentCount = getAttachments().size(); 2890dc97bf4509c450c9121b79ec4668e0f9b34f0690Andy Huang final String msgType; 2891dc97bf4509c450c9121b79ec4668e0f9b34f0690Andy Huang switch (mComposeMode) { 2892dc97bf4509c450c9121b79ec4668e0f9b34f0690Andy Huang case COMPOSE: 2893dc97bf4509c450c9121b79ec4668e0f9b34f0690Andy Huang msgType = "new_message"; 2894dc97bf4509c450c9121b79ec4668e0f9b34f0690Andy Huang break; 2895dc97bf4509c450c9121b79ec4668e0f9b34f0690Andy Huang case REPLY: 2896dc97bf4509c450c9121b79ec4668e0f9b34f0690Andy Huang msgType = "reply"; 2897dc97bf4509c450c9121b79ec4668e0f9b34f0690Andy Huang break; 2898dc97bf4509c450c9121b79ec4668e0f9b34f0690Andy Huang case REPLY_ALL: 2899dc97bf4509c450c9121b79ec4668e0f9b34f0690Andy Huang msgType = "reply_all"; 2900dc97bf4509c450c9121b79ec4668e0f9b34f0690Andy Huang break; 2901dc97bf4509c450c9121b79ec4668e0f9b34f0690Andy Huang case FORWARD: 2902dc97bf4509c450c9121b79ec4668e0f9b34f0690Andy Huang msgType = "forward"; 2903dc97bf4509c450c9121b79ec4668e0f9b34f0690Andy Huang break; 2904dc97bf4509c450c9121b79ec4668e0f9b34f0690Andy Huang default: 2905dc97bf4509c450c9121b79ec4668e0f9b34f0690Andy Huang msgType = "unknown"; 2906dc97bf4509c450c9121b79ec4668e0f9b34f0690Andy Huang break; 2907dc97bf4509c450c9121b79ec4668e0f9b34f0690Andy Huang } 2908dc97bf4509c450c9121b79ec4668e0f9b34f0690Andy Huang final String label; 2909dc97bf4509c450c9121b79ec4668e0f9b34f0690Andy Huang final long value; 2910dc97bf4509c450c9121b79ec4668e0f9b34f0690Andy Huang if (mComposeMode == COMPOSE) { 2911dc97bf4509c450c9121b79ec4668e0f9b34f0690Andy Huang label = Integer.toString(attachmentCount); 2912dc97bf4509c450c9121b79ec4668e0f9b34f0690Andy Huang value = attachmentCount; 2913dc97bf4509c450c9121b79ec4668e0f9b34f0690Andy Huang } else { 2914dc97bf4509c450c9121b79ec4668e0f9b34f0690Andy Huang label = null; 2915dc97bf4509c450c9121b79ec4668e0f9b34f0690Andy Huang value = 0; 2916dc97bf4509c450c9121b79ec4668e0f9b34f0690Andy Huang } 2917dc97bf4509c450c9121b79ec4668e0f9b34f0690Andy Huang Analytics.getInstance().sendEvent(category, msgType, label, value); 2918dc97bf4509c450c9121b79ec4668e0f9b34f0690Andy Huang } 2919dc97bf4509c450c9121b79ec4668e0f9b34f0690Andy Huang 2920326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira @Override 2921326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira public boolean onNavigationItemSelected(int position, long itemId) { 2922a26b54e3a858de409be3746e65591bb8a0d6ea9aMindy Pereira int initialComposeMode = mComposeMode; 2923326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira if (position == ComposeActivity.REPLY) { 2924326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira mComposeMode = ComposeActivity.REPLY; 2925326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } else if (position == ComposeActivity.REPLY_ALL) { 2926326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira mComposeMode = ComposeActivity.REPLY_ALL; 2927326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } else if (position == ComposeActivity.FORWARD) { 2928326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira mComposeMode = ComposeActivity.FORWARD; 2929326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } 2930cbfb75a0f92a3ef5cf10ab94b451e4898cc78bfcMindy Pereira clearChangeListeners(); 2931a26b54e3a858de409be3746e65591bb8a0d6ea9aMindy Pereira if (initialComposeMode != mComposeMode) { 2932154386a287a9bfffb2eb3a4c05445f2774e1d4f0Mindy Pereira resetMessageForModeChange(); 293368c0bfcc4c5ee390305b6f677dc43ad0036371d8mindyp if (mRefMessage != null) { 29340aeaf7d8c2ee4bc882ca901531f985c61b4cc7c7Scott Kennedy setFieldsFromRefMessage(mComposeMode); 29358eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira } 2936ef38830943dac17adb4cade670b5ae0c6b4442c6Mindy Pereira boolean showCc = false; 2937ef38830943dac17adb4cade670b5ae0c6b4442c6Mindy Pereira boolean showBcc = false; 2938ef38830943dac17adb4cade670b5ae0c6b4442c6Mindy Pereira if (mDraft != null) { 2939ef38830943dac17adb4cade670b5ae0c6b4442c6Mindy Pereira // Following desktop behavior, if the user has added a BCC 2940ef38830943dac17adb4cade670b5ae0c6b4442c6Mindy Pereira // field to a draft, we show it regardless of compose mode. 29418960f0af431bc164003e09b3c8981aab808d9ec1Scott Kennedy showBcc = !TextUtils.isEmpty(mDraft.getBcc()); 2942ef38830943dac17adb4cade670b5ae0c6b4442c6Mindy Pereira // Use the draft to determine what to populate. 2943ef38830943dac17adb4cade670b5ae0c6b4442c6Mindy Pereira // If the Bcc field is showing, show the Cc field whether it is populated or not. 29448960f0af431bc164003e09b3c8981aab808d9ec1Scott Kennedy showCc = showBcc 29458960f0af431bc164003e09b3c8981aab808d9ec1Scott Kennedy || (!TextUtils.isEmpty(mDraft.getCc()) && mComposeMode == REPLY_ALL); 294668c0bfcc4c5ee390305b6f677dc43ad0036371d8mindyp } 294768c0bfcc4c5ee390305b6f677dc43ad0036371d8mindyp if (mRefMessage != null) { 29489b1ac57b10316cc1416c46f04811c54830e01529mindyp showCc = !TextUtils.isEmpty(mCc.getText()); 294968c0bfcc4c5ee390305b6f677dc43ad0036371d8mindyp showBcc = !TextUtils.isEmpty(mBcc.getText()); 2950ef38830943dac17adb4cade670b5ae0c6b4442c6Mindy Pereira } 2951ef38830943dac17adb4cade670b5ae0c6b4442c6Mindy Pereira mCcBccView.show(false, showCc, showBcc); 2952a26b54e3a858de409be3746e65591bb8a0d6ea9aMindy Pereira } 2953ef38830943dac17adb4cade670b5ae0c6b4442c6Mindy Pereira updateHideOrShowCcBcc(); 2954cbfb75a0f92a3ef5cf10ab94b451e4898cc78bfcMindy Pereira initChangeListeners(); 2955326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira return true; 2956326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } 2957326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira 2958b3112a2bf7b805695259e412b0e2bc0e0e73e9d6Mindy Pereira @VisibleForTesting 2959b3112a2bf7b805695259e412b0e2bc0e0e73e9d6Mindy Pereira protected void resetMessageForModeChange() { 2960154386a287a9bfffb2eb3a4c05445f2774e1d4f0Mindy Pereira // When switching between reply, reply all, forward, 2961154386a287a9bfffb2eb3a4c05445f2774e1d4f0Mindy Pereira // follow the behavior of webview. 2962154386a287a9bfffb2eb3a4c05445f2774e1d4f0Mindy Pereira // The contents of the following fields are cleared 2963154386a287a9bfffb2eb3a4c05445f2774e1d4f0Mindy Pereira // so that they can be populated directly from the 2964154386a287a9bfffb2eb3a4c05445f2774e1d4f0Mindy Pereira // ref message: 2965154386a287a9bfffb2eb3a4c05445f2774e1d4f0Mindy Pereira // 1) Any recipient fields 2966154386a287a9bfffb2eb3a4c05445f2774e1d4f0Mindy Pereira // 2) The subject 2967154386a287a9bfffb2eb3a4c05445f2774e1d4f0Mindy Pereira mTo.setText(""); 2968154386a287a9bfffb2eb3a4c05445f2774e1d4f0Mindy Pereira mCc.setText(""); 2969154386a287a9bfffb2eb3a4c05445f2774e1d4f0Mindy Pereira mBcc.setText(""); 2970154386a287a9bfffb2eb3a4c05445f2774e1d4f0Mindy Pereira // Any edits to the subject are replaced with the original subject. 2971154386a287a9bfffb2eb3a4c05445f2774e1d4f0Mindy Pereira mSubject.setText(""); 2972154386a287a9bfffb2eb3a4c05445f2774e1d4f0Mindy Pereira 2973154386a287a9bfffb2eb3a4c05445f2774e1d4f0Mindy Pereira // Any changes to the contents of the following fields are kept: 2974154386a287a9bfffb2eb3a4c05445f2774e1d4f0Mindy Pereira // 1) Body 2975154386a287a9bfffb2eb3a4c05445f2774e1d4f0Mindy Pereira // 2) Attachments 2976154386a287a9bfffb2eb3a4c05445f2774e1d4f0Mindy Pereira // If the user made changes to attachments, keep their changes. 2977154386a287a9bfffb2eb3a4c05445f2774e1d4f0Mindy Pereira if (!mAttachmentsChanged) { 2978154386a287a9bfffb2eb3a4c05445f2774e1d4f0Mindy Pereira mAttachmentsView.deleteAllAttachments(); 2979154386a287a9bfffb2eb3a4c05445f2774e1d4f0Mindy Pereira } 2980154386a287a9bfffb2eb3a4c05445f2774e1d4f0Mindy Pereira } 2981154386a287a9bfffb2eb3a4c05445f2774e1d4f0Mindy Pereira 2982326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira private class ComposeModeAdapter extends ArrayAdapter<String> { 2983326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira 2984326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira private LayoutInflater mInflater; 2985326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira 2986326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira public ComposeModeAdapter(Context context) { 2987326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira super(context, R.layout.compose_mode_item, R.id.mode, getResources() 2988326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira .getStringArray(R.array.compose_modes)); 2989326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } 2990326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira 2991326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira private LayoutInflater getInflater() { 2992326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira if (mInflater == null) { 2993326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira mInflater = LayoutInflater.from(getContext()); 2994326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } 2995326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira return mInflater; 2996326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } 2997326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira 2998326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira @Override 2999326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira public View getView(int position, View convertView, ViewGroup parent) { 3000326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira if (convertView == null) { 3001326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira convertView = getInflater().inflate(R.layout.compose_mode_display_item, null); 3002326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } 3003326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira ((TextView) convertView.findViewById(R.id.mode)).setText(getItem(position)); 3004326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira return super.getView(position, convertView, parent); 3005326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } 3006326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } 300746ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira 300846ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira @Override 300946ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira public void onRespondInline(String text) { 301046ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira appendToBody(text, false); 301140882430c874ff29890ec6fa31f7649788cbc470mindyp mQuotedTextView.setUpperDividerVisible(false); 30121623f9bfde8ced840a52820da28a0939bcaa32f9mindyp mRespondedInline = true; 301309dd373fae26156a847bb99d88474a7538b9e7c1mindyp if (!mBodyView.hasFocus()) { 30148654d4fcc09ba68872e677b2a57877a46d27fdb5mindyp mBodyView.requestFocus(); 301509dd373fae26156a847bb99d88474a7538b9e7c1mindyp } 301646ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira } 301746ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira 301846ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira /** 301946ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira * Append text to the body of the message. If there is no existing body 302046ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira * text, just sets the body to text. 302146ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira * 302246ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira * @param text 302346ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira * @param withSignature True to append a signature. 302446ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira */ 302546ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira public void appendToBody(CharSequence text, boolean withSignature) { 3026eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira Editable bodyText = mBodyView.getEditableText(); 302746ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira if (bodyText != null && bodyText.length() > 0) { 302846ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira bodyText.append(text); 302946ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira } else { 303046ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira setBody(text, withSignature); 303146ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira } 303246ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira } 303346ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira 303446ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira /** 303546ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira * Set the body of the message. 3036bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira * 303746ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira * @param text 303846ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira * @param withSignature True to append a signature. 303946ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira */ 304046ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira public void setBody(CharSequence text, boolean withSignature) { 3041eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira mBodyView.setText(text); 3042bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira if (withSignature) { 3043bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira appendSignature(); 3044bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira } 3045bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira } 3046bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira 3047bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira private void appendSignature() { 3048b13917c3d753c6674db2a226668a7f3048ddc4b5Mindy Pereira String newSignature = mCachedSettings != null ? mCachedSettings.signature : null; 3049433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira boolean hasFocus = mBodyView.hasFocus(); 30502708306e0b6f8dde22b2571d0dbcc28a53c9f29bmindyp int signaturePos = getSignatureStartPosition(mSignature, mBodyView.getText().toString()); 30512708306e0b6f8dde22b2571d0dbcc28a53c9f29bmindyp if (!TextUtils.equals(newSignature, mSignature) || signaturePos < 0) { 3052b13917c3d753c6674db2a226668a7f3048ddc4b5Mindy Pereira mSignature = newSignature; 30532708306e0b6f8dde22b2571d0dbcc28a53c9f29bmindyp if (!TextUtils.isEmpty(mSignature)) { 3054b13917c3d753c6674db2a226668a7f3048ddc4b5Mindy Pereira // Appending a signature does not count as changing text. 3055b13917c3d753c6674db2a226668a7f3048ddc4b5Mindy Pereira mBodyView.removeTextChangedListener(this); 3056b13917c3d753c6674db2a226668a7f3048ddc4b5Mindy Pereira mBodyView.append(convertToPrintableSignature(mSignature)); 3057b13917c3d753c6674db2a226668a7f3048ddc4b5Mindy Pereira mBodyView.addTextChangedListener(this); 3058b13917c3d753c6674db2a226668a7f3048ddc4b5Mindy Pereira } 3059433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira if (hasFocus) { 3060433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira focusBody(); 3061433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira } 3062bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira } 3063bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira } 3064bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira 3065bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira private String convertToPrintableSignature(String signature) { 3066bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira String signatureResource = getResources().getString(R.string.signature); 3067bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira if (signature == null) { 3068bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira signature = ""; 3069bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira } 3070bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira return String.format(signatureResource, signature); 307146ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira } 30721a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira 30735a85e2b7485a5c407c581219fe1b44417f050529Mindy Pereira @Override 30745a85e2b7485a5c407c581219fe1b44417f050529Mindy Pereira public void onAccountChanged() { 307592551d057965689f1952faeb06763f0762bc717fMindy Pereira mReplyFromAccount = mFromSpinner.getCurrentAccount(); 307692551d057965689f1952faeb06763f0762bc717fMindy Pereira if (!mAccount.equals(mReplyFromAccount.account)) { 3077f432dbce53a73eabed150b35033f2ec1a70c9725mindyp // Clear a signature, if there was one. 3078f432dbce53a73eabed150b35033f2ec1a70c9725mindyp mBodyView.removeTextChangedListener(this); 3079f432dbce53a73eabed150b35033f2ec1a70c9725mindyp String oldSignature = mSignature; 3080f432dbce53a73eabed150b35033f2ec1a70c9725mindyp String bodyText = getBody().getText().toString(); 3081f432dbce53a73eabed150b35033f2ec1a70c9725mindyp if (!TextUtils.isEmpty(oldSignature)) { 3082f432dbce53a73eabed150b35033f2ec1a70c9725mindyp int pos = getSignatureStartPosition(oldSignature, bodyText); 3083f432dbce53a73eabed150b35033f2ec1a70c9725mindyp if (pos > -1) { 3084f432dbce53a73eabed150b35033f2ec1a70c9725mindyp mBodyView.setText(bodyText.substring(0, pos)); 3085f432dbce53a73eabed150b35033f2ec1a70c9725mindyp } 3086f432dbce53a73eabed150b35033f2ec1a70c9725mindyp } 3087b1f573c59ec20f9149443e1e0cc8b64ff3a07feaPaul Westbrook setAccount(mReplyFromAccount.account); 3088f432dbce53a73eabed150b35033f2ec1a70c9725mindyp mBodyView.addTextChangedListener(this); 3089181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira // TODO: handle discarding attachments when switching accounts. 3090181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira // Only enable save for this draft if there is any other content 3091181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira // in the message. 3092181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira if (!isBlank()) { 3093181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira enableSave(true); 3094181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira } 3095181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira mReplyFromChanged = true; 3096181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira initRecipients(); 309782cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira } 30981a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira } 309982cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira 310082cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira public void enableSave(boolean enabled) { 310182cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira if (mSave != null) { 310282cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira mSave.setEnabled(enabled); 310382cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira } 310482cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira } 310582cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira 31062558b509117872e539a6eaeb72aa63425529d50bTony Mantler public static class DiscardConfirmDialogFragment extends DialogFragment { 3107f0ea4849bf7a2c11f99ca0b42307ae8ba665b1dcPaul Westbrook // Public no-args constructor needed for fragment re-instantiation 3108f0ea4849bf7a2c11f99ca0b42307ae8ba665b1dcPaul Westbrook public DiscardConfirmDialogFragment() {} 3109f0ea4849bf7a2c11f99ca0b42307ae8ba665b1dcPaul Westbrook 31102558b509117872e539a6eaeb72aa63425529d50bTony Mantler @Override 31112558b509117872e539a6eaeb72aa63425529d50bTony Mantler public Dialog onCreateDialog(Bundle savedInstanceState) { 31122558b509117872e539a6eaeb72aa63425529d50bTony Mantler return new AlertDialog.Builder(getActivity()) 31132558b509117872e539a6eaeb72aa63425529d50bTony Mantler .setMessage(R.string.confirm_discard_text) 31142558b509117872e539a6eaeb72aa63425529d50bTony Mantler .setPositiveButton(R.string.discard, 31152558b509117872e539a6eaeb72aa63425529d50bTony Mantler new DialogInterface.OnClickListener() { 31162558b509117872e539a6eaeb72aa63425529d50bTony Mantler @Override 31172558b509117872e539a6eaeb72aa63425529d50bTony Mantler public void onClick(DialogInterface dialog, int which) { 31182558b509117872e539a6eaeb72aa63425529d50bTony Mantler ((ComposeActivity)getActivity()).doDiscardWithoutConfirmation(); 31192558b509117872e539a6eaeb72aa63425529d50bTony Mantler } 31202558b509117872e539a6eaeb72aa63425529d50bTony Mantler }) 31212b215b7e4aa5901322dd6ef2e4e8616a4552e9b3Tony Mantler .setNegativeButton(R.string.cancel, null) 31222558b509117872e539a6eaeb72aa63425529d50bTony Mantler .create(); 312382cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira } 312482cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira } 312582cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira 3126efe3d25aa19da172fd5c3ec39539cdd91f29e927Mindy Pereira private void doDiscard() { 31272558b509117872e539a6eaeb72aa63425529d50bTony Mantler final DialogFragment frag = new DiscardConfirmDialogFragment(); 31282558b509117872e539a6eaeb72aa63425529d50bTony Mantler frag.show(getFragmentManager(), "discard confirm"); 3129efe3d25aa19da172fd5c3ec39539cdd91f29e927Mindy Pereira } 313082cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira /** 313182cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira * Effectively discard the current message. 313282cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira * 313382cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira * This method is either invoked from the menu or from the dialog 313482cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira * once the user has confirmed that they want to discard the message. 313582cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira */ 31362558b509117872e539a6eaeb72aa63425529d50bTony Mantler private void doDiscardWithoutConfirmation() { 31377ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira synchronized (mDraftLock) { 313882cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira if (mDraftId != UIProvider.INVALID_MESSAGE_ID) { 313982cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira ContentValues values = new ContentValues(); 3140b7050e62aab7133dea300d7fb3266311da99ec80Paul Westbrook values.put(BaseColumns._ID, mDraftId); 314178ea8e20c7d678c79153a1f814d0740f2bf3e462Marc Blank if (!mAccount.expungeMessageUri.equals(Uri.EMPTY)) { 3142cfb7f33ff8ef9dc60b9143af32de64c7a3d71f36Mindy Pereira getContentResolver().update(mAccount.expungeMessageUri, values, null, null); 3143cfb7f33ff8ef9dc60b9143af32de64c7a3d71f36Mindy Pereira } else { 31440bbc858506c95005f2840fa5dff495a9216d2665Marc Blank getContentResolver().delete(mDraft.uri, null, null); 3145cfb7f33ff8ef9dc60b9143af32de64c7a3d71f36Mindy Pereira } 314682cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira // This is not strictly necessary (since we should not try to 314782cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira // save the draft after calling this) but it ensures that if we 314882cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira // do save again for some reason we make a new draft rather than 314982cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira // trying to resave an expunged draft. 315082cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira mDraftId = UIProvider.INVALID_MESSAGE_ID; 315182cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira } 315282cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira } 315382cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira 31542558b509117872e539a6eaeb72aa63425529d50bTony Mantler // Display a toast to let the user know 31552558b509117872e539a6eaeb72aa63425529d50bTony Mantler Toast.makeText(this, R.string.message_discarded, Toast.LENGTH_SHORT).show(); 315682cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira 315782cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira // This prevents the draft from being saved in onPause(). 315882cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira discardChanges(); 3159dc97bf4509c450c9121b79ec4668e0f9b34f0690Andy Huang mPerformedSendOrDiscard = true; 316082cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira finish(); 316182cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira } 316282cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira 3163eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira private void saveIfNeeded() { 3164eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira if (mAccount == null) { 3165eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira // We have not chosen an account yet so there's no way that we can save. This is ok, 3166eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira // though, since we are saving our state before AccountsActivity is activated. Thus, the 3167eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira // user has not interacted with us yet and there is no real state to save. 3168eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira return; 3169eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira } 3170eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira 3171eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira if (shouldSave()) { 317248e31b07b5ac7c83dc3a009242fa915afccddb9eMindy Pereira doSave(!mAddingAttachment /* show toast */); 3173eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira } 3174eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira } 3175eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira 3176eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira @Override 3177eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira public void onAttachmentDeleted() { 3178eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira mAttachmentsChanged = true; 317940882430c874ff29890ec6fa31f7649788cbc470mindyp // If we are showing any attachments, make sure we have an upper 318040882430c874ff29890ec6fa31f7649788cbc470mindyp // divider. 318140882430c874ff29890ec6fa31f7649788cbc470mindyp mQuotedTextView.setUpperDividerVisible(mAttachmentsView.getAttachments().size() > 0); 3182eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira updateSaveUi(); 3183eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira } 318475f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira 318540882430c874ff29890ec6fa31f7649788cbc470mindyp @Override 318640882430c874ff29890ec6fa31f7649788cbc470mindyp public void onAttachmentAdded() { 318740882430c874ff29890ec6fa31f7649788cbc470mindyp mQuotedTextView.setUpperDividerVisible(mAttachmentsView.getAttachments().size() > 0); 318840882430c874ff29890ec6fa31f7649788cbc470mindyp mAttachmentsView.focusLastAttachment(); 318940882430c874ff29890ec6fa31f7649788cbc470mindyp } 319075f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira 319175f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira /** 319275f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira * This is called any time one of our text fields changes. 319375f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira */ 31940bbc858506c95005f2840fa5dff495a9216d2665Marc Blank @Override 319575f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira public void afterTextChanged(Editable s) { 319675f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira mTextChanged = true; 319775f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira updateSaveUi(); 319875f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira } 319975f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira 320075f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira @Override 320175f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira public void beforeTextChanged(CharSequence s, int start, int count, int after) { 320275f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira // Do nothing. 320375f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira } 320475f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira 32050bbc858506c95005f2840fa5dff495a9216d2665Marc Blank @Override 320675f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira public void onTextChanged(CharSequence s, int start, int before, int count) { 320775f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira // Do nothing. 320875f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira } 320975f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira 321075f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira 321175f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira // There is a big difference between the text associated with an address changing 321275f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira // to add the display name or to format properly and a recipient being added or deleted. 321375f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira // Make sure we only notify of changes when a recipient has been added or deleted. 321475f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira private class RecipientTextWatcher implements TextWatcher { 321575f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira private HashMap<String, Integer> mContent = new HashMap<String, Integer>(); 321675f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira 321775f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira private RecipientEditTextView mView; 321875f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira 321975f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira private TextWatcher mListener; 322075f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira 322175f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira public RecipientTextWatcher(RecipientEditTextView view, TextWatcher listener) { 322275f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira mView = view; 322375f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira mListener = listener; 322475f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira } 322575f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira 322675f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira @Override 322775f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira public void afterTextChanged(Editable s) { 322875f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira if (hasChanged()) { 322975f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira mListener.afterTextChanged(s); 323075f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira } 323175f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira } 323275f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira 323375f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira private boolean hasChanged() { 323475f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira String[] currRecips = tokenizeRecips(getAddressesFromList(mView)); 323575f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira int totalCount = currRecips.length; 323675f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira int totalPrevCount = 0; 323775f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira for (Entry<String, Integer> entry : mContent.entrySet()) { 323875f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira totalPrevCount += entry.getValue(); 323975f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira } 324075f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira if (totalCount != totalPrevCount) { 324175f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira return true; 324275f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira } 324375f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira 324475f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira for (String recip : currRecips) { 324575f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira if (!mContent.containsKey(recip)) { 324675f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira return true; 324775f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira } else { 324875f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira int count = mContent.get(recip) - 1; 324975f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira if (count < 0) { 325075f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira return true; 325175f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira } else { 325275f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira mContent.put(recip, count); 325375f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira } 325475f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira } 325575f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira } 325675f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira return false; 325775f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira } 325875f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira 325975f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira private String[] tokenizeRecips(String[] recips) { 326075f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira // Tokenize them all and put them in the list. 326175f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira String[] recipAddresses = new String[recips.length]; 326275f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira for (int i = 0; i < recips.length; i++) { 326375f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira recipAddresses[i] = Rfc822Tokenizer.tokenize(recips[i])[0].getAddress(); 326475f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira } 326575f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira return recipAddresses; 326675f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira } 326775f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira 326875f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira @Override 326975f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira public void beforeTextChanged(CharSequence s, int start, int count, int after) { 327075f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira String[] recips = tokenizeRecips(getAddressesFromList(mView)); 327175f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira for (String recip : recips) { 327275f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira if (!mContent.containsKey(recip)) { 327375f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira mContent.put(recip, 1); 327475f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira } else { 327575f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira mContent.put(recip, (mContent.get(recip)) + 1); 327675f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira } 327775f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira } 327875f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira } 327975f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira 328075f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira @Override 328175f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira public void onTextChanged(CharSequence s, int start, int before, int count) { 328275f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira // Do nothing. 328375f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira } 328475f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira } 3285e011b1d1c8e2e674dfdf1985d9d13da8cc06d803Mindy Pereira 3286e011b1d1c8e2e674dfdf1985d9d13da8cc06d803Mindy Pereira public static void registerTestSendOrSaveCallback(SendOrSaveCallback testCallback) { 3287e011b1d1c8e2e674dfdf1985d9d13da8cc06d803Mindy Pereira if (sTestSendOrSaveCallback != null && testCallback != null) { 3288e011b1d1c8e2e674dfdf1985d9d13da8cc06d803Mindy Pereira throw new IllegalStateException("Attempting to register more than one test callback"); 3289e011b1d1c8e2e674dfdf1985d9d13da8cc06d803Mindy Pereira } 3290e011b1d1c8e2e674dfdf1985d9d13da8cc06d803Mindy Pereira sTestSendOrSaveCallback = testCallback; 3291e011b1d1c8e2e674dfdf1985d9d13da8cc06d803Mindy Pereira } 3292bddd6f39f34aa15fed2e757f7d3e4163272ca02cMindy Pereira 3293bddd6f39f34aa15fed2e757f7d3e4163272ca02cMindy Pereira @VisibleForTesting 3294bddd6f39f34aa15fed2e757f7d3e4163272ca02cMindy Pereira protected ArrayList<Attachment> getAttachments() { 3295bddd6f39f34aa15fed2e757f7d3e4163272ca02cMindy Pereira return mAttachmentsView.getAttachments(); 3296bddd6f39f34aa15fed2e757f7d3e4163272ca02cMindy Pereira } 329796a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira 329896a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira @Override 329996a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira public Loader<Cursor> onCreateLoader(int id, Bundle args) { 330096a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira switch (id) { 3301a990a715012379451344246c5156d29938f12886Alice Yang case INIT_DRAFT_USING_REFERENCE_MESSAGE: 3302a990a715012379451344246c5156d29938f12886Alice Yang return new CursorLoader(this, mRefMessageUri, UIProvider.MESSAGE_PROJECTION, null, 3303a990a715012379451344246c5156d29938f12886Alice Yang null, null); 330496a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira case REFERENCE_MESSAGE_LOADER: 330596a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira return new CursorLoader(this, mRefMessageUri, UIProvider.MESSAGE_PROJECTION, null, 330696a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira null, null); 3307b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira case LOADER_ACCOUNT_CURSOR: 3308b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira return new CursorLoader(this, MailAppProvider.getAccountsUri(), 3309b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira UIProvider.ACCOUNTS_PROJECTION, null, null, null); 331096a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira } 331196a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira return null; 331296a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira } 331396a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira 331496a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira @Override 331596a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira public void onLoadFinished(Loader<Cursor> loader, Cursor data) { 3316b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira int id = loader.getId(); 3317b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira switch (id) { 3318a990a715012379451344246c5156d29938f12886Alice Yang case INIT_DRAFT_USING_REFERENCE_MESSAGE: 3319b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira if (data != null && data.moveToFirst()) { 3320b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira mRefMessage = new Message(data); 3321b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira Intent intent = getIntent(); 3322a990a715012379451344246c5156d29938f12886Alice Yang initFromRefMessage(mComposeMode); 3323a990a715012379451344246c5156d29938f12886Alice Yang finishSetup(mComposeMode, intent, null); 3324a990a715012379451344246c5156d29938f12886Alice Yang if (mComposeMode != FORWARD) { 3325b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira String to = intent.getStringExtra(EXTRA_TO); 3326b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira if (!TextUtils.isEmpty(to)) { 33270aeaf7d8c2ee4bc882ca901531f985c61b4cc7c7Scott Kennedy mRefMessage.setTo(null); 33280aeaf7d8c2ee4bc882ca901531f985c61b4cc7c7Scott Kennedy mRefMessage.setFrom(null); 3329b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira clearChangeListeners(); 3330b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira mTo.append(to); 3331b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira initChangeListeners(); 3332b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira } 3333b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira } 3334b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira } else { 3335b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira finish(); 333696a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira } 3337b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira break; 3338a990a715012379451344246c5156d29938f12886Alice Yang case REFERENCE_MESSAGE_LOADER: 3339a990a715012379451344246c5156d29938f12886Alice Yang // Only populate mRefMessage and leave other fields untouched. 3340a990a715012379451344246c5156d29938f12886Alice Yang if (data != null && data.moveToFirst()) { 3341a990a715012379451344246c5156d29938f12886Alice Yang mRefMessage = new Message(data); 3342a990a715012379451344246c5156d29938f12886Alice Yang } 33439f855d667e34fbf0d330845225c26956e540b819Andy Huang finishSetup(mComposeMode, getIntent(), mInnerSavedState); 3344a990a715012379451344246c5156d29938f12886Alice Yang break; 3345b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira case LOADER_ACCOUNT_CURSOR: 3346b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira if (data != null && data.moveToFirst()) { 3347b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira // there are accounts now! 3348b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira Account account; 3349faa742fcff868e17fb7e78c4c3f3ffdb01386f57Paul Westbrook final ArrayList<Account> accounts = new ArrayList<Account>(); 3350faa742fcff868e17fb7e78c4c3f3ffdb01386f57Paul Westbrook final ArrayList<Account> initializedAccounts = new ArrayList<Account>(); 3351b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira do { 3352b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira account = new Account(data); 3353dfa1dec0cfdc263c51e971dc3c41b90386a24340Paul Westbrook if (account.isAccountReady()) { 3354b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira initializedAccounts.add(account); 3355b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira } 3356b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira accounts.add(account); 3357b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira } while (data.moveToNext()); 3358b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira if (initializedAccounts.size() > 0) { 3359b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira findViewById(R.id.wait).setVisibility(View.GONE); 3360b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira getLoaderManager().destroyLoader(LOADER_ACCOUNT_CURSOR); 3361b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira findViewById(R.id.compose).setVisibility(View.VISIBLE); 3362faa742fcff868e17fb7e78c4c3f3ffdb01386f57Paul Westbrook mAccounts = initializedAccounts.toArray( 3363faa742fcff868e17fb7e78c4c3f3ffdb01386f57Paul Westbrook new Account[initializedAccounts.size()]); 3364faa742fcff868e17fb7e78c4c3f3ffdb01386f57Paul Westbrook 3365b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira finishCreate(); 3366b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira invalidateOptionsMenu(); 3367b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira } else { 3368b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira // Show "waiting" 3369b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira account = accounts.size() > 0 ? accounts.get(0) : null; 3370b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira showWaitFragment(account); 3371b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira } 3372b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira } 3373b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira break; 3374b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira } 3375b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira } 3376b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira 3377b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira private void showWaitFragment(Account account) { 3378b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira WaitFragment fragment = getWaitFragment(); 3379b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira if (fragment != null) { 3380b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira fragment.updateAccount(account); 338196a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira } else { 3382b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira findViewById(R.id.wait).setVisibility(View.VISIBLE); 3383b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira replaceFragment(WaitFragment.newInstance(account, true), 3384b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira FragmentTransaction.TRANSIT_FRAGMENT_OPEN, TAG_WAIT); 338596a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira } 338696a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira } 338796a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira 3388b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira private WaitFragment getWaitFragment() { 3389b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira return (WaitFragment) getFragmentManager().findFragmentByTag(TAG_WAIT); 3390b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira } 3391b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira 3392b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira private int replaceFragment(Fragment fragment, int transition, String tag) { 3393b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira FragmentTransaction fragmentTransaction = getFragmentManager().beginTransaction(); 3394b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira fragmentTransaction.setTransition(transition); 3395b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira fragmentTransaction.replace(R.id.wait, fragment, tag); 3396b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira final int transactionId = fragmentTransaction.commitAllowingStateLoss(); 3397b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira return transactionId; 3398b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira } 3399b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira 340096a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira @Override 340196a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira public void onLoaderReset(Loader<Cursor> arg0) { 340296a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira // Do nothing. 340396a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira } 340483e6b574cffd06164cad18ee388237a9427ceb3fPaul Westbrook 340583e6b574cffd06164cad18ee388237a9427ceb3fPaul Westbrook @Override 340683e6b574cffd06164cad18ee388237a9427ceb3fPaul Westbrook public Context getActivityContext() { 340783e6b574cffd06164cad18ee388237a9427ceb3fPaul Westbrook return this; 340883e6b574cffd06164cad18ee388237a9427ceb3fPaul Westbrook } 34091f8f4dd8c53e6c18ae642235335ce492c9d1e520Andy Huang} 3410