ComposeActivity.java revision 5ee9dc48884714e9005a1409e7002a0e04bad313
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; 25b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereiraimport android.app.Fragment; 26b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereiraimport android.app.FragmentTransaction; 2796a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereiraimport android.app.LoaderManager; 286349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereiraimport android.content.ContentResolver; 2982cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereiraimport android.content.ContentValues; 306349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereiraimport android.content.Context; 3196a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereiraimport android.content.CursorLoader; 3282cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereiraimport android.content.DialogInterface; 336349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereiraimport android.content.Intent; 3496a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereiraimport android.content.Loader; 3582cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereiraimport android.content.pm.ActivityInfo; 367ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereiraimport android.database.Cursor; 376349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereiraimport android.net.Uri; 388e9305ec0bbe23cec01eb34a2aee76c55199a10aMindy Pereiraimport android.os.Bundle; 3982cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereiraimport android.os.Handler; 4082cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereiraimport android.os.HandlerThread; 41f97588bd03fdcd318e24a9d74a283e73d1fbd37cPaul Westbrookimport android.os.Parcelable; 423c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrookimport android.os.ParcelFileDescriptor; 4382cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereiraimport android.provider.BaseColumns; 4446ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereiraimport android.text.Editable; 4582cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereiraimport android.text.Html; 46ed9c2f0e9b6b7d7556c3d048c78c072c21e587a1mindypimport android.text.SpannableString; 4782cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereiraimport android.text.Spanned; 48c182762df95fd382faf8e4a25e5cf7783ea10176Paul Westbrookimport android.text.TextUtils; 4982cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereiraimport android.text.TextWatcher; 5046ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereiraimport android.text.util.Rfc822Token; 51c17d073dd43871df36ea70b3dea55963bdb98384Mindy Pereiraimport android.text.util.Rfc822Tokenizer; 523cd4f40dab2c0810cb5ecd77256abf022863b2b5Mindy Pereiraimport android.view.Gravity; 5362d3ec7f251f6f9a96a859a2702916d07f30a04amindypimport android.view.KeyEvent; 54326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereiraimport android.view.LayoutInflater; 55b47f3e286bcf78e85ab2d3389e38e99020d0634fMindy Pereiraimport android.view.Menu; 56b47f3e286bcf78e85ab2d3389e38e99020d0634fMindy Pereiraimport android.view.MenuInflater; 57b47f3e286bcf78e85ab2d3389e38e99020d0634fMindy Pereiraimport android.view.MenuItem; 588e9305ec0bbe23cec01eb34a2aee76c55199a10aMindy Pereiraimport android.view.View; 598e9305ec0bbe23cec01eb34a2aee76c55199a10aMindy Pereiraimport android.view.View.OnClickListener; 605c5fd571b40a15b95ea5a5d6033f377706ffd0fbAndy Huangimport android.view.ViewGroup; 6162d3ec7f251f6f9a96a859a2702916d07f30a04amindypimport android.view.inputmethod.EditorInfo; 62326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereiraimport android.widget.ArrayAdapter; 638e9305ec0bbe23cec01eb34a2aee76c55199a10aMindy Pereiraimport android.widget.Button; 64433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereiraimport android.widget.EditText; 656349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereiraimport android.widget.TextView; 66013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereiraimport android.widget.Toast; 677b56a61174eeb202eea468b7f68b79729737ded2Mindy Pereira 68c17d073dd43871df36ea70b3dea55963bdb98384Mindy Pereiraimport com.android.common.Rfc822Validator; 695c5fd571b40a15b95ea5a5d6033f377706ffd0fbAndy Huangimport com.android.ex.chips.RecipientEditTextView; 705680ec22f92125cbd95ff0f8d18d5cc04c6f0b81Scott Kennedyimport com.android.mail.MailIntentService; 715c5fd571b40a15b95ea5a5d6033f377706ffd0fbAndy Huangimport com.android.mail.R; 7240882430c874ff29890ec6fa31f7649788cbc470mindypimport com.android.mail.compose.AttachmentsView.AttachmentAddedOrDeletedListener; 739932dee248718d2cec993d93b5115973d1389d0aMindy Pereiraimport com.android.mail.compose.AttachmentsView.AttachmentFailureException; 745a85e2b7485a5c407c581219fe1b44417f050529Mindy Pereiraimport com.android.mail.compose.FromAddressSpinner.OnAccountChangedListener; 7530e2c24b056542f3b1b438aeb798305d1226d0c8Andy Huangimport com.android.mail.compose.QuotedTextView.RespondInlineListener; 7633fe908589dca6a7f58aa9f56d73f74a48ac42f6Mindy Pereiraimport com.android.mail.providers.Account; 7730e2c24b056542f3b1b438aeb798305d1226d0c8Andy Huangimport com.android.mail.providers.Address; 7830e2c24b056542f3b1b438aeb798305d1226d0c8Andy Huangimport com.android.mail.providers.Attachment; 795680ec22f92125cbd95ff0f8d18d5cc04c6f0b81Scott Kennedyimport com.android.mail.providers.Folder; 8047d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereiraimport com.android.mail.providers.MailAppProvider; 813ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereiraimport com.android.mail.providers.Message; 8282cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereiraimport com.android.mail.providers.MessageModification; 8392551d057965689f1952faeb06763f0762bc717fMindy Pereiraimport com.android.mail.providers.ReplyFromAccount; 84181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereiraimport com.android.mail.providers.Settings; 8530e2c24b056542f3b1b438aeb798305d1226d0c8Andy Huangimport com.android.mail.providers.UIProvider; 863ca5bad62c075184920c5e331870280fc6acca16Mindy Pereiraimport com.android.mail.providers.UIProvider.AccountCapabilities; 8712575866e5526e45eaf773c6c98c93c3a06fe156Mindy Pereiraimport com.android.mail.providers.UIProvider.DraftType; 88fa20c1a4e36e0da2577baddbbb38a988b2017339Mindy Pereiraimport com.android.mail.ui.MailActivity; 89b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereiraimport com.android.mail.ui.WaitFragment; 9062066e47fe69c33b60ed970e46809ba81d044064Mark Weiimport com.android.mail.ui.AttachmentTile.AttachmentPreview; 9192227f6b35b3bec54609dc0feb9dd6756c2a43e6Paul Westbrookimport com.android.mail.utils.AccountUtils; 92434f294a3ae17a4f76342af38d6376f672a5d9edMark Weiimport com.android.mail.utils.AttachmentUtils; 93febd226e871263aeb21d436bee81eb2f7dec3d03mindypimport com.android.mail.utils.ContentProviderTask; 94b334c9035e9b7a38766bb66c29da2208525d1e11Paul Westbrookimport com.android.mail.utils.LogTag; 9530e2c24b056542f3b1b438aeb798305d1226d0c8Andy Huangimport com.android.mail.utils.LogUtils; 9630e2c24b056542f3b1b438aeb798305d1226d0c8Andy Huangimport com.android.mail.utils.Utils; 9746ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereiraimport com.google.common.annotations.VisibleForTesting; 9882cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereiraimport com.google.common.collect.Lists; 994a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereiraimport com.google.common.collect.Sets; 1008e9305ec0bbe23cec01eb34a2aee76c55199a10aMindy Pereira 1013c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrookimport java.io.FileNotFoundException; 1023c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrookimport java.io.IOException; 1038eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereiraimport java.io.UnsupportedEncodingException; 1048eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereiraimport java.net.URLDecoder; 10546ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereiraimport java.util.ArrayList; 106bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrookimport java.util.Arrays; 10746ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereiraimport java.util.Collection; 10875f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereiraimport java.util.HashMap; 10946ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereiraimport java.util.HashSet; 11046ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereiraimport java.util.List; 1111c078cff1958b29e280100bfa6221103ec46b555Paul Westbrookimport java.util.Map.Entry; 112bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrookimport java.util.Set; 11382cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereiraimport java.util.concurrent.ConcurrentHashMap; 11446ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira 11546ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereirapublic class ComposeActivity extends Activity implements OnClickListener, OnNavigationListener, 1165a85e2b7485a5c407c581219fe1b44417f050529Mindy Pereira RespondInlineListener, DialogInterface.OnClickListener, TextWatcher, 11740882430c874ff29890ec6fa31f7649788cbc470mindyp AttachmentAddedOrDeletedListener, OnAccountChangedListener, LoaderManager.LoaderCallbacks<Cursor>, 11862d3ec7f251f6f9a96a859a2702916d07f30a04amindyp TextView.OnEditorActionListener { 1196349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira // Identifiers for which type of composition this is 12036bbcaeff2a6e57189e4f4818e0ccdf6317ce836Mindy Pereira static final int COMPOSE = -1; 12136bbcaeff2a6e57189e4f4818e0ccdf6317ce836Mindy Pereira static final int REPLY = 0; 12236bbcaeff2a6e57189e4f4818e0ccdf6317ce836Mindy Pereira static final int REPLY_ALL = 1; 12336bbcaeff2a6e57189e4f4818e0ccdf6317ce836Mindy Pereira static final int FORWARD = 2; 12436bbcaeff2a6e57189e4f4818e0ccdf6317ce836Mindy Pereira static final int EDIT_DRAFT = 3; 1256349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira 1266349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira // Integer extra holding one of the above compose action 12796a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira protected static final String EXTRA_ACTION = "action"; 1286349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira 129326689d531da1d2579fa7daaf6e307e24a05f993Mindy Pereira private static final String EXTRA_SHOW_CC = "showCc"; 130326689d531da1d2579fa7daaf6e307e24a05f993Mindy Pereira private static final String EXTRA_SHOW_BCC = "showBcc"; 1311623f9bfde8ced840a52820da28a0939bcaa32f9mindyp private static final String EXTRA_RESPONDED_INLINE = "respondedInline"; 1321d7e9145fa4f490ba87ade0ed70ce0fa1f33be81mindyp private static final String EXTRA_SAVE_ENABLED = "saveEnabled"; 133a34c9a054c9aef6f83abe56515c132a31d71b3c8Mindy Pereira 1348eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira private static final String UTF8_ENCODING_NAME = "UTF-8"; 1358eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira 1368eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira private static final String MAIL_TO = "mailto"; 1378eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira 1388eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira private static final String EXTRA_SUBJECT = "subject"; 1398eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira 1408eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira private static final String EXTRA_BODY = "body"; 1418eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira 142d27b6ea7fcc68b2af200158fab341c6e98727144mindyp protected static final String EXTRA_FROM_ACCOUNT_STRING = "fromAccountString"; 1439a42bb4f11c502dd5c2cf92249ac214a6c2f1a70Mindy Pereira 14462066e47fe69c33b60ed970e46809ba81d044064Mark Wei private static final String EXTRA_ATTACHMENT_PREVIEWS = "attachmentPreviews"; 14562066e47fe69c33b60ed970e46809ba81d044064Mark Wei 1468eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira // Extra that we can get passed from other activities 1478eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira private static final String EXTRA_TO = "to"; 1488eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira private static final String EXTRA_CC = "cc"; 1498eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira private static final String EXTRA_BCC = "bcc"; 1508eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira 1518eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira // List of all the fields 1528eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira static final String[] ALL_EXTRAS = { EXTRA_SUBJECT, EXTRA_BODY, EXTRA_TO, EXTRA_CC, EXTRA_BCC }; 1538eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira 15482cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira private static SendOrSaveCallback sTestSendOrSaveCallback = null; 15582cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira // Map containing information about requests to create new messages, and the id of the 15682cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira // messages that were the result of those requests. 15782cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira // 15882cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira // This map is used when the activity that initiated the save a of a new message, is killed 15982cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira // before the save has completed (and when we know the id of the newly created message). When 16082cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira // a save is completed, the service that is running in the background, will update the map 16182cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira // 16282cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira // When a new ComposeActivity instance is created, it will attempt to use the information in 16382cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira // the previously instantiated map. If ComposeActivity.onCreate() is called, with a bundle 16482cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira // (restoring data from a previous instance), and the map hasn't been created, we will attempt 16582cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira // to populate the map with data stored in shared preferences. 1661f8f4dd8c53e6c18ae642235335ce492c9d1e520Andy Huang // FIXME: values in this map are never read. 16782cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira private static ConcurrentHashMap<Integer, Long> sRequestMessageIdMap = null; 16882cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira // Key used to store the above map 16982cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira private static final String CACHED_MESSAGE_REQUEST_IDS_KEY = "cache-message-request-ids"; 1706349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira /** 1716349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira * Notifies the {@code Activity} that the caller is an Email 1726349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira * {@code Activity}, so that the back behavior may be modified accordingly. 1736349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira * 1746349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira * @see #onAppUpPressed 1756349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira */ 176daecb4b9b20a609b27fc803390ecf4f524b76089Paul Westbrook public static final String EXTRA_FROM_EMAIL_TASK = "fromemail"; 1776349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira 178e011b1d1c8e2e674dfdf1985d9d13da8cc06d803Mindy Pereira public static final String EXTRA_ATTACHMENTS = "attachments"; 179f97588bd03fdcd318e24a9d74a283e73d1fbd37cPaul Westbrook 1805680ec22f92125cbd95ff0f8d18d5cc04c6f0b81Scott Kennedy /** If set, we will clear notifications for this folder. */ 1815680ec22f92125cbd95ff0f8d18d5cc04c6f0b81Scott Kennedy public static final String EXTRA_NOTIFICATION_FOLDER = "extra-notification-folder"; 1825680ec22f92125cbd95ff0f8d18d5cc04c6f0b81Scott Kennedy 1833ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereira // If this is a reply/forward then this extra will hold the original message 18436bbcaeff2a6e57189e4f4818e0ccdf6317ce836Mindy Pereira private static final String EXTRA_IN_REFERENCE_TO_MESSAGE = "in-reference-to-message"; 185b18e5a9341c73541d7201830c513cb0ed247e935Mindy Pereira // If this is a reply/forward then this extra will hold a uri we must query 186b18e5a9341c73541d7201830c513cb0ed247e935Mindy Pereira // to get the original message. 187b18e5a9341c73541d7201830c513cb0ed247e935Mindy Pereira protected static final String EXTRA_IN_REFERENCE_TO_MESSAGE_URI = "in-reference-to-message-uri"; 188434f294a3ae17a4f76342af38d6376f672a5d9edMark Wei // If this is an action to edit an existing draft message, this extra will hold the 189bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook // draft message 190bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook private static final String ORIGINAL_DRAFT_MESSAGE = "original-draft-message"; 1914a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira private static final String END_TOKEN = ", "; 192b334c9035e9b7a38766bb66c29da2208525d1e11Paul Westbrook private static final String LOG_TAG = LogTag.getLogTag(); 193013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira // Request numbers for activities we start 194013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira private static final int RESULT_PICK_ATTACHMENT = 1; 195013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira private static final int RESULT_CREATE_ACCOUNT = 2; 1968eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira // TODO(mindyp) set mime-type for auto send? 197e011b1d1c8e2e674dfdf1985d9d13da8cc06d803Mindy Pereira public static final String AUTO_SEND_ACTION = "com.android.mail.action.AUTO_SEND"; 1988eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira 199e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira private static final String EXTRA_SELECTED_REPLY_FROM_ACCOUNT = "replyFromAccount"; 200e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira private static final String EXTRA_REQUEST_ID = "requestId"; 201e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira private static final String EXTRA_FOCUS_SELECTION_START = "focusSelectionStart"; 202e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira private static final String EXTRA_FOCUS_SELECTION_END = null; 203e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira private static final String EXTRA_MESSAGE = "extraMessage"; 20496a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira private static final int REFERENCE_MESSAGE_LOADER = 0; 205b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira private static final int LOADER_ACCOUNT_CURSOR = 1; 20647d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereira private static final String EXTRA_SELECTED_ACCOUNT = "selectedAccount"; 207b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira private static final String TAG_WAIT = "wait-fragment"; 2082db7d4a37b794e1721a5b9416068702aa799c5f8Mindy Pereira private static final String MIME_TYPE_PHOTO = "image/*"; 2092db7d4a37b794e1721a5b9416068702aa799c5f8Mindy Pereira private static final String MIME_TYPE_VIDEO = "video/*"; 2108e9305ec0bbe23cec01eb34a2aee76c55199a10aMindy Pereira 21182cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira /** 21282cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira * A single thread for running tasks in the background. 21382cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira */ 21482cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira private Handler mSendSaveTaskHandler = null; 215c17d073dd43871df36ea70b3dea55963bdb98384Mindy Pereira private RecipientEditTextView mTo; 216c17d073dd43871df36ea70b3dea55963bdb98384Mindy Pereira private RecipientEditTextView mCc; 217c17d073dd43871df36ea70b3dea55963bdb98384Mindy Pereira private RecipientEditTextView mBcc; 2188e9305ec0bbe23cec01eb34a2aee76c55199a10aMindy Pereira private Button mCcBccButton; 2198e9305ec0bbe23cec01eb34a2aee76c55199a10aMindy Pereira private CcBccView mCcBccView; 2207b56a61174eeb202eea468b7f68b79729737ded2Mindy Pereira private AttachmentsView mAttachmentsView; 22133fe908589dca6a7f58aa9f56d73f74a48ac42f6Mindy Pereira private Account mAccount; 22292551d057965689f1952faeb06763f0762bc717fMindy Pereira private ReplyFromAccount mReplyFromAccount; 223181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira private Settings mCachedSettings; 22482cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira private Rfc822Validator mValidator; 2256349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira private TextView mSubject; 2266349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira 227326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira private ComposeModeAdapter mComposeModeAdapter; 228326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira private int mComposeMode = -1; 22946ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira private boolean mForward; 23046ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira private String mRecipient; 23146ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira private QuotedTextView mQuotedTextView; 232433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira private EditText mBodyView; 2331a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira private View mFromStatic; 2342eb173211741adf7454bbf1990ba1b9d1e1f6a64Mindy Pereira private TextView mFromStaticText; 235eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira private View mFromSpinnerWrapper; 2361883b346928322a9f045bc5b7426ddcd6af9beb3Mindy Pereira @VisibleForTesting 2371883b346928322a9f045bc5b7426ddcd6af9beb3Mindy Pereira protected FromAddressSpinner mFromSpinner; 238013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira private boolean mAddingAttachment; 239eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira private boolean mAttachmentsChanged; 24082cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira private boolean mTextChanged; 24182cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira private boolean mReplyFromChanged; 24282cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira private MenuItem mSave; 24382cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira private MenuItem mSend; 24482cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira private AlertDialog mRecipientErrorDialog; 245eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira private AlertDialog mSendConfirmDialog; 246b3112a2bf7b805695259e412b0e2bc0e0e73e9d6Mindy Pereira @VisibleForTesting 247b3112a2bf7b805695259e412b0e2bc0e0e73e9d6Mindy Pereira protected Message mRefMessage; 2487ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira private long mDraftId = UIProvider.INVALID_MESSAGE_ID; 2497ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira private Message mDraft; 25044a6339dd80f4b5b9e5d54567021698d92467c5emindyp private ReplyFromAccount mDraftAccount; 2517ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira private Object mDraftLock = new Object(); 25293b079ba1d38d919b557dabcd971e7aa1e3f5cbcmindyp private View mPhotoAttachmentsButton; 25393b079ba1d38d919b557dabcd971e7aa1e3f5cbcmindyp private View mVideoAttachmentsButton; 2543ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereira 255326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira /** 256daecb4b9b20a609b27fc803390ecf4f524b76089Paul Westbrook * Boolean indicating whether ComposeActivity was launched from a Gmail controlled view. 257daecb4b9b20a609b27fc803390ecf4f524b76089Paul Westbrook */ 258daecb4b9b20a609b27fc803390ecf4f524b76089Paul Westbrook private boolean mLaunchedFromEmail = false; 259cbfb75a0f92a3ef5cf10ab94b451e4898cc78bfcMindy Pereira private RecipientTextWatcher mToListener; 260cbfb75a0f92a3ef5cf10ab94b451e4898cc78bfcMindy Pereira private RecipientTextWatcher mCcListener; 261cbfb75a0f92a3ef5cf10ab94b451e4898cc78bfcMindy Pereira private RecipientTextWatcher mBccListener; 262b18e5a9341c73541d7201830c513cb0ed247e935Mindy Pereira private Uri mRefMessageUri; 263b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira private Bundle mSavedInstanceState; 264daecb4b9b20a609b27fc803390ecf4f524b76089Paul Westbrook 265daecb4b9b20a609b27fc803390ecf4f524b76089Paul Westbrook 2661623f9bfde8ced840a52820da28a0939bcaa32f9mindyp // Array of the outstanding send or save tasks. Access is synchronized 2671623f9bfde8ced840a52820da28a0939bcaa32f9mindyp // with the object itself 2681623f9bfde8ced840a52820da28a0939bcaa32f9mindyp /* package for testing */ 2691623f9bfde8ced840a52820da28a0939bcaa32f9mindyp @VisibleForTesting 2701623f9bfde8ced840a52820da28a0939bcaa32f9mindyp public ArrayList<SendOrSaveTask> mActiveTasks = Lists.newArrayList(); 2711623f9bfde8ced840a52820da28a0939bcaa32f9mindyp // FIXME: this variable is never read. related to sRequestMessageIdMap. 2721623f9bfde8ced840a52820da28a0939bcaa32f9mindyp private int mRequestId; 2731623f9bfde8ced840a52820da28a0939bcaa32f9mindyp private String mSignature; 2741623f9bfde8ced840a52820da28a0939bcaa32f9mindyp private Account[] mAccounts; 2751623f9bfde8ced840a52820da28a0939bcaa32f9mindyp private boolean mRespondedInline; 2761623f9bfde8ced840a52820da28a0939bcaa32f9mindyp 277daecb4b9b20a609b27fc803390ecf4f524b76089Paul Westbrook /** 278326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira * Can be called from a non-UI thread. 279326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira */ 2803ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereira public static void editDraft(Context launcher, Account account, Message message) { 281bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook launch(launcher, account, message, EDIT_DRAFT); 282326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } 283326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira 2846349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira /** 2856349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira * Can be called from a non-UI thread. 2866349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira */ 28733fe908589dca6a7f58aa9f56d73f74a48ac42f6Mindy Pereira public static void compose(Context launcher, Account account) { 2886349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira launch(launcher, account, null, COMPOSE); 2896349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira } 2906349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira 2916349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira /** 2926349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira * Can be called from a non-UI thread. 2936349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira */ 2940aeaf7d8c2ee4bc882ca901531f985c61b4cc7c7Scott Kennedy public static Intent createReplyIntent(final Context launcher, final Account account, 2950aeaf7d8c2ee4bc882ca901531f985c61b4cc7c7Scott Kennedy final Uri messageUri, final boolean isReplyAll) { 2960aeaf7d8c2ee4bc882ca901531f985c61b4cc7c7Scott Kennedy return createActionIntent(launcher, account, messageUri, isReplyAll ? REPLY_ALL : REPLY); 2970aeaf7d8c2ee4bc882ca901531f985c61b4cc7c7Scott Kennedy } 2980aeaf7d8c2ee4bc882ca901531f985c61b4cc7c7Scott Kennedy 2990aeaf7d8c2ee4bc882ca901531f985c61b4cc7c7Scott Kennedy /** 3000aeaf7d8c2ee4bc882ca901531f985c61b4cc7c7Scott Kennedy * Can be called from a non-UI thread. 3010aeaf7d8c2ee4bc882ca901531f985c61b4cc7c7Scott Kennedy */ 3020aeaf7d8c2ee4bc882ca901531f985c61b4cc7c7Scott Kennedy public static Intent createForwardIntent(final Context launcher, final Account account, 3030aeaf7d8c2ee4bc882ca901531f985c61b4cc7c7Scott Kennedy final Uri messageUri) { 3040aeaf7d8c2ee4bc882ca901531f985c61b4cc7c7Scott Kennedy return createActionIntent(launcher, account, messageUri, FORWARD); 3050aeaf7d8c2ee4bc882ca901531f985c61b4cc7c7Scott Kennedy } 3060aeaf7d8c2ee4bc882ca901531f985c61b4cc7c7Scott Kennedy 3070aeaf7d8c2ee4bc882ca901531f985c61b4cc7c7Scott Kennedy private static Intent createActionIntent(final Context launcher, final Account account, 3080aeaf7d8c2ee4bc882ca901531f985c61b4cc7c7Scott Kennedy final Uri messageUri, final int action) { 3090aeaf7d8c2ee4bc882ca901531f985c61b4cc7c7Scott Kennedy final Intent intent = new Intent(launcher, ComposeActivity.class); 3100aeaf7d8c2ee4bc882ca901531f985c61b4cc7c7Scott Kennedy 3110aeaf7d8c2ee4bc882ca901531f985c61b4cc7c7Scott Kennedy intent.putExtra(EXTRA_FROM_EMAIL_TASK, true); 3120aeaf7d8c2ee4bc882ca901531f985c61b4cc7c7Scott Kennedy intent.putExtra(EXTRA_ACTION, action); 3130aeaf7d8c2ee4bc882ca901531f985c61b4cc7c7Scott Kennedy intent.putExtra(Utils.EXTRA_ACCOUNT, account); 3140aeaf7d8c2ee4bc882ca901531f985c61b4cc7c7Scott Kennedy intent.putExtra(EXTRA_IN_REFERENCE_TO_MESSAGE_URI, messageUri); 3150aeaf7d8c2ee4bc882ca901531f985c61b4cc7c7Scott Kennedy 3160aeaf7d8c2ee4bc882ca901531f985c61b4cc7c7Scott Kennedy return intent; 3170aeaf7d8c2ee4bc882ca901531f985c61b4cc7c7Scott Kennedy } 3180aeaf7d8c2ee4bc882ca901531f985c61b4cc7c7Scott Kennedy 3190aeaf7d8c2ee4bc882ca901531f985c61b4cc7c7Scott Kennedy /** 3200aeaf7d8c2ee4bc882ca901531f985c61b4cc7c7Scott Kennedy * Can be called from a non-UI thread. 3210aeaf7d8c2ee4bc882ca901531f985c61b4cc7c7Scott Kennedy */ 3223ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereira public static void reply(Context launcher, Account account, Message message) { 3233ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereira launch(launcher, account, message, REPLY); 3246349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira } 3256349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira 3266349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira /** 3276349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira * Can be called from a non-UI thread. 3286349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira */ 3293ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereira public static void replyAll(Context launcher, Account account, Message message) { 3303ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereira launch(launcher, account, message, REPLY_ALL); 3316349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira } 3326349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira 3336349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira /** 3346349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira * Can be called from a non-UI thread. 3356349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira */ 3363ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereira public static void forward(Context launcher, Account account, Message message) { 3373ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereira launch(launcher, account, message, FORWARD); 3386349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira } 3396349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira 3403ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereira private static void launch(Context launcher, Account account, Message message, int action) { 3416349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira Intent intent = new Intent(launcher, ComposeActivity.class); 3426349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira intent.putExtra(EXTRA_FROM_EMAIL_TASK, true); 3436349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira intent.putExtra(EXTRA_ACTION, action); 3446349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira intent.putExtra(Utils.EXTRA_ACCOUNT, account); 345bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook if (action == EDIT_DRAFT) { 346bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook intent.putExtra(ORIGINAL_DRAFT_MESSAGE, message); 347bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook } else { 348bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook intent.putExtra(EXTRA_IN_REFERENCE_TO_MESSAGE, message); 349bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook } 3506349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira launcher.startActivity(intent); 3516349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira } 3528e9305ec0bbe23cec01eb34a2aee76c55199a10aMindy Pereira 3538e9305ec0bbe23cec01eb34a2aee76c55199a10aMindy Pereira @Override 3548e9305ec0bbe23cec01eb34a2aee76c55199a10aMindy Pereira public void onCreate(Bundle savedInstanceState) { 3558e9305ec0bbe23cec01eb34a2aee76c55199a10aMindy Pereira super.onCreate(savedInstanceState); 3568e9305ec0bbe23cec01eb34a2aee76c55199a10aMindy Pereira setContentView(R.layout.compose); 357b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira mSavedInstanceState = savedInstanceState; 358b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira checkValidAccounts(); 359b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira } 360b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira 361b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira private void finishCreate() { 362b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira Bundle savedInstanceState = mSavedInstanceState; 36346ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira findViews(); 364818143e2163648acc0c91f123b84777d65cd70cfMindy Pereira Intent intent = getIntent(); 365e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira Message message; 36662066e47fe69c33b60ed970e46809ba81d044064Mark Wei ArrayList<AttachmentPreview> previews; 36771c9e569c06ee362840c14093cf1973ecf297059Mindy Pereira boolean showQuotedText = false; 368e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira int action; 36947d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereira // Check for any of the possibly supplied accounts.; 37047d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereira Account account = null; 371f7fc6c339da7f73755041cceb9b8f8447680728aMindy Pereira if (hadSavedInstanceStateMessage(savedInstanceState)) { 372e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira action = savedInstanceState.getInt(EXTRA_ACTION, COMPOSE); 373e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira account = savedInstanceState.getParcelable(Utils.EXTRA_ACCOUNT); 374e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira message = (Message) savedInstanceState.getParcelable(EXTRA_MESSAGE); 37562066e47fe69c33b60ed970e46809ba81d044064Mark Wei 37662066e47fe69c33b60ed970e46809ba81d044064Mark Wei previews = savedInstanceState.getParcelableArrayList(EXTRA_ATTACHMENT_PREVIEWS); 377e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira mRefMessage = (Message) savedInstanceState.getParcelable(EXTRA_IN_REFERENCE_TO_MESSAGE); 378e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira } else { 37947d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereira account = obtainAccount(intent); 380e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira action = intent.getIntExtra(EXTRA_ACTION, COMPOSE); 381e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira // Initialize the message from the message in the intent 382e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira message = (Message) intent.getParcelableExtra(ORIGINAL_DRAFT_MESSAGE); 38362066e47fe69c33b60ed970e46809ba81d044064Mark Wei previews = intent.getParcelableArrayListExtra(EXTRA_ATTACHMENT_PREVIEWS); 384e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira mRefMessage = (Message) intent.getParcelableExtra(EXTRA_IN_REFERENCE_TO_MESSAGE); 385b18e5a9341c73541d7201830c513cb0ed247e935Mindy Pereira mRefMessageUri = (Uri) intent.getParcelableExtra(EXTRA_IN_REFERENCE_TO_MESSAGE_URI); 386e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira } 38762066e47fe69c33b60ed970e46809ba81d044064Mark Wei mAttachmentsView.setAttachmentPreviews(previews); 38892227f6b35b3bec54609dc0feb9dd6756c2a43e6Paul Westbrook 38992227f6b35b3bec54609dc0feb9dd6756c2a43e6Paul Westbrook setAccount(account); 390818143e2163648acc0c91f123b84777d65cd70cfMindy Pereira if (mAccount == null) { 391818143e2163648acc0c91f123b84777d65cd70cfMindy Pereira return; 392818143e2163648acc0c91f123b84777d65cd70cfMindy Pereira } 393bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook 3945680ec22f92125cbd95ff0f8d18d5cc04c6f0b81Scott Kennedy // Clear the notification and mark the conversation as seen, if necessary 3955680ec22f92125cbd95ff0f8d18d5cc04c6f0b81Scott Kennedy final Folder notificationFolder = 3965680ec22f92125cbd95ff0f8d18d5cc04c6f0b81Scott Kennedy intent.getParcelableExtra(EXTRA_NOTIFICATION_FOLDER); 3975680ec22f92125cbd95ff0f8d18d5cc04c6f0b81Scott Kennedy if (notificationFolder != null) { 3985680ec22f92125cbd95ff0f8d18d5cc04c6f0b81Scott Kennedy final Intent clearNotifIntent = 3995680ec22f92125cbd95ff0f8d18d5cc04c6f0b81Scott Kennedy new Intent(MailIntentService.ACTION_CLEAR_NEW_MAIL_NOTIFICATIONS); 4005680ec22f92125cbd95ff0f8d18d5cc04c6f0b81Scott Kennedy clearNotifIntent.putExtra(MailIntentService.ACCOUNT_EXTRA, account.name); 4015680ec22f92125cbd95ff0f8d18d5cc04c6f0b81Scott Kennedy clearNotifIntent.putExtra(MailIntentService.FOLDER_EXTRA, notificationFolder); 4025680ec22f92125cbd95ff0f8d18d5cc04c6f0b81Scott Kennedy 4035680ec22f92125cbd95ff0f8d18d5cc04c6f0b81Scott Kennedy startService(clearNotifIntent); 4045680ec22f92125cbd95ff0f8d18d5cc04c6f0b81Scott Kennedy } 4055680ec22f92125cbd95ff0f8d18d5cc04c6f0b81Scott Kennedy 406daecb4b9b20a609b27fc803390ecf4f524b76089Paul Westbrook if (intent.getBooleanExtra(EXTRA_FROM_EMAIL_TASK, false)) { 407daecb4b9b20a609b27fc803390ecf4f524b76089Paul Westbrook mLaunchedFromEmail = true; 408daecb4b9b20a609b27fc803390ecf4f524b76089Paul Westbrook } else if (Intent.ACTION_SEND.equals(intent.getAction())) { 409daecb4b9b20a609b27fc803390ecf4f524b76089Paul Westbrook final Uri dataUri = intent.getData(); 410daecb4b9b20a609b27fc803390ecf4f524b76089Paul Westbrook if (dataUri != null) { 411daecb4b9b20a609b27fc803390ecf4f524b76089Paul Westbrook final String dataScheme = intent.getData().getScheme(); 412daecb4b9b20a609b27fc803390ecf4f524b76089Paul Westbrook final String accountScheme = mAccount.composeIntentUri.getScheme(); 413daecb4b9b20a609b27fc803390ecf4f524b76089Paul Westbrook mLaunchedFromEmail = TextUtils.equals(dataScheme, accountScheme); 414daecb4b9b20a609b27fc803390ecf4f524b76089Paul Westbrook } 415daecb4b9b20a609b27fc803390ecf4f524b76089Paul Westbrook } 416daecb4b9b20a609b27fc803390ecf4f524b76089Paul Westbrook 41796a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira if (mRefMessageUri != null) { 41896a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira // We have a referenced message that we must look up. 41996a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira getLoaderManager().initLoader(REFERENCE_MESSAGE_LOADER, null, this); 42096a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira return; 42196a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira } else if (message != null && action != EDIT_DRAFT) { 422e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira initFromDraftMessage(message); 423e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira initQuotedTextFromRefMessage(mRefMessage, action); 424a34c9a054c9aef6f83abe56515c132a31d71b3c8Mindy Pereira showCcBcc(savedInstanceState); 42571c9e569c06ee362840c14093cf1973ecf297059Mindy Pereira showQuotedText = message.appendRefMessageContent; 426e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira } else if (action == EDIT_DRAFT) { 427e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira initFromDraftMessage(message); 4288960f0af431bc164003e09b3c8981aab808d9ec1Scott Kennedy boolean showBcc = !TextUtils.isEmpty(message.getBcc()); 4298960f0af431bc164003e09b3c8981aab808d9ec1Scott Kennedy boolean showCc = showBcc || !TextUtils.isEmpty(message.getCc()); 430ef38830943dac17adb4cade670b5ae0c6b4442c6Mindy Pereira mCcBccView.show(false, showCc, showBcc); 431bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook // Update the action to the draft type of the previous draft 432bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook switch (message.draftType) { 433bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook case UIProvider.DraftType.REPLY: 434bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook action = REPLY; 435bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook break; 436bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook case UIProvider.DraftType.REPLY_ALL: 437bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook action = REPLY_ALL; 438bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook break; 439bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook case UIProvider.DraftType.FORWARD: 440bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook action = FORWARD; 441bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook break; 442bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook case UIProvider.DraftType.COMPOSE: 443bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook default: 444bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook action = COMPOSE; 445bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook break; 446bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook } 447e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira initQuotedTextFromRefMessage(mRefMessage, action); 44871c9e569c06ee362840c14093cf1973ecf297059Mindy Pereira showQuotedText = message.appendRefMessageContent; 449e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira } else if ((action == REPLY || action == REPLY_ALL || action == FORWARD)) { 450e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira if (mRefMessage != null) { 4510aeaf7d8c2ee4bc882ca901531f985c61b4cc7c7Scott Kennedy initFromRefMessage(action); 45271c9e569c06ee362840c14093cf1973ecf297059Mindy Pereira showQuotedText = true; 453e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira } 4548eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira } else { 4558eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira initFromExtras(intent); 456bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook } 45796a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira finishSetup(action, intent, savedInstanceState, showQuotedText); 45896a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira } 459bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook 460b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira private void checkValidAccounts() { 461faa742fcff868e17fb7e78c4c3f3ffdb01386f57Paul Westbrook final Account[] allAccounts = AccountUtils.getAccounts(this); 462faa742fcff868e17fb7e78c4c3f3ffdb01386f57Paul Westbrook if (allAccounts == null || allAccounts.length == 0) { 463b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira final Intent noAccountIntent = MailAppProvider.getNoAccountIntent(this); 464b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira if (noAccountIntent != null) { 465faa742fcff868e17fb7e78c4c3f3ffdb01386f57Paul Westbrook mAccounts = null; 466b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira startActivityForResult(noAccountIntent, RESULT_CREATE_ACCOUNT); 467b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira } 468b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira } else { 46926d4d2d9c43c499f458808f050ec73ea3c28dec4mindyp // If none of the accounts are syncing, setup a watcher. 470b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira boolean anySyncing = false; 471faa742fcff868e17fb7e78c4c3f3ffdb01386f57Paul Westbrook for (Account a : allAccounts) { 472dfa1dec0cfdc263c51e971dc3c41b90386a24340Paul Westbrook if (a.isAccountReady()) { 473b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira anySyncing = true; 474b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira break; 475b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira } 476b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira } 477b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira if (!anySyncing) { 478b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira // There are accounts, but none are sync'd, which is just like having no accounts. 479b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira mAccounts = null; 480b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira getLoaderManager().initLoader(LOADER_ACCOUNT_CURSOR, null, this); 481b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira return; 482b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira } 483faa742fcff868e17fb7e78c4c3f3ffdb01386f57Paul Westbrook mAccounts = AccountUtils.getSyncingAccounts(this); 484b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira finishCreate(); 485b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira } 486b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira } 487b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira 48847d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereira private Account obtainAccount(Intent intent) { 48947d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereira Account account = null; 49047d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereira Object accountExtra = null; 49147d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereira if (intent != null && intent.getExtras() != null) { 49247d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereira accountExtra = intent.getExtras().get(Utils.EXTRA_ACCOUNT); 49347d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereira if (accountExtra instanceof Account) { 49447d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereira return (Account) accountExtra; 4957ae042ef2a23bf4c87f3edfcd71f7ebc784174abmindyp } else if (accountExtra instanceof String) { 4967ae042ef2a23bf4c87f3edfcd71f7ebc784174abmindyp // This is the Account attached to the widget compose intent. 4977ae042ef2a23bf4c87f3edfcd71f7ebc784174abmindyp account = Account.newinstance((String)accountExtra); 4987ae042ef2a23bf4c87f3edfcd71f7ebc784174abmindyp if (account != null) { 4997ae042ef2a23bf4c87f3edfcd71f7ebc784174abmindyp return account; 5007ae042ef2a23bf4c87f3edfcd71f7ebc784174abmindyp } 50147d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereira } 5025ee9dc48884714e9005a1409e7002a0e04bad313mindyp accountExtra = intent.hasExtra(Utils.EXTRA_ACCOUNT) ? 5035ee9dc48884714e9005a1409e7002a0e04bad313mindyp intent.getStringExtra(Utils.EXTRA_ACCOUNT) : 5045ee9dc48884714e9005a1409e7002a0e04bad313mindyp intent.getStringExtra(EXTRA_SELECTED_ACCOUNT); 50547d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereira } 50647d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereira if (account == null) { 5070617446db14891bffaa2748e1fc98526aac1e06dmindyp MailAppProvider provider = MailAppProvider.getInstance(); 5080617446db14891bffaa2748e1fc98526aac1e06dmindyp String lastAccountUri = provider.getLastSentFromAccount(); 5090617446db14891bffaa2748e1fc98526aac1e06dmindyp if (TextUtils.isEmpty(lastAccountUri)) { 5100617446db14891bffaa2748e1fc98526aac1e06dmindyp lastAccountUri = provider.getLastViewedAccount(); 5110617446db14891bffaa2748e1fc98526aac1e06dmindyp } 51247d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereira if (!TextUtils.isEmpty(lastAccountUri)) { 51347d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereira accountExtra = Uri.parse(lastAccountUri); 51447d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereira } 51547d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereira } 516b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira if (mAccounts != null && mAccounts.length > 0) { 51747d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereira if (accountExtra instanceof String && !TextUtils.isEmpty((String) accountExtra)) { 51847d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereira // For backwards compatibility, we need to check account 51947d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereira // names. 520b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira for (Account a : mAccounts) { 52147d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereira if (a.name.equals(accountExtra)) { 52247d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereira account = a; 52347d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereira } 52447d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereira } 52547d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereira } else if (accountExtra instanceof Uri) { 52647d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereira // The uri of the last viewed account is what is stored in 52747d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereira // the current code base. 528b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira for (Account a : mAccounts) { 52947d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereira if (a.uri.equals(accountExtra)) { 53047d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereira account = a; 53147d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereira } 53247d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereira } 533b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira } 534b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira if (account == null) { 535b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira account = mAccounts[0]; 53647d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereira } 53747d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereira } 53847d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereira return account; 53947d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereira } 54047d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereira 54196a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira private void finishSetup(int action, Intent intent, Bundle savedInstanceState, 54296a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira boolean showQuotedText) { 54334a3c56570eac4760405b3d5bff5fdc706a22facmindyp setFocus(action); 544bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook if (action == COMPOSE) { 545eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira mQuotedTextView.setVisibility(View.GONE); 54646ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira } 547818143e2163648acc0c91f123b84777d65cd70cfMindy Pereira initRecipients(); 548f7fc6c339da7f73755041cceb9b8f8447680728aMindy Pereira // Don't bother with the intent if we have procured a message from the 549f7fc6c339da7f73755041cceb9b8f8447680728aMindy Pereira // intent already. 550f7fc6c339da7f73755041cceb9b8f8447680728aMindy Pereira if (!hadSavedInstanceStateMessage(savedInstanceState)) { 551f7fc6c339da7f73755041cceb9b8f8447680728aMindy Pereira initAttachmentsFromIntent(intent); 552f7fc6c339da7f73755041cceb9b8f8447680728aMindy Pereira } 5531a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira initActionBar(action); 554e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira initFromSpinner(savedInstanceState != null ? savedInstanceState : intent.getExtras(), 555e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira action); 556d4a4866c99ae0ed8c943b6c9ced1e7fbc987c639mindyp 557d4a4866c99ae0ed8c943b6c9ced1e7fbc987c639mindyp // If this is a draft message, the draft account is whatever account was 558d4a4866c99ae0ed8c943b6c9ced1e7fbc987c639mindyp // used to open the draft message in Compose. 559d4a4866c99ae0ed8c943b6c9ced1e7fbc987c639mindyp if (mDraft != null) { 560d4a4866c99ae0ed8c943b6c9ced1e7fbc987c639mindyp mDraftAccount = mReplyFromAccount; 561d4a4866c99ae0ed8c943b6c9ced1e7fbc987c639mindyp } 562d4a4866c99ae0ed8c943b6c9ced1e7fbc987c639mindyp 56375f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira initChangeListeners(); 564326689d531da1d2579fa7daaf6e307e24a05f993Mindy Pereira updateHideOrShowCcBcc(); 56571c9e569c06ee362840c14093cf1973ecf297059Mindy Pereira updateHideOrShowQuotedText(showQuotedText); 5661623f9bfde8ced840a52820da28a0939bcaa32f9mindyp 5671623f9bfde8ced840a52820da28a0939bcaa32f9mindyp mRespondedInline = mSavedInstanceState != null ? 5681623f9bfde8ced840a52820da28a0939bcaa32f9mindyp mSavedInstanceState.getBoolean(EXTRA_RESPONDED_INLINE) : false; 5691623f9bfde8ced840a52820da28a0939bcaa32f9mindyp if (mRespondedInline) { 5701623f9bfde8ced840a52820da28a0939bcaa32f9mindyp mQuotedTextView.setVisibility(View.GONE); 5711623f9bfde8ced840a52820da28a0939bcaa32f9mindyp } 57271c9e569c06ee362840c14093cf1973ecf297059Mindy Pereira } 57371c9e569c06ee362840c14093cf1973ecf297059Mindy Pereira 574f7fc6c339da7f73755041cceb9b8f8447680728aMindy Pereira private boolean hadSavedInstanceStateMessage(Bundle savedInstanceState) { 575f7fc6c339da7f73755041cceb9b8f8447680728aMindy Pereira return savedInstanceState != null && savedInstanceState.containsKey(EXTRA_MESSAGE); 576f7fc6c339da7f73755041cceb9b8f8447680728aMindy Pereira } 577f7fc6c339da7f73755041cceb9b8f8447680728aMindy Pereira 57871c9e569c06ee362840c14093cf1973ecf297059Mindy Pereira private void updateHideOrShowQuotedText(boolean showQuotedText) { 57971c9e569c06ee362840c14093cf1973ecf297059Mindy Pereira mQuotedTextView.updateCheckedState(showQuotedText); 58040882430c874ff29890ec6fa31f7649788cbc470mindyp mQuotedTextView.setUpperDividerVisible(mAttachmentsView.getAttachments().size() > 0); 581433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira } 582433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira 583433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira private void setFocus(int action) { 584433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira if (action == EDIT_DRAFT) { 585433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira int type = mDraft.draftType; 586433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira switch (type) { 587433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira case UIProvider.DraftType.COMPOSE: 588433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira case UIProvider.DraftType.FORWARD: 589433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira action = COMPOSE; 590433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira break; 591433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira case UIProvider.DraftType.REPLY: 592433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira case UIProvider.DraftType.REPLY_ALL: 593433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira default: 594433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira action = REPLY; 595433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira break; 596433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira } 597433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira } 598433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira switch (action) { 599433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira case FORWARD: 600433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira case COMPOSE: 6012708306e0b6f8dde22b2571d0dbcc28a53c9f29bmindyp if (TextUtils.isEmpty(mTo.getText())) { 6022708306e0b6f8dde22b2571d0dbcc28a53c9f29bmindyp mTo.requestFocus(); 6032708306e0b6f8dde22b2571d0dbcc28a53c9f29bmindyp break; 6042708306e0b6f8dde22b2571d0dbcc28a53c9f29bmindyp } 605433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira case REPLY: 606433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira case REPLY_ALL: 607433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira default: 608433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira focusBody(); 609433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira break; 610433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira } 611433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira } 612433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira 613433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira /** 614433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira * Focus the body of the message. 615433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira */ 616433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira public void focusBody() { 617433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira mBodyView.requestFocus(); 618433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira int length = mBodyView.getText().length(); 619433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira 620433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira int signatureStartPos = getSignatureStartPosition( 621433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira mSignature, mBodyView.getText().toString()); 622433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira if (signatureStartPos > -1) { 623433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira // In case the user deleted the newlines... 624433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira mBodyView.setSelection(signatureStartPos); 6258743cfca851058d50385951b111dd903b1fa6c5amindyp } else if (length >= 0) { 626433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira // Move cursor to the end. 627433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira mBodyView.setSelection(length); 628433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira } 6291a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira } 6301a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira 6311a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira @Override 6321a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira protected void onResume() { 6331a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira super.onResume(); 6341a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira // Update the from spinner as other accounts 6351a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira // may now be available. 636818143e2163648acc0c91f123b84777d65cd70cfMindy Pereira if (mFromSpinner != null && mAccount != null) { 637b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira mFromSpinner.asyncInitFromSpinner(mComposeMode, mAccount, mAccounts); 638818143e2163648acc0c91f123b84777d65cd70cfMindy Pereira } 6391a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira } 6401a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira 641eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira @Override 642eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira protected void onPause() { 643eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira super.onPause(); 644eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira 645eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira if (mSendConfirmDialog != null) { 646eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira mSendConfirmDialog.dismiss(); 647eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira } 648eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira if (mRecipientErrorDialog != null) { 649eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira mRecipientErrorDialog.dismiss(); 650eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira } 651a214833a75ba2b27cdd166ceee9a2529b13a17c4Mindy Pereira // When the user exits the compose view, see if this draft needs saving. 6523d7048ea243df4c1ae163bd72971e83e1218e7f0Yorke Lee // Don't save unnecessary drafts if we are only changing the orientation. 6533d7048ea243df4c1ae163bd72971e83e1218e7f0Yorke Lee if (!isChangingConfigurations()) { 654a214833a75ba2b27cdd166ceee9a2529b13a17c4Mindy Pereira saveIfNeeded(); 655a214833a75ba2b27cdd166ceee9a2529b13a17c4Mindy Pereira } 656eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira } 657eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira 658eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira @Override 659eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira protected final void onActivityResult(int request, int result, Intent data) { 660b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira if (request == RESULT_PICK_ATTACHMENT && result == RESULT_OK) { 661eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira addAttachmentAndUpdateView(data); 662b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira mAddingAttachment = false; 663b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira } else if (request == RESULT_CREATE_ACCOUNT) { 664b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira // We were waiting for the user to create an account 665b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira if (result != RESULT_OK) { 666b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira finish(); 667b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira } else { 668b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira // Watch for accounts to show up! 669b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira // restart the loader to get the updated list of accounts 670b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira getLoaderManager().initLoader(LOADER_ACCOUNT_CURSOR, null, this); 671b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira showWaitFragment(null); 672b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira } 673eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira } 674eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira } 675eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira 676eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira @Override 677e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira public final void onRestoreInstanceState(Bundle savedInstanceState) { 67847db6d764dd4b74ddfd7fda6412e32d84d86fc9amindyp clearChangeListeners(); 679e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira super.onRestoreInstanceState(savedInstanceState); 680e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira if (savedInstanceState != null) { 681e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira if (savedInstanceState.containsKey(EXTRA_FOCUS_SELECTION_START)) { 682e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira int selectionStart = savedInstanceState.getInt(EXTRA_FOCUS_SELECTION_START); 683e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira int selectionEnd = savedInstanceState.getInt(EXTRA_FOCUS_SELECTION_END); 684e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira // There should be a focus and it should be an EditText since we 685e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira // only save these extras if these conditions are true. 686e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira EditText focusEditText = (EditText) getCurrentFocus(); 687e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira final int length = focusEditText.getText().length(); 688e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira if (selectionStart < length && selectionEnd < length) { 689e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira focusEditText.setSelection(selectionStart, selectionEnd); 690e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira } 691e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira } 692e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira } 6931d7e9145fa4f490ba87ade0ed70ce0fa1f33be81mindyp initChangeListeners(); 694e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira } 695e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira 696e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira @Override 697eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira public final void onSaveInstanceState(Bundle state) { 698eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira super.onSaveInstanceState(state); 699b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira // We have no accounts so there is nothing to compose, and therefore, nothing to save. 700b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira if (mAccounts == null || mAccounts.length == 0) { 701b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira return; 702b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira } 703e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira // The framework is happy to save and restore the selection but only if it also saves and 704e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira // restores the contents of the edit text. That's a lot of text to put in a bundle so we do 705e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira // this manually. 706e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira View focus = getCurrentFocus(); 707e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira if (focus != null && focus instanceof EditText) { 708e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira EditText focusEditText = (EditText) focus; 709e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira state.putInt(EXTRA_FOCUS_SELECTION_START, focusEditText.getSelectionStart()); 710e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira state.putInt(EXTRA_FOCUS_SELECTION_END, focusEditText.getSelectionEnd()); 711e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira } 7126273e96b7204a33ea44823fb36fd7fc8baf5ba20Paul Westbrook 7136273e96b7204a33ea44823fb36fd7fc8baf5ba20Paul Westbrook final List<ReplyFromAccount> replyFromAccounts = mFromSpinner.getReplyFromAccounts(); 714151f1ad1613ecac0207144472872440517172b5aPaul Westbrook final int selectedPos = mFromSpinner.getSelectedItemPosition(); 715d90f7ac9b1a62e8beefdac3ceda9e4cb75ef000cMindy Pereira final ReplyFromAccount selectedReplyFromAccount = (replyFromAccounts != null 716d90f7ac9b1a62e8beefdac3ceda9e4cb75ef000cMindy Pereira && replyFromAccounts.size() > 0 && replyFromAccounts.size() > selectedPos) ? 717d90f7ac9b1a62e8beefdac3ceda9e4cb75ef000cMindy Pereira replyFromAccounts.get(selectedPos) : null; 718e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira if (selectedReplyFromAccount != null) { 719e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira state.putString(EXTRA_SELECTED_REPLY_FROM_ACCOUNT, selectedReplyFromAccount.serialize() 720e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira .toString()); 721e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira state.putParcelable(Utils.EXTRA_ACCOUNT, selectedReplyFromAccount.account); 722e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira } else { 723e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira state.putParcelable(Utils.EXTRA_ACCOUNT, mAccount); 724e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira } 725eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira 726e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira if (mDraftId == UIProvider.INVALID_MESSAGE_ID && mRequestId !=0) { 727e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira // We don't have a draft id, and we have a request id, 728e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira // save the request id. 729e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira state.putInt(EXTRA_REQUEST_ID, mRequestId); 730e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira } 731e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira 732e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira // We want to restore the current mode after a pause 733e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira // or rotation. 734e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira int mode = getMode(); 735e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira state.putInt(EXTRA_ACTION, mode); 736e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira 737e7b76aac2ad5b12d6b04838ca72011ceaedc8910mindyp final Message message = createMessage(selectedReplyFromAccount, mode); 7381f8f4dd8c53e6c18ae642235335ce492c9d1e520Andy Huang if (mDraft != null) { 739e7b76aac2ad5b12d6b04838ca72011ceaedc8910mindyp message.id = mDraft.id; 740e7b76aac2ad5b12d6b04838ca72011ceaedc8910mindyp message.serverId = mDraft.serverId; 741e7b76aac2ad5b12d6b04838ca72011ceaedc8910mindyp message.uri = mDraft.uri; 7421f8f4dd8c53e6c18ae642235335ce492c9d1e520Andy Huang } 743e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira state.putParcelable(EXTRA_MESSAGE, message); 744e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira 745e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira if (mRefMessage != null) { 746e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira state.putParcelable(EXTRA_IN_REFERENCE_TO_MESSAGE, mRefMessage); 747e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira } 748326689d531da1d2579fa7daaf6e307e24a05f993Mindy Pereira state.putBoolean(EXTRA_SHOW_CC, mCcBccView.isCcVisible()); 749326689d531da1d2579fa7daaf6e307e24a05f993Mindy Pereira state.putBoolean(EXTRA_SHOW_BCC, mCcBccView.isBccVisible()); 7501623f9bfde8ced840a52820da28a0939bcaa32f9mindyp state.putBoolean(EXTRA_RESPONDED_INLINE, mRespondedInline); 751816b3f0adc04db073820f04ce379e5126e1cbef1mindyp state.putBoolean(EXTRA_SAVE_ENABLED, mSave != null && mSave.isEnabled()); 75262066e47fe69c33b60ed970e46809ba81d044064Mark Wei state.putParcelableArrayList( 75362066e47fe69c33b60ed970e46809ba81d044064Mark Wei EXTRA_ATTACHMENT_PREVIEWS, mAttachmentsView.getAttachmentPreviews()); 754e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira } 755e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira 756e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira private int getMode() { 757e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira int mode = ComposeActivity.COMPOSE; 758e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira ActionBar actionBar = getActionBar(); 759e011b1d1c8e2e674dfdf1985d9d13da8cc06d803Mindy Pereira if (actionBar != null 760e011b1d1c8e2e674dfdf1985d9d13da8cc06d803Mindy Pereira && actionBar.getNavigationMode() == ActionBar.NAVIGATION_MODE_LIST) { 761e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira mode = actionBar.getSelectedNavigationIndex(); 762e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira } 763e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira return mode; 764e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira } 765e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira 766e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira private Message createMessage(ReplyFromAccount selectedReplyFromAccount, int mode) { 767e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira Message message = new Message(); 768e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira message.id = UIProvider.INVALID_MESSAGE_ID; 769d47877e3860ea4249eddb3f6efefbc6cd39f2320Andy Huang message.serverId = null; 770e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira message.uri = null; 771e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira message.conversationUri = null; 772e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira message.subject = mSubject.getText().toString(); 773e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira message.snippet = null; 7748960f0af431bc164003e09b3c8981aab808d9ec1Scott Kennedy message.setTo(formatSenders(mTo.getText().toString())); 7758960f0af431bc164003e09b3c8981aab808d9ec1Scott Kennedy message.setCc(formatSenders(mCc.getText().toString())); 7768960f0af431bc164003e09b3c8981aab808d9ec1Scott Kennedy message.setBcc(formatSenders(mBcc.getText().toString())); 7778960f0af431bc164003e09b3c8981aab808d9ec1Scott Kennedy message.setReplyTo(null); 778e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira message.dateReceivedMs = 0; 779ed9c2f0e9b6b7d7556c3d048c78c072c21e587a1mindyp String htmlBody = Html.toHtml(new SpannableString(mBodyView.getText().toString())); 780e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira StringBuilder fullBody = new StringBuilder(htmlBody); 781e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira message.bodyHtml = fullBody.toString(); 782e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira message.bodyText = mBodyView.getText().toString(); 783e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira message.embedsExternalResources = false; 784e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira message.refMessageId = mRefMessage != null ? mRefMessage.uri.toString() : null; 785e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira message.appendRefMessageContent = mQuotedTextView.getQuotedTextIfIncluded() != null; 786e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira ArrayList<Attachment> attachments = mAttachmentsView.getAttachments(); 787e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira message.hasAttachments = attachments != null && attachments.size() > 0; 788e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira message.attachmentListUri = null; 789e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira message.messageFlags = 0; 790e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira message.saveUri = null; 791e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira message.sendUri = null; 792e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira message.alwaysShowImages = false; 793e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira message.attachmentsJson = Attachment.toJSONArray(attachments); 794e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira CharSequence quotedText = mQuotedTextView.getQuotedText(); 795e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira message.quotedTextOffset = !TextUtils.isEmpty(quotedText) ? QuotedTextView 796e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira .getQuotedTextOffset(quotedText.toString()) : -1; 797e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira message.accountUri = null; 7988960f0af431bc164003e09b3c8981aab808d9ec1Scott Kennedy message.setFrom(selectedReplyFromAccount != null ? selectedReplyFromAccount.address 7998960f0af431bc164003e09b3c8981aab808d9ec1Scott Kennedy : mAccount != null ? mAccount.name : null); 8001f8f4dd8c53e6c18ae642235335ce492c9d1e520Andy Huang message.draftType = getDraftType(mode); 8018960f0af431bc164003e09b3c8981aab808d9ec1Scott Kennedy message.setTo(formatSenders(mTo.getText().toString())); 8028960f0af431bc164003e09b3c8981aab808d9ec1Scott Kennedy message.setCc(formatSenders(mCc.getText().toString())); 8038960f0af431bc164003e09b3c8981aab808d9ec1Scott Kennedy message.setBcc(formatSenders(mBcc.getText().toString())); 804e7b76aac2ad5b12d6b04838ca72011ceaedc8910mindyp return message; 8051f8f4dd8c53e6c18ae642235335ce492c9d1e520Andy Huang } 8061f8f4dd8c53e6c18ae642235335ce492c9d1e520Andy Huang 8073c9115813343861a44133b805fb9f55512d20948Mindy Pereira private String formatSenders(String string) { 8083c9115813343861a44133b805fb9f55512d20948Mindy Pereira if (!TextUtils.isEmpty(string) && string.charAt(string.length() - 1) == ',') { 8093c9115813343861a44133b805fb9f55512d20948Mindy Pereira return string.substring(0, string.length() - 1); 8103c9115813343861a44133b805fb9f55512d20948Mindy Pereira } 8113c9115813343861a44133b805fb9f55512d20948Mindy Pereira return string; 8123c9115813343861a44133b805fb9f55512d20948Mindy Pereira } 8133c9115813343861a44133b805fb9f55512d20948Mindy Pereira 814818143e2163648acc0c91f123b84777d65cd70cfMindy Pereira @VisibleForTesting 815818143e2163648acc0c91f123b84777d65cd70cfMindy Pereira void setAccount(Account account) { 816bb5217ee950c156d761a086bfd0d1d392d224cf4Mindy Pereira if (account == null) { 817bb5217ee950c156d761a086bfd0d1d392d224cf4Mindy Pereira return; 818bb5217ee950c156d761a086bfd0d1d392d224cf4Mindy Pereira } 81923e9fdec6872f9b4d0fbe675745cb25becf7878cMindy Pereira if (!account.equals(mAccount)) { 82023e9fdec6872f9b4d0fbe675745cb25becf7878cMindy Pereira mAccount = account; 821b1f573c59ec20f9149443e1e0cc8b64ff3a07feaPaul Westbrook mCachedSettings = mAccount.settings; 822b1f573c59ec20f9149443e1e0cc8b64ff3a07feaPaul Westbrook appendSignature(); 82323e9fdec6872f9b4d0fbe675745cb25becf7878cMindy Pereira } 824fa20c1a4e36e0da2577baddbbb38a988b2017339Mindy Pereira if (mAccount != null) { 825f6c00b8304062a17d14b484bd1fc33a83c4a90d7Vikram Aggarwal MailActivity.setNfcMessage(mAccount.name); 826fa20c1a4e36e0da2577baddbbb38a988b2017339Mindy Pereira } 827818143e2163648acc0c91f123b84777d65cd70cfMindy Pereira } 828818143e2163648acc0c91f123b84777d65cd70cfMindy Pereira 829e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira private void initFromSpinner(Bundle bundle, int action) { 8309a42bb4f11c502dd5c2cf92249ac214a6c2f1a70Mindy Pereira String accountString = null; 831e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira if (action == EDIT_DRAFT && mDraft.draftType == UIProvider.DraftType.COMPOSE) { 83262de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira action = COMPOSE; 83362de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira } 834b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira mFromSpinner.asyncInitFromSpinner(action, mAccount, mAccounts); 8359a42bb4f11c502dd5c2cf92249ac214a6c2f1a70Mindy Pereira if (bundle != null) { 8369a42bb4f11c502dd5c2cf92249ac214a6c2f1a70Mindy Pereira if (bundle.containsKey(EXTRA_SELECTED_REPLY_FROM_ACCOUNT)) { 8379a42bb4f11c502dd5c2cf92249ac214a6c2f1a70Mindy Pereira mReplyFromAccount = ReplyFromAccount.deserialize(mAccount, 8389a42bb4f11c502dd5c2cf92249ac214a6c2f1a70Mindy Pereira bundle.getString(EXTRA_SELECTED_REPLY_FROM_ACCOUNT)); 8399a42bb4f11c502dd5c2cf92249ac214a6c2f1a70Mindy Pereira } else if (bundle.containsKey(EXTRA_FROM_ACCOUNT_STRING)) { 8409a42bb4f11c502dd5c2cf92249ac214a6c2f1a70Mindy Pereira accountString = bundle.getString(EXTRA_FROM_ACCOUNT_STRING); 8419a42bb4f11c502dd5c2cf92249ac214a6c2f1a70Mindy Pereira mReplyFromAccount = mFromSpinner.getMatchingReplyFromAccount(accountString); 8429a42bb4f11c502dd5c2cf92249ac214a6c2f1a70Mindy Pereira } 843e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira } 844e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira if (mReplyFromAccount == null) { 845e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira if (mDraft != null) { 846e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira mReplyFromAccount = getReplyFromAccountFromDraft(mAccount, mDraft); 847e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira } else if (mRefMessage != null) { 848e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira mReplyFromAccount = getReplyFromAccountForReply(mAccount, mRefMessage); 849e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira } 85062de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira } 85162de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira if (mReplyFromAccount == null) { 852238aa47dbd4426e8bd1c958e68a9d9b70c9be0f7Andy Huang mReplyFromAccount = getDefaultReplyFromAccount(mAccount); 85362de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira } 8549a42bb4f11c502dd5c2cf92249ac214a6c2f1a70Mindy Pereira 85562de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira mFromSpinner.setCurrentAccount(mReplyFromAccount); 8569a42bb4f11c502dd5c2cf92249ac214a6c2f1a70Mindy Pereira 85762de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira if (mFromSpinner.getCount() > 1) { 858a83e708e162ad1f4b04b41738882bf318e217f64Mindy Pereira // If there is only 1 account, just show that account. 859a83e708e162ad1f4b04b41738882bf318e217f64Mindy Pereira // Otherwise, give the user the ability to choose which account to 86062de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira // send mail from / save drafts to. 86162de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira mFromStatic.setVisibility(View.GONE); 862a83e708e162ad1f4b04b41738882bf318e217f64Mindy Pereira mFromStaticText.setText(mAccount.name); 86362de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira mFromSpinnerWrapper.setVisibility(View.VISIBLE); 864a83e708e162ad1f4b04b41738882bf318e217f64Mindy Pereira } else { 865a83e708e162ad1f4b04b41738882bf318e217f64Mindy Pereira mFromStatic.setVisibility(View.VISIBLE); 866a83e708e162ad1f4b04b41738882bf318e217f64Mindy Pereira mFromStaticText.setText(mAccount.name); 867a83e708e162ad1f4b04b41738882bf318e217f64Mindy Pereira mFromSpinnerWrapper.setVisibility(View.GONE); 868a83e708e162ad1f4b04b41738882bf318e217f64Mindy Pereira } 86946ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira } 87046ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira 87162de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira private ReplyFromAccount getReplyFromAccountForReply(Account account, Message refMessage) { 87262de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira if (refMessage.accountUri != null) { 87362de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira // This must be from combined inbox. 87462de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira List<ReplyFromAccount> replyFromAccounts = mFromSpinner.getReplyFromAccounts(); 87562de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira for (ReplyFromAccount from : replyFromAccounts) { 87662de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira if (from.account.uri.equals(refMessage.accountUri)) { 87762de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira return from; 87862de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira } 87962de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira } 88062de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira return null; 88162de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira } else { 88262de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira return getReplyFromAccount(account, refMessage); 88362de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira } 88462de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira } 88562de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira 88662de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira /** 88762de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira * Given an account and which email address the message was sent to, 88862de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira * return who the message should be sent from. 88962de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira * @param account Account in which the message arrived. 89062de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira * @param sentTo Email address to which the message was sent. 89162de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira * @return the address from which to reply. 89262de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira */ 89362de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira public ReplyFromAccount getReplyFromAccount(Account account, Message refMessage) { 89462de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira // First see if we are supposed to use the default address or 89562de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira // the address it was sentTo. 896326689d531da1d2579fa7daaf6e307e24a05f993Mindy Pereira if (mCachedSettings.forceReplyFromDefault) { 89762de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira return getDefaultReplyFromAccount(account); 89862de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira } else { 89989bae5713b830ec1182073de22c3091d3613ac3eMindy Pereira // If we aren't explicitly told which account to look for, look at 90062de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira // all the message recipients and find one that matches 90162de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira // a custom from or account. 90262de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira List<String> allRecipients = new ArrayList<String>(); 9035ed6311d6beb968e83585a43d7cdf5909e0a2cf6mindyp allRecipients.addAll(Arrays.asList(refMessage.getToAddresses())); 9045ed6311d6beb968e83585a43d7cdf5909e0a2cf6mindyp allRecipients.addAll(Arrays.asList(refMessage.getCcAddresses())); 90562de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira return getMatchingRecipient(account, allRecipients); 90662de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira } 90762de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira } 90862de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira 90962de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira /** 91062de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira * Compare all the recipients of an email to the current account and all 91162de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira * custom addresses associated with that account. Return the match if there 91262de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira * is one, or the default account if there isn't. 91362de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira */ 91462de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira protected ReplyFromAccount getMatchingRecipient(Account account, List<String> sentTo) { 91562de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira // Tokenize the list and place in a hashmap. 91662de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira ReplyFromAccount matchingReplyFrom = null; 91762de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira Rfc822Token[] tokens; 91862de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira HashSet<String> recipientsMap = new HashSet<String>(); 91962de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira for (String address : sentTo) { 92062de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira tokens = Rfc822Tokenizer.tokenize(address); 92162de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira for (int i = 0; i < tokens.length; i++) { 92262de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira recipientsMap.add(tokens[i].getAddress()); 92362de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira } 92462de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira } 92562de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira 92662de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira int matchingAddressCount = 0; 92762de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira List<ReplyFromAccount> customFroms; 9281617481de7c1f9b8dfcd25ba9828e933cf9d5490Andy Huang customFroms = account.getReplyFroms(); 9291617481de7c1f9b8dfcd25ba9828e933cf9d5490Andy Huang if (customFroms != null) { 9301617481de7c1f9b8dfcd25ba9828e933cf9d5490Andy Huang for (ReplyFromAccount entry : customFroms) { 9311617481de7c1f9b8dfcd25ba9828e933cf9d5490Andy Huang if (recipientsMap.contains(entry.address)) { 9321617481de7c1f9b8dfcd25ba9828e933cf9d5490Andy Huang matchingReplyFrom = entry; 9331617481de7c1f9b8dfcd25ba9828e933cf9d5490Andy Huang matchingAddressCount++; 93462de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira } 93562de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira } 93662de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira } 93762de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira if (matchingAddressCount > 1) { 93862de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira matchingReplyFrom = getDefaultReplyFromAccount(account); 93962de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira } 94062de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira return matchingReplyFrom; 94162de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira } 94262de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira 94362de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira private ReplyFromAccount getDefaultReplyFromAccount(Account account) { 944238aa47dbd4426e8bd1c958e68a9d9b70c9be0f7Andy Huang for (ReplyFromAccount from : account.getReplyFroms()) { 94562de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira if (from.isDefault) { 94662de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira return from; 94762de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira } 94862de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira } 949cd970ddaba4e212b668588db2104dc46ad3ad793Mindy Pereira return new ReplyFromAccount(account, account.uri, account.name, account.name, account.name, 950cd970ddaba4e212b668588db2104dc46ad3ad793Mindy Pereira true, false); 95162de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira } 95262de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira 953e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira private ReplyFromAccount getReplyFromAccountFromDraft(Account account, Message msg) { 9548960f0af431bc164003e09b3c8981aab808d9ec1Scott Kennedy String sender = msg.getFrom(); 95562de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira ReplyFromAccount replyFromAccount = null; 95662de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira List<ReplyFromAccount> replyFromAccounts = mFromSpinner.getReplyFromAccounts(); 95762de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira if (TextUtils.equals(account.name, sender)) { 95862de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira replyFromAccount = new ReplyFromAccount(mAccount, mAccount.uri, mAccount.name, 959cd970ddaba4e212b668588db2104dc46ad3ad793Mindy Pereira mAccount.name, mAccount.name, true, false); 96062de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira } else { 96162de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira for (ReplyFromAccount fromAccount : replyFromAccounts) { 96262de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira if (TextUtils.equals(fromAccount.name, sender)) { 96362de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira replyFromAccount = fromAccount; 96462de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira break; 96562de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira } 96662de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira } 96762de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira } 96862de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira return replyFromAccount; 96962de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira } 97062de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira 97146ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira private void findViews() { 972b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira findViewById(R.id.compose).setVisibility(View.VISIBLE); 973a26b54e3a858de409be3746e65591bb8a0d6ea9aMindy Pereira mCcBccButton = (Button) findViewById(R.id.add_cc_bcc); 9748e9305ec0bbe23cec01eb34a2aee76c55199a10aMindy Pereira if (mCcBccButton != null) { 9758e9305ec0bbe23cec01eb34a2aee76c55199a10aMindy Pereira mCcBccButton.setOnClickListener(this); 9768e9305ec0bbe23cec01eb34a2aee76c55199a10aMindy Pereira } 9778e9305ec0bbe23cec01eb34a2aee76c55199a10aMindy Pereira mCcBccView = (CcBccView) findViewById(R.id.cc_bcc_wrapper); 9787b56a61174eeb202eea468b7f68b79729737ded2Mindy Pereira mAttachmentsView = (AttachmentsView)findViewById(R.id.attachments); 97993b079ba1d38d919b557dabcd971e7aa1e3f5cbcmindyp mPhotoAttachmentsButton = findViewById(R.id.add_photo_attachment); 980cd0b0b950efebfc3964334067747b97e61c4f027mindyp if (mPhotoAttachmentsButton != null) { 981cd0b0b950efebfc3964334067747b97e61c4f027mindyp mPhotoAttachmentsButton.setOnClickListener(this); 982cd0b0b950efebfc3964334067747b97e61c4f027mindyp } 98393b079ba1d38d919b557dabcd971e7aa1e3f5cbcmindyp mVideoAttachmentsButton = findViewById(R.id.add_video_attachment); 984cd0b0b950efebfc3964334067747b97e61c4f027mindyp if (mVideoAttachmentsButton != null) { 985cd0b0b950efebfc3964334067747b97e61c4f027mindyp mVideoAttachmentsButton.setOnClickListener(this); 986cd0b0b950efebfc3964334067747b97e61c4f027mindyp } 987818143e2163648acc0c91f123b84777d65cd70cfMindy Pereira mTo = (RecipientEditTextView) findViewById(R.id.to); 988818143e2163648acc0c91f123b84777d65cd70cfMindy Pereira mCc = (RecipientEditTextView) findViewById(R.id.cc); 989818143e2163648acc0c91f123b84777d65cd70cfMindy Pereira mBcc = (RecipientEditTextView) findViewById(R.id.bcc); 99082cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira // TODO: add special chips text change watchers before adding 99182cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira // this as a text changed watcher to the to, cc, bcc fields. 9926349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira mSubject = (TextView) findViewById(R.id.subject); 99362d3ec7f251f6f9a96a859a2702916d07f30a04amindyp mSubject.setOnEditorActionListener(this); 99446ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira mQuotedTextView = (QuotedTextView) findViewById(R.id.quoted_text_view); 99546ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira mQuotedTextView.setRespondInlineListener(this); 996433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira mBodyView = (EditText) findViewById(R.id.body); 9971a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira mFromStatic = findViewById(R.id.static_from_content); 9982eb173211741adf7454bbf1990ba1b9d1e1f6a64Mindy Pereira mFromStaticText = (TextView) findViewById(R.id.from_account_name); 999eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira mFromSpinnerWrapper = findViewById(R.id.spinner_from_content); 10005a85e2b7485a5c407c581219fe1b44417f050529Mindy Pereira mFromSpinner = (FromAddressSpinner) findViewById(R.id.from_picker); 1001326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } 1002326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira 100362d3ec7f251f6f9a96a859a2702916d07f30a04amindyp @Override 100462d3ec7f251f6f9a96a859a2702916d07f30a04amindyp public boolean onEditorAction(TextView view, int action, KeyEvent keyEvent) { 100562d3ec7f251f6f9a96a859a2702916d07f30a04amindyp if (action == EditorInfo.IME_ACTION_DONE) { 100662d3ec7f251f6f9a96a859a2702916d07f30a04amindyp focusBody(); 100762d3ec7f251f6f9a96a859a2702916d07f30a04amindyp return true; 100862d3ec7f251f6f9a96a859a2702916d07f30a04amindyp } 100962d3ec7f251f6f9a96a859a2702916d07f30a04amindyp return false; 101062d3ec7f251f6f9a96a859a2702916d07f30a04amindyp } 101162d3ec7f251f6f9a96a859a2702916d07f30a04amindyp 1012e011b1d1c8e2e674dfdf1985d9d13da8cc06d803Mindy Pereira protected TextView getBody() { 1013e011b1d1c8e2e674dfdf1985d9d13da8cc06d803Mindy Pereira return mBodyView; 1014e011b1d1c8e2e674dfdf1985d9d13da8cc06d803Mindy Pereira } 1015e011b1d1c8e2e674dfdf1985d9d13da8cc06d803Mindy Pereira 1016e011b1d1c8e2e674dfdf1985d9d13da8cc06d803Mindy Pereira @VisibleForTesting 1017e011b1d1c8e2e674dfdf1985d9d13da8cc06d803Mindy Pereira public Account getFromAccount() { 1018e011b1d1c8e2e674dfdf1985d9d13da8cc06d803Mindy Pereira return mReplyFromAccount != null && mReplyFromAccount.account != null ? 1019e011b1d1c8e2e674dfdf1985d9d13da8cc06d803Mindy Pereira mReplyFromAccount.account : mAccount; 1020e011b1d1c8e2e674dfdf1985d9d13da8cc06d803Mindy Pereira } 1021e011b1d1c8e2e674dfdf1985d9d13da8cc06d803Mindy Pereira 1022cbfb75a0f92a3ef5cf10ab94b451e4898cc78bfcMindy Pereira private void clearChangeListeners() { 1023cbfb75a0f92a3ef5cf10ab94b451e4898cc78bfcMindy Pereira mSubject.removeTextChangedListener(this); 1024cbfb75a0f92a3ef5cf10ab94b451e4898cc78bfcMindy Pereira mBodyView.removeTextChangedListener(this); 1025cbfb75a0f92a3ef5cf10ab94b451e4898cc78bfcMindy Pereira mTo.removeTextChangedListener(mToListener); 1026cbfb75a0f92a3ef5cf10ab94b451e4898cc78bfcMindy Pereira mCc.removeTextChangedListener(mCcListener); 1027cbfb75a0f92a3ef5cf10ab94b451e4898cc78bfcMindy Pereira mBcc.removeTextChangedListener(mBccListener); 1028cbfb75a0f92a3ef5cf10ab94b451e4898cc78bfcMindy Pereira mFromSpinner.setOnAccountChangedListener(null); 1029cbfb75a0f92a3ef5cf10ab94b451e4898cc78bfcMindy Pereira mAttachmentsView.setAttachmentChangesListener(null); 1030cbfb75a0f92a3ef5cf10ab94b451e4898cc78bfcMindy Pereira } 1031cbfb75a0f92a3ef5cf10ab94b451e4898cc78bfcMindy Pereira 103275f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira // Now that the message has been initialized from any existing draft or 103375f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira // ref message data, set up listeners for any changes that occur to the 103475f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira // message. 103575f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira private void initChangeListeners() { 10361d7e9145fa4f490ba87ade0ed70ce0fa1f33be81mindyp // Make sure we only add text changed listeners once! 10371d7e9145fa4f490ba87ade0ed70ce0fa1f33be81mindyp clearChangeListeners(); 103875f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira mSubject.addTextChangedListener(this); 103975f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira mBodyView.addTextChangedListener(this); 1040cbfb75a0f92a3ef5cf10ab94b451e4898cc78bfcMindy Pereira if (mToListener == null) { 1041cbfb75a0f92a3ef5cf10ab94b451e4898cc78bfcMindy Pereira mToListener = new RecipientTextWatcher(mTo, this); 1042cbfb75a0f92a3ef5cf10ab94b451e4898cc78bfcMindy Pereira } 1043cbfb75a0f92a3ef5cf10ab94b451e4898cc78bfcMindy Pereira mTo.addTextChangedListener(mToListener); 1044cbfb75a0f92a3ef5cf10ab94b451e4898cc78bfcMindy Pereira if (mCcListener == null) { 1045cbfb75a0f92a3ef5cf10ab94b451e4898cc78bfcMindy Pereira mCcListener = new RecipientTextWatcher(mCc, this); 1046cbfb75a0f92a3ef5cf10ab94b451e4898cc78bfcMindy Pereira } 1047cbfb75a0f92a3ef5cf10ab94b451e4898cc78bfcMindy Pereira mCc.addTextChangedListener(mCcListener); 1048cbfb75a0f92a3ef5cf10ab94b451e4898cc78bfcMindy Pereira if (mBccListener == null) { 1049cbfb75a0f92a3ef5cf10ab94b451e4898cc78bfcMindy Pereira mBccListener = new RecipientTextWatcher(mBcc, this); 1050cbfb75a0f92a3ef5cf10ab94b451e4898cc78bfcMindy Pereira } 1051cbfb75a0f92a3ef5cf10ab94b451e4898cc78bfcMindy Pereira mBcc.addTextChangedListener(mBccListener); 105275f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira mFromSpinner.setOnAccountChangedListener(this); 1053818143e2163648acc0c91f123b84777d65cd70cfMindy Pereira mAttachmentsView.setAttachmentChangesListener(this); 105475f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira } 105575f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira 1056326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira private void initActionBar(int action) { 1057326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira mComposeMode = action; 1058eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira ActionBar actionBar = getActionBar(); 1059e011b1d1c8e2e674dfdf1985d9d13da8cc06d803Mindy Pereira if (actionBar == null) { 1060e011b1d1c8e2e674dfdf1985d9d13da8cc06d803Mindy Pereira return; 1061e011b1d1c8e2e674dfdf1985d9d13da8cc06d803Mindy Pereira } 1062326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira if (action == ComposeActivity.COMPOSE) { 1063eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_STANDARD); 1064eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira actionBar.setTitle(R.string.compose); 1065326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } else { 1066eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira actionBar.setTitle(null); 1067326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira if (mComposeModeAdapter == null) { 1068326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira mComposeModeAdapter = new ComposeModeAdapter(this); 1069326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } 1070eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_LIST); 1071eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira actionBar.setListNavigationCallbacks(mComposeModeAdapter, this); 1072326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira switch (action) { 1073326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira case ComposeActivity.REPLY: 1074eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira actionBar.setSelectedNavigationItem(0); 1075326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira break; 1076326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira case ComposeActivity.REPLY_ALL: 1077eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira actionBar.setSelectedNavigationItem(1); 1078326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira break; 1079326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira case ComposeActivity.FORWARD: 1080eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira actionBar.setSelectedNavigationItem(2); 1081326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira break; 1082326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } 10836349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira } 1084fbe4019a262f6b1934a44e598009ae63dc5745eeMindy Pereira actionBar.setDisplayOptions(ActionBar.DISPLAY_HOME_AS_UP | ActionBar.DISPLAY_SHOW_HOME, 1085fbe4019a262f6b1934a44e598009ae63dc5745eeMindy Pereira ActionBar.DISPLAY_HOME_AS_UP | ActionBar.DISPLAY_SHOW_HOME); 1086fbe4019a262f6b1934a44e598009ae63dc5745eeMindy Pereira actionBar.setHomeButtonEnabled(true); 10876349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira } 10886349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira 10890aeaf7d8c2ee4bc882ca901531f985c61b4cc7c7Scott Kennedy private void initFromRefMessage(int action) { 10900aeaf7d8c2ee4bc882ca901531f985c61b4cc7c7Scott Kennedy setFieldsFromRefMessage(action); 109196a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira if (mRefMessage != null) { 109296a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira // CC field only gets populated when doing REPLY_ALL. 109396a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira // BCC never gets auto-populated, unless the user is editing 109496a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira // a draft with one. 109529a717e1047a2b50574e358c94a8ee8a41f377e9Mindy Pereira if (!TextUtils.isEmpty(mCc.getText()) && action == REPLY_ALL) { 109696a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira mCcBccView.show(false, true, false); 109796a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira } 109896a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira } 109996a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira updateHideOrShowCcBcc(); 110096a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira } 110196a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira 11020aeaf7d8c2ee4bc882ca901531f985c61b4cc7c7Scott Kennedy private void setFieldsFromRefMessage(int action) { 11038eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira setSubject(mRefMessage, action); 11048eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira // Setup recipients 11058eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira if (action == FORWARD) { 11068eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira mForward = true; 11078eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira } 11080aeaf7d8c2ee4bc882ca901531f985c61b4cc7c7Scott Kennedy initRecipientsFromRefMessage(mRefMessage, action); 1109e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira initQuotedTextFromRefMessage(mRefMessage, action); 11108eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira if (action == ComposeActivity.FORWARD || mAttachmentsChanged) { 11118eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira initAttachments(mRefMessage); 11126349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira } 1113c17d073dd43871df36ea70b3dea55963bdb98384Mindy Pereira } 1114c17d073dd43871df36ea70b3dea55963bdb98384Mindy Pereira 1115e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira private void initFromDraftMessage(Message message) { 11161f8f4dd8c53e6c18ae642235335ce492c9d1e520Andy Huang LogUtils.d(LOG_TAG, "Intializing draft from previous draft message: %s", message); 1117bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook 1118bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook mDraft = message; 1119bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook mDraftId = message.id; 1120bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook mSubject.setText(message.subject); 1121bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook mForward = message.draftType == UIProvider.DraftType.FORWARD; 1122bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook final List<String> toAddresses = Arrays.asList(message.getToAddresses()); 1123bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook addToAddresses(toAddresses); 1124bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook addCcAddresses(Arrays.asList(message.getCcAddresses()), toAddresses); 1125bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook addBccAddresses(Arrays.asList(message.getBccAddresses())); 11262421dc8d6d0b4c727ab7ab0e5ce730f415089e86Mindy Pereira if (message.hasAttachments) { 11272421dc8d6d0b4c727ab7ab0e5ce730f415089e86Mindy Pereira List<Attachment> attachments = message.getAttachments(); 11282421dc8d6d0b4c727ab7ab0e5ce730f415089e86Mindy Pereira for (Attachment a : attachments) { 11295c5fd571b40a15b95ea5a5d6033f377706ffd0fbAndy Huang addAttachmentAndUpdateView(a); 11302421dc8d6d0b4c727ab7ab0e5ce730f415089e86Mindy Pereira } 11312421dc8d6d0b4c727ab7ab0e5ce730f415089e86Mindy Pereira } 1132cc8e7db940b2ad6c673e84ca7addae9295c10a33Mindy Pereira int quotedTextIndex = message.appendRefMessageContent ? 1133002ff5244800c32f2d70c96cc1110657020ee65cMindy Pereira message.quotedTextOffset : -1; 1134bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook // Set the body 1135002ff5244800c32f2d70c96cc1110657020ee65cMindy Pereira CharSequence quotedText = null; 1136bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook if (!TextUtils.isEmpty(message.bodyHtml)) { 1137752222d839d9afeb5c4665669eab81645e413495Mindy Pereira CharSequence htmlText = ""; 1138002ff5244800c32f2d70c96cc1110657020ee65cMindy Pereira if (quotedTextIndex > -1) { 1139752222d839d9afeb5c4665669eab81645e413495Mindy Pereira // Find the offset in the htmltext of the actual quoted text and strip it out. 1140752222d839d9afeb5c4665669eab81645e413495Mindy Pereira quotedTextIndex = QuotedTextView.findQuotedTextIndex(message.bodyHtml); 1141752222d839d9afeb5c4665669eab81645e413495Mindy Pereira if (quotedTextIndex > -1) { 1142c59dd8270215f97d39697dae9e69976bcfe3642bmindyp htmlText = Utils.convertHtmlToPlainText(message.bodyHtml.substring(0, 1143c59dd8270215f97d39697dae9e69976bcfe3642bmindyp quotedTextIndex)); 1144752222d839d9afeb5c4665669eab81645e413495Mindy Pereira quotedText = message.bodyHtml.subSequence(quotedTextIndex, 1145752222d839d9afeb5c4665669eab81645e413495Mindy Pereira message.bodyHtml.length()); 1146752222d839d9afeb5c4665669eab81645e413495Mindy Pereira } 11471a6e938c8a97092e332707a55edb5a53996edf98Mindy Pereira } else { 1148c59dd8270215f97d39697dae9e69976bcfe3642bmindyp htmlText = Utils.convertHtmlToPlainText(message.bodyHtml); 1149002ff5244800c32f2d70c96cc1110657020ee65cMindy Pereira } 1150002ff5244800c32f2d70c96cc1110657020ee65cMindy Pereira mBodyView.setText(htmlText); 1151bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook } else { 1152752222d839d9afeb5c4665669eab81645e413495Mindy Pereira final String body = message.bodyText; 1153752222d839d9afeb5c4665669eab81645e413495Mindy Pereira final CharSequence bodyText = !TextUtils.isEmpty(body) ? 1154752222d839d9afeb5c4665669eab81645e413495Mindy Pereira (quotedTextIndex > -1 ? 1155752222d839d9afeb5c4665669eab81645e413495Mindy Pereira message.bodyText.substring(0, quotedTextIndex) : message.bodyText) 1156752222d839d9afeb5c4665669eab81645e413495Mindy Pereira : ""; 1157002ff5244800c32f2d70c96cc1110657020ee65cMindy Pereira if (quotedTextIndex > -1) { 1158752222d839d9afeb5c4665669eab81645e413495Mindy Pereira quotedText = !TextUtils.isEmpty(body) ? message.bodyText.substring(quotedTextIndex) 1159752222d839d9afeb5c4665669eab81645e413495Mindy Pereira : null; 1160002ff5244800c32f2d70c96cc1110657020ee65cMindy Pereira } 1161002ff5244800c32f2d70c96cc1110657020ee65cMindy Pereira mBodyView.setText(bodyText); 1162002ff5244800c32f2d70c96cc1110657020ee65cMindy Pereira } 1163002ff5244800c32f2d70c96cc1110657020ee65cMindy Pereira if (quotedTextIndex > -1 && quotedText != null) { 11643971323f24b15b541f7460c1a4db42d78eb1873bMindy Pereira mQuotedTextView.setQuotedTextFromDraft(quotedText, mForward); 1165bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook } 1166bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook } 1167bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook 11688eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira /** 11698eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira * Fill all the widgets with the content found in the Intent Extra, if any. 11708eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira * Also apply the same style to all widgets. Note: if initFromExtras is 11718eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira * called as a result of switching between reply, reply all, and forward per 11728eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira * the latest revision of Gmail, and the user has already made changes to 11738eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira * attachments on a previous incarnation of the message (as a reply, reply 11748eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira * all, or forward), the original attachments from the message will not be 11758eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira * re-instantiated. The user's changes will be respected. This follows the 11768eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira * web gmail interaction. 11778eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira */ 11788eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira public void initFromExtras(Intent intent) { 11798eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira // If we were invoked with a SENDTO intent, the value 11808eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira // should take precedence 11818eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira final Uri dataUri = intent.getData(); 11828eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira if (dataUri != null) { 11838eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira if (MAIL_TO.equals(dataUri.getScheme())) { 11848eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira initFromMailTo(dataUri.toString()); 11858eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira } else { 11860b4f28ed53a7f1617dadf3b34de8c743a1733ce5Mindy Pereira if (!mAccount.composeIntentUri.equals(dataUri)) { 11878eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira String toText = dataUri.getSchemeSpecificPart(); 11888eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira if (toText != null) { 11898eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira mTo.setText(""); 1190dbe8996d8ba382bfe1a23894abbc4711e36c9daeMindy Pereira addToAddresses(Arrays.asList(TextUtils.split(toText, ","))); 11918eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira } 11928eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira } 11938eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira } 11948eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira } 11958eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira 11968eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira String[] extraStrings = intent.getStringArrayExtra(Intent.EXTRA_EMAIL); 11978eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira if (extraStrings != null) { 11988eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira addToAddresses(Arrays.asList(extraStrings)); 11998eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira } 12008eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira extraStrings = intent.getStringArrayExtra(Intent.EXTRA_CC); 12018eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira if (extraStrings != null) { 12028eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira addCcAddresses(Arrays.asList(extraStrings), null); 12038eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira } 12048eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira extraStrings = intent.getStringArrayExtra(Intent.EXTRA_BCC); 12058eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira if (extraStrings != null) { 12068eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira addBccAddresses(Arrays.asList(extraStrings)); 12078eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira } 12088eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira 12098eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira String extraString = intent.getStringExtra(Intent.EXTRA_SUBJECT); 12108eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira if (extraString != null) { 12118eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira mSubject.setText(extraString); 12128eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira } 12138eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira 12148eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira for (String extra : ALL_EXTRAS) { 12158eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira if (intent.hasExtra(extra)) { 12168eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira String value = intent.getStringExtra(extra); 12178eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira if (EXTRA_TO.equals(extra)) { 1218dbe8996d8ba382bfe1a23894abbc4711e36c9daeMindy Pereira addToAddresses(Arrays.asList(TextUtils.split(value, ","))); 12198eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira } else if (EXTRA_CC.equals(extra)) { 1220dbe8996d8ba382bfe1a23894abbc4711e36c9daeMindy Pereira addCcAddresses(Arrays.asList(TextUtils.split(value, ",")), null); 12218eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira } else if (EXTRA_BCC.equals(extra)) { 1222dbe8996d8ba382bfe1a23894abbc4711e36c9daeMindy Pereira addBccAddresses(Arrays.asList(TextUtils.split(value, ","))); 12238eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira } else if (EXTRA_SUBJECT.equals(extra)) { 12248eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira mSubject.setText(value); 12258eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira } else if (EXTRA_BODY.equals(extra)) { 12268eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira setBody(value, true /* with signature */); 12278eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira } 12288eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira } 12298eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira } 12308eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira 12318eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira Bundle extras = intent.getExtras(); 12328eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira if (extras != null) { 12338eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira CharSequence text = extras.getCharSequence(Intent.EXTRA_TEXT); 12348eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira if (text != null) { 12358eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira setBody(text, true /* with signature */); 12368eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira } 12378eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira } 1238e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira } 1239e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira 12408eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira @VisibleForTesting 12418eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira protected String decodeEmailInUri(String s) throws UnsupportedEncodingException { 1242a4069f2f16c05c6d2948baa39b0c463be4c7a360Mindy Pereira // TODO: handle the case where there are spaces in the display name as 1243a4069f2f16c05c6d2948baa39b0c463be4c7a360Mindy Pereira // well as the email such as "Guy with spaces <guy+with+spaces@gmail.com>" 1244a4069f2f16c05c6d2948baa39b0c463be4c7a360Mindy Pereira // as they could be encoded ambiguously. 12458eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira // Since URLDecode.decode changes + into ' ', and + is a valid 12468eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira // email character, we need to find/ replace these ourselves before 12478eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira // decoding. 12488eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira String replacePlus = s.replace("+", "%2B"); 1249a4069f2f16c05c6d2948baa39b0c463be4c7a360Mindy Pereira try { 1250a4069f2f16c05c6d2948baa39b0c463be4c7a360Mindy Pereira return URLDecoder.decode(replacePlus, UTF8_ENCODING_NAME); 1251a4069f2f16c05c6d2948baa39b0c463be4c7a360Mindy Pereira } catch (IllegalArgumentException e) { 1252a4069f2f16c05c6d2948baa39b0c463be4c7a360Mindy Pereira if (LogUtils.isLoggable(LOG_TAG, LogUtils.VERBOSE)) { 1253a4069f2f16c05c6d2948baa39b0c463be4c7a360Mindy Pereira LogUtils.e(LOG_TAG, "%s while decoding '%s'", e.getMessage(), s); 1254a4069f2f16c05c6d2948baa39b0c463be4c7a360Mindy Pereira } else { 1255a4069f2f16c05c6d2948baa39b0c463be4c7a360Mindy Pereira LogUtils.e(LOG_TAG, e, "Exception while decoding mailto address"); 1256a4069f2f16c05c6d2948baa39b0c463be4c7a360Mindy Pereira } 1257a4069f2f16c05c6d2948baa39b0c463be4c7a360Mindy Pereira return null; 1258a4069f2f16c05c6d2948baa39b0c463be4c7a360Mindy Pereira } 12598eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira } 12608eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira 12618eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira /** 12628eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira * Initialize the compose view from a String representing a mailTo uri. 12638eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira * @param mailToString The uri as a string. 12648eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira */ 12658eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira public void initFromMailTo(String mailToString) { 12668eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira // We need to disguise this string as a URI in order to parse it 12678eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira // TODO: Remove this hack when http://b/issue?id=1445295 gets fixed 12688eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira Uri uri = Uri.parse("foo://" + mailToString); 12698eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira int index = mailToString.indexOf("?"); 12708eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira int length = "mailto".length() + 1; 12718eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira String to; 12728eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira try { 12738eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira // Extract the recipient after mailto: 12748eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira if (index == -1) { 12758eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira to = decodeEmailInUri(mailToString.substring(length)); 12768eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira } else { 12778eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira to = decodeEmailInUri(mailToString.substring(length, index)); 12788eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira } 1279a4069f2f16c05c6d2948baa39b0c463be4c7a360Mindy Pereira if (!TextUtils.isEmpty(to)) { 1280a4069f2f16c05c6d2948baa39b0c463be4c7a360Mindy Pereira addToAddresses(Arrays.asList(TextUtils.split(to, ","))); 1281a4069f2f16c05c6d2948baa39b0c463be4c7a360Mindy Pereira } 12828eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira } catch (UnsupportedEncodingException e) { 12838eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira if (LogUtils.isLoggable(LOG_TAG, LogUtils.VERBOSE)) { 12848eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira LogUtils.e(LOG_TAG, "%s while decoding '%s'", e.getMessage(), mailToString); 12858eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira } else { 12868eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira LogUtils.e(LOG_TAG, e, "Exception while decoding mailto address"); 12878eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira } 12888eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira } 12898eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira 12908eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira List<String> cc = uri.getQueryParameters("cc"); 12918eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira addCcAddresses(Arrays.asList(cc.toArray(new String[cc.size()])), null); 12928eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira 12938eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira List<String> otherTo = uri.getQueryParameters("to"); 12948eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira addToAddresses(Arrays.asList(otherTo.toArray(new String[otherTo.size()]))); 12958eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira 12968eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira List<String> bcc = uri.getQueryParameters("bcc"); 12978eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira addBccAddresses(Arrays.asList(bcc.toArray(new String[bcc.size()]))); 12988eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira 12998eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira List<String> subject = uri.getQueryParameters("subject"); 13008eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira if (subject.size() > 0) { 13018eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira try { 13028eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira mSubject.setText(URLDecoder.decode(subject.get(0), UTF8_ENCODING_NAME)); 13038eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira } catch (UnsupportedEncodingException e) { 13048eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira LogUtils.e(LOG_TAG, "%s while decoding subject '%s'", 13058eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira e.getMessage(), subject); 13068eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira } 13078eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira } 13088eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira 13098eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira List<String> body = uri.getQueryParameters("body"); 13108eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira if (body.size() > 0) { 13118eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira try { 13128eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira setBody(URLDecoder.decode(body.get(0), UTF8_ENCODING_NAME), 13138eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira true /* with signature */); 13148eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira } catch (UnsupportedEncodingException e) { 13158eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira LogUtils.e(LOG_TAG, "%s while decoding body '%s'", e.getMessage(), body); 13168eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira } 13178eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira } 13188eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira } 13198eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira 1320bddd6f39f34aa15fed2e757f7d3e4163272ca02cMindy Pereira @VisibleForTesting 1321bddd6f39f34aa15fed2e757f7d3e4163272ca02cMindy Pereira protected void initAttachments(Message refMessage) { 1322434f294a3ae17a4f76342af38d6376f672a5d9edMark Wei addAttachments(refMessage.getAttachments()); 1323434f294a3ae17a4f76342af38d6376f672a5d9edMark Wei } 1324434f294a3ae17a4f76342af38d6376f672a5d9edMark Wei 1325434f294a3ae17a4f76342af38d6376f672a5d9edMark Wei public long addAttachments(List<Attachment> attachments) { 1326434f294a3ae17a4f76342af38d6376f672a5d9edMark Wei long size = 0; 1327434f294a3ae17a4f76342af38d6376f672a5d9edMark Wei AttachmentFailureException error = null; 1328434f294a3ae17a4f76342af38d6376f672a5d9edMark Wei for (Attachment a : attachments) { 1329434f294a3ae17a4f76342af38d6376f672a5d9edMark Wei try { 1330434f294a3ae17a4f76342af38d6376f672a5d9edMark Wei size += mAttachmentsView.addAttachment(mAccount, a); 1331434f294a3ae17a4f76342af38d6376f672a5d9edMark Wei } catch (AttachmentFailureException e) { 1332434f294a3ae17a4f76342af38d6376f672a5d9edMark Wei error = e; 1333434f294a3ae17a4f76342af38d6376f672a5d9edMark Wei } 1334434f294a3ae17a4f76342af38d6376f672a5d9edMark Wei } 1335434f294a3ae17a4f76342af38d6376f672a5d9edMark Wei if (error != null) { 1336434f294a3ae17a4f76342af38d6376f672a5d9edMark Wei LogUtils.e(LOG_TAG, error, "Error adding attachment"); 1337434f294a3ae17a4f76342af38d6376f672a5d9edMark Wei if (attachments.size() > 1) { 1338434f294a3ae17a4f76342af38d6376f672a5d9edMark Wei showAttachmentTooBigToast(R.string.too_large_to_attach_multiple); 1339434f294a3ae17a4f76342af38d6376f672a5d9edMark Wei } else { 1340434f294a3ae17a4f76342af38d6376f672a5d9edMark Wei showAttachmentTooBigToast(error.getErrorRes()); 1341434f294a3ae17a4f76342af38d6376f672a5d9edMark Wei } 13423cd4f40dab2c0810cb5ecd77256abf022863b2b5Mindy Pereira } 1343434f294a3ae17a4f76342af38d6376f672a5d9edMark Wei return size; 13443cd4f40dab2c0810cb5ecd77256abf022863b2b5Mindy Pereira } 13453cd4f40dab2c0810cb5ecd77256abf022863b2b5Mindy Pereira 13463cd4f40dab2c0810cb5ecd77256abf022863b2b5Mindy Pereira /** 13473cd4f40dab2c0810cb5ecd77256abf022863b2b5Mindy Pereira * When an attachment is too large to be added to a message, show a toast. 13483cd4f40dab2c0810cb5ecd77256abf022863b2b5Mindy Pereira * This method also updates the position of the toast so that it is shown 13493cd4f40dab2c0810cb5ecd77256abf022863b2b5Mindy Pereira * clearly above they keyboard if it happens to be open. 13503cd4f40dab2c0810cb5ecd77256abf022863b2b5Mindy Pereira */ 1351434f294a3ae17a4f76342af38d6376f672a5d9edMark Wei private void showAttachmentTooBigToast(int errorRes) { 1352434f294a3ae17a4f76342af38d6376f672a5d9edMark Wei String maxSize = AttachmentUtils.convertToHumanReadableSize( 1353434f294a3ae17a4f76342af38d6376f672a5d9edMark Wei getApplicationContext(), mAccount.settings.getMaxAttachmentSize()); 1354434f294a3ae17a4f76342af38d6376f672a5d9edMark Wei showErrorToast(getString(errorRes, maxSize)); 13553cd4f40dab2c0810cb5ecd77256abf022863b2b5Mindy Pereira } 13563cd4f40dab2c0810cb5ecd77256abf022863b2b5Mindy Pereira 1357434f294a3ae17a4f76342af38d6376f672a5d9edMark Wei private void showErrorToast(String message) { 1358434f294a3ae17a4f76342af38d6376f672a5d9edMark Wei Toast t = Toast.makeText(this, message, Toast.LENGTH_LONG); 1359434f294a3ae17a4f76342af38d6376f672a5d9edMark Wei t.setText(message); 13603cd4f40dab2c0810cb5ecd77256abf022863b2b5Mindy Pereira t.setGravity(Gravity.CENTER_HORIZONTAL, 0, 13613cd4f40dab2c0810cb5ecd77256abf022863b2b5Mindy Pereira getResources().getDimensionPixelSize(R.dimen.attachment_toast_yoffset)); 13623cd4f40dab2c0810cb5ecd77256abf022863b2b5Mindy Pereira t.show(); 1363eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira } 1364eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira 1365f97588bd03fdcd318e24a9d74a283e73d1fbd37cPaul Westbrook private void initAttachmentsFromIntent(Intent intent) { 136603ee971afd8d766dea81b72fe77593e3be3ab798Paul Westbrook Bundle extras = intent.getExtras(); 136703ee971afd8d766dea81b72fe77593e3be3ab798Paul Westbrook if (extras == null) { 136803ee971afd8d766dea81b72fe77593e3be3ab798Paul Westbrook extras = Bundle.EMPTY; 136903ee971afd8d766dea81b72fe77593e3be3ab798Paul Westbrook } 1370f97588bd03fdcd318e24a9d74a283e73d1fbd37cPaul Westbrook final String action = intent.getAction(); 1371f97588bd03fdcd318e24a9d74a283e73d1fbd37cPaul Westbrook if (!mAttachmentsChanged) { 1372f97588bd03fdcd318e24a9d74a283e73d1fbd37cPaul Westbrook long totalSize = 0; 1373f97588bd03fdcd318e24a9d74a283e73d1fbd37cPaul Westbrook if (extras.containsKey(EXTRA_ATTACHMENTS)) { 1374f97588bd03fdcd318e24a9d74a283e73d1fbd37cPaul Westbrook String[] uris = (String[]) extras.getSerializable(EXTRA_ATTACHMENTS); 1375f97588bd03fdcd318e24a9d74a283e73d1fbd37cPaul Westbrook for (String uriString : uris) { 1376f97588bd03fdcd318e24a9d74a283e73d1fbd37cPaul Westbrook final Uri uri = Uri.parse(uriString); 1377f97588bd03fdcd318e24a9d74a283e73d1fbd37cPaul Westbrook long size = 0; 1378f97588bd03fdcd318e24a9d74a283e73d1fbd37cPaul Westbrook try { 13795c5fd571b40a15b95ea5a5d6033f377706ffd0fbAndy Huang size = mAttachmentsView.addAttachment(mAccount, uri); 1380f97588bd03fdcd318e24a9d74a283e73d1fbd37cPaul Westbrook } catch (AttachmentFailureException e) { 1381f97588bd03fdcd318e24a9d74a283e73d1fbd37cPaul Westbrook LogUtils.e(LOG_TAG, e, "Error adding attachment"); 1382434f294a3ae17a4f76342af38d6376f672a5d9edMark Wei showAttachmentTooBigToast(e.getErrorRes()); 1383f97588bd03fdcd318e24a9d74a283e73d1fbd37cPaul Westbrook } 1384f97588bd03fdcd318e24a9d74a283e73d1fbd37cPaul Westbrook totalSize += size; 1385f97588bd03fdcd318e24a9d74a283e73d1fbd37cPaul Westbrook } 1386f97588bd03fdcd318e24a9d74a283e73d1fbd37cPaul Westbrook } 13879a9e8d698ce11fb5fa8e7afecf587147f1a4e02amindyp if (extras.containsKey(Intent.EXTRA_STREAM)) { 13889a9e8d698ce11fb5fa8e7afecf587147f1a4e02amindyp if (Intent.ACTION_SEND_MULTIPLE.equals(action)) { 13899a9e8d698ce11fb5fa8e7afecf587147f1a4e02amindyp ArrayList<Parcelable> uris = extras 13909a9e8d698ce11fb5fa8e7afecf587147f1a4e02amindyp .getParcelableArrayList(Intent.EXTRA_STREAM); 13919a9e8d698ce11fb5fa8e7afecf587147f1a4e02amindyp ArrayList<Attachment> attachments = new ArrayList<Attachment>(); 13929a9e8d698ce11fb5fa8e7afecf587147f1a4e02amindyp for (Parcelable uri : uris) { 13939a9e8d698ce11fb5fa8e7afecf587147f1a4e02amindyp try { 13949a9e8d698ce11fb5fa8e7afecf587147f1a4e02amindyp attachments.add(mAttachmentsView.generateLocalAttachment((Uri) uri)); 13959a9e8d698ce11fb5fa8e7afecf587147f1a4e02amindyp } catch (AttachmentFailureException e) { 13969a9e8d698ce11fb5fa8e7afecf587147f1a4e02amindyp LogUtils.e(LOG_TAG, e, "Error adding attachment"); 13979a9e8d698ce11fb5fa8e7afecf587147f1a4e02amindyp String maxSize = AttachmentUtils.convertToHumanReadableSize( 13989a9e8d698ce11fb5fa8e7afecf587147f1a4e02amindyp getApplicationContext(), 13999a9e8d698ce11fb5fa8e7afecf587147f1a4e02amindyp mAccount.settings.getMaxAttachmentSize()); 14009a9e8d698ce11fb5fa8e7afecf587147f1a4e02amindyp showErrorToast(getString 14019a9e8d698ce11fb5fa8e7afecf587147f1a4e02amindyp (R.string.generic_attachment_problem, maxSize)); 14029a9e8d698ce11fb5fa8e7afecf587147f1a4e02amindyp } 14039a9e8d698ce11fb5fa8e7afecf587147f1a4e02amindyp } 14049a9e8d698ce11fb5fa8e7afecf587147f1a4e02amindyp totalSize += addAttachments(attachments); 14059a9e8d698ce11fb5fa8e7afecf587147f1a4e02amindyp } else { 14069a9e8d698ce11fb5fa8e7afecf587147f1a4e02amindyp final Uri uri = (Uri) extras.getParcelable(Intent.EXTRA_STREAM); 14079a9e8d698ce11fb5fa8e7afecf587147f1a4e02amindyp long size = 0; 1408f97588bd03fdcd318e24a9d74a283e73d1fbd37cPaul Westbrook try { 14099a9e8d698ce11fb5fa8e7afecf587147f1a4e02amindyp size = mAttachmentsView.addAttachment(mAccount, uri); 1410f97588bd03fdcd318e24a9d74a283e73d1fbd37cPaul Westbrook } catch (AttachmentFailureException e) { 1411f97588bd03fdcd318e24a9d74a283e73d1fbd37cPaul Westbrook LogUtils.e(LOG_TAG, e, "Error adding attachment"); 14129a9e8d698ce11fb5fa8e7afecf587147f1a4e02amindyp showAttachmentTooBigToast(e.getErrorRes()); 1413f97588bd03fdcd318e24a9d74a283e73d1fbd37cPaul Westbrook } 14149a9e8d698ce11fb5fa8e7afecf587147f1a4e02amindyp totalSize += size; 1415f97588bd03fdcd318e24a9d74a283e73d1fbd37cPaul Westbrook } 1416f97588bd03fdcd318e24a9d74a283e73d1fbd37cPaul Westbrook } 1417f97588bd03fdcd318e24a9d74a283e73d1fbd37cPaul Westbrook 1418f97588bd03fdcd318e24a9d74a283e73d1fbd37cPaul Westbrook if (totalSize > 0) { 1419f97588bd03fdcd318e24a9d74a283e73d1fbd37cPaul Westbrook mAttachmentsChanged = true; 1420f97588bd03fdcd318e24a9d74a283e73d1fbd37cPaul Westbrook updateSaveUi(); 1421f97588bd03fdcd318e24a9d74a283e73d1fbd37cPaul Westbrook } 1422f97588bd03fdcd318e24a9d74a283e73d1fbd37cPaul Westbrook } 1423f97588bd03fdcd318e24a9d74a283e73d1fbd37cPaul Westbrook } 1424f97588bd03fdcd318e24a9d74a283e73d1fbd37cPaul Westbrook 1425f97588bd03fdcd318e24a9d74a283e73d1fbd37cPaul Westbrook 1426e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira private void initQuotedTextFromRefMessage(Message refMessage, int action) { 1427e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira if (mRefMessage != null && (action == REPLY || action == REPLY_ALL || action == FORWARD)) { 14289932dee248718d2cec993d93b5115973d1389d0aMindy Pereira mQuotedTextView.setQuotedText(action, refMessage, action != FORWARD); 14299932dee248718d2cec993d93b5115973d1389d0aMindy Pereira } 143046ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira } 143146ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira 143246ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira private void updateHideOrShowCcBcc() { 1433ec8b0edb23c0e0b7f1a8ce9558a919be31169d45Mindy Pereira // Its possible there is a menu item OR a button. 1434326689d531da1d2579fa7daaf6e307e24a05f993Mindy Pereira boolean ccVisible = mCcBccView.isCcVisible(); 1435326689d531da1d2579fa7daaf6e307e24a05f993Mindy Pereira boolean bccVisible = mCcBccView.isBccVisible(); 1436ec8b0edb23c0e0b7f1a8ce9558a919be31169d45Mindy Pereira if (mCcBccButton != null) { 1437326689d531da1d2579fa7daaf6e307e24a05f993Mindy Pereira if (!ccVisible || !bccVisible) { 1438ec8b0edb23c0e0b7f1a8ce9558a919be31169d45Mindy Pereira mCcBccButton.setVisibility(View.VISIBLE); 1439326689d531da1d2579fa7daaf6e307e24a05f993Mindy Pereira mCcBccButton.setText(getString(!ccVisible ? R.string.add_cc_label 1440ec8b0edb23c0e0b7f1a8ce9558a919be31169d45Mindy Pereira : R.string.add_bcc_label)); 1441ec8b0edb23c0e0b7f1a8ce9558a919be31169d45Mindy Pereira } else { 1442cd0b0b950efebfc3964334067747b97e61c4f027mindyp mCcBccButton.setVisibility(View.INVISIBLE); 1443ec8b0edb23c0e0b7f1a8ce9558a919be31169d45Mindy Pereira } 1444ec8b0edb23c0e0b7f1a8ce9558a919be31169d45Mindy Pereira } 144546ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira } 144646ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira 1447a34c9a054c9aef6f83abe56515c132a31d71b3c8Mindy Pereira private void showCcBcc(Bundle state) { 1448326689d531da1d2579fa7daaf6e307e24a05f993Mindy Pereira if (state != null && state.containsKey(EXTRA_SHOW_CC)) { 1449326689d531da1d2579fa7daaf6e307e24a05f993Mindy Pereira boolean showCc = state.getBoolean(EXTRA_SHOW_CC); 1450326689d531da1d2579fa7daaf6e307e24a05f993Mindy Pereira boolean showBcc = state.getBoolean(EXTRA_SHOW_BCC); 1451326689d531da1d2579fa7daaf6e307e24a05f993Mindy Pereira if (showCc || showBcc) { 1452326689d531da1d2579fa7daaf6e307e24a05f993Mindy Pereira mCcBccView.show(false, showCc, showBcc); 1453326689d531da1d2579fa7daaf6e307e24a05f993Mindy Pereira } 1454326689d531da1d2579fa7daaf6e307e24a05f993Mindy Pereira } 1455326689d531da1d2579fa7daaf6e307e24a05f993Mindy Pereira } 1456326689d531da1d2579fa7daaf6e307e24a05f993Mindy Pereira 1457013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira /** 1458013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira * Add attachment and update the compose area appropriately. 1459013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira * @param data 1460013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira */ 1461013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira public void addAttachmentAndUpdateView(Intent data) { 14622421dc8d6d0b4c727ab7ab0e5ce730f415089e86Mindy Pereira addAttachmentAndUpdateView(data != null ? data.getData() : (Uri) null); 14632421dc8d6d0b4c727ab7ab0e5ce730f415089e86Mindy Pereira } 14642421dc8d6d0b4c727ab7ab0e5ce730f415089e86Mindy Pereira 14655c5fd571b40a15b95ea5a5d6033f377706ffd0fbAndy Huang public void addAttachmentAndUpdateView(Uri contentUri) { 14665c5fd571b40a15b95ea5a5d6033f377706ffd0fbAndy Huang if (contentUri == null) { 14672421dc8d6d0b4c727ab7ab0e5ce730f415089e86Mindy Pereira return; 14682421dc8d6d0b4c727ab7ab0e5ce730f415089e86Mindy Pereira } 1469013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira try { 14705c5fd571b40a15b95ea5a5d6033f377706ffd0fbAndy Huang addAttachmentAndUpdateView(mAttachmentsView.generateLocalAttachment(contentUri)); 14715c5fd571b40a15b95ea5a5d6033f377706ffd0fbAndy Huang } catch (AttachmentFailureException e) { 14725c5fd571b40a15b95ea5a5d6033f377706ffd0fbAndy Huang LogUtils.e(LOG_TAG, e, "Error adding attachment"); 1473434f294a3ae17a4f76342af38d6376f672a5d9edMark Wei showErrorToast(getResources().getString( 1474434f294a3ae17a4f76342af38d6376f672a5d9edMark Wei e.getErrorRes(), 1475434f294a3ae17a4f76342af38d6376f672a5d9edMark Wei AttachmentUtils.convertToHumanReadableSize( 1476434f294a3ae17a4f76342af38d6376f672a5d9edMark Wei getApplicationContext(), mAccount.settings.getMaxAttachmentSize()))); 14775c5fd571b40a15b95ea5a5d6033f377706ffd0fbAndy Huang } 14785c5fd571b40a15b95ea5a5d6033f377706ffd0fbAndy Huang } 14795c5fd571b40a15b95ea5a5d6033f377706ffd0fbAndy Huang 14805c5fd571b40a15b95ea5a5d6033f377706ffd0fbAndy Huang public void addAttachmentAndUpdateView(Attachment attachment) { 14815c5fd571b40a15b95ea5a5d6033f377706ffd0fbAndy Huang try { 1482434f294a3ae17a4f76342af38d6376f672a5d9edMark Wei long size = mAttachmentsView.addAttachment(mAccount, attachment); 14839932dee248718d2cec993d93b5115973d1389d0aMindy Pereira if (size > 0) { 14849932dee248718d2cec993d93b5115973d1389d0aMindy Pereira mAttachmentsChanged = true; 14859932dee248718d2cec993d93b5115973d1389d0aMindy Pereira updateSaveUi(); 1486013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira } 14879932dee248718d2cec993d93b5115973d1389d0aMindy Pereira } catch (AttachmentFailureException e) { 14889932dee248718d2cec993d93b5115973d1389d0aMindy Pereira LogUtils.e(LOG_TAG, e, "Error adding attachment"); 1489434f294a3ae17a4f76342af38d6376f672a5d9edMark Wei showAttachmentTooBigToast(e.getErrorRes()); 1490013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira } 1491013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira } 1492013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira 14930aeaf7d8c2ee4bc882ca901531f985c61b4cc7c7Scott Kennedy void initRecipientsFromRefMessage(Message refMessage, int action) { 14944a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira // Don't populate the address if this is a forward. 14954a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira if (action == ComposeActivity.FORWARD) { 14964a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira return; 14974a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira } 149833fe908589dca6a7f58aa9f56d73f74a48ac42f6Mindy Pereira initReplyRecipients(mAccount.name, refMessage, action); 14994a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira } 15004a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira 1501818143e2163648acc0c91f123b84777d65cd70cfMindy Pereira @VisibleForTesting 15023ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereira void initReplyRecipients(String account, Message refMessage, int action) { 15034a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira // This is the email address of the current user, i.e. the one composing 15044a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira // the reply. 15054a20b708dd9ff3fb2b96f29b0b59012194c6fa34Mindy Pereira final String accountEmail = Address.getEmailAddress(account).getAddress(); 15065ed6311d6beb968e83585a43d7cdf5909e0a2cf6mindyp String[] sentToAddresses = refMessage.getToAddresses(); 1507a26b54e3a858de409be3746e65591bb8a0d6ea9aMindy Pereira final Collection<String> toAddresses; 150865b06f52e5b6336493388923be88bdd2ded4e1d1mindyp String replytoAddress = refMessage.getReplyTo(); 150965b06f52e5b6336493388923be88bdd2ded4e1d1mindyp // If there is no reply to address, the reply to address is the sender. 151065b06f52e5b6336493388923be88bdd2ded4e1d1mindyp if (TextUtils.isEmpty(replytoAddress)) { 151165b06f52e5b6336493388923be88bdd2ded4e1d1mindyp replytoAddress = refMessage.getFrom(); 151265b06f52e5b6336493388923be88bdd2ded4e1d1mindyp } 15134a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira 15144a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira // If this is a reply, the Cc list is empty. If this is a reply-all, the 15154a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira // Cc list is the union of the To and Cc recipients of the original 15164a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira // message, excluding the current user's email address and any addresses 1517a26b54e3a858de409be3746e65591bb8a0d6ea9aMindy Pereira // already on the To list. 1518a26b54e3a858de409be3746e65591bb8a0d6ea9aMindy Pereira if (action == ComposeActivity.REPLY) { 15195ee5d69dc7ddbef52c6c62947757b3d86ac89f23mindyp toAddresses = initToRecipients(accountEmail, refMessage.getFrom(), 15208960f0af431bc164003e09b3c8981aab808d9ec1Scott Kennedy replytoAddress, sentToAddresses); 1521a26b54e3a858de409be3746e65591bb8a0d6ea9aMindy Pereira addToAddresses(toAddresses); 1522a26b54e3a858de409be3746e65591bb8a0d6ea9aMindy Pereira } else if (action == ComposeActivity.REPLY_ALL) { 15234a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira final Set<String> ccAddresses = Sets.newHashSet(); 15245ee5d69dc7ddbef52c6c62947757b3d86ac89f23mindyp toAddresses = initToRecipients(accountEmail, refMessage.getFrom(), 15258960f0af431bc164003e09b3c8981aab808d9ec1Scott Kennedy replytoAddress, sentToAddresses); 1526154386a287a9bfffb2eb3a4c05445f2774e1d4f0Mindy Pereira addToAddresses(toAddresses); 15274a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira addRecipients(accountEmail, ccAddresses, sentToAddresses); 15285ed6311d6beb968e83585a43d7cdf5909e0a2cf6mindyp addRecipients(accountEmail, ccAddresses, refMessage.getCcAddresses()); 15294a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira addCcAddresses(ccAddresses, toAddresses); 15304a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira } 15314a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira } 15324a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira 15334a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira private void addToAddresses(Collection<String> addresses) { 15344a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira addAddressesToList(addresses, mTo); 15354a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira } 15364a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira 15374a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira private void addCcAddresses(Collection<String> addresses, Collection<String> toAddresses) { 15388eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira addCcAddressesToList(tokenizeAddressList(addresses), 15398eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira toAddresses != null ? tokenizeAddressList(toAddresses) : null, mCc); 15404a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira } 15414a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira 1542bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook private void addBccAddresses(Collection<String> addresses) { 1543bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook addAddressesToList(addresses, mBcc); 1544bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook } 1545bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook 15464a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira @VisibleForTesting 15474a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira protected void addCcAddressesToList(List<Rfc822Token[]> addresses, 15484a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira List<Rfc822Token[]> compareToList, RecipientEditTextView list) { 15494a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira String address; 15504a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira 15518eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira if (compareToList == null) { 15528eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira for (Rfc822Token[] tokens : addresses) { 15538eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira for (int i = 0; i < tokens.length; i++) { 15548eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira address = tokens[i].toString(); 15554a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira list.append(address + END_TOKEN); 15564a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira } 15574a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira } 15588eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira } else { 15598eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira HashSet<String> compareTo = convertToHashSet(compareToList); 15608eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira for (Rfc822Token[] tokens : addresses) { 15618eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira for (int i = 0; i < tokens.length; i++) { 15628eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira address = tokens[i].toString(); 15638eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira // Check if this is a duplicate: 15648eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira if (!compareTo.contains(tokens[i].getAddress())) { 15658eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira // Get the address here 15668eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira list.append(address + END_TOKEN); 15678eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira } 15688eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira } 15698eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira } 15704a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira } 15714a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira } 15724a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira 15734a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira private HashSet<String> convertToHashSet(List<Rfc822Token[]> list) { 15744a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira HashSet<String> hash = new HashSet<String>(); 15754a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira for (Rfc822Token[] tokens : list) { 15764a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira for (int i = 0; i < tokens.length; i++) { 15774a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira hash.add(tokens[i].getAddress()); 15784a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira } 15794a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira } 15804a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira return hash; 15814a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira } 15824a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira 15834a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira protected List<Rfc822Token[]> tokenizeAddressList(Collection<String> addresses) { 15844a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira @VisibleForTesting 15854a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira List<Rfc822Token[]> tokenized = new ArrayList<Rfc822Token[]>(); 15864a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira 15874a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira for (String address: addresses) { 15884a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira tokenized.add(Rfc822Tokenizer.tokenize(address)); 15894a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira } 15904a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira return tokenized; 15914a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira } 15924a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira 15934a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira @VisibleForTesting 15944a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira void addAddressesToList(Collection<String> addresses, RecipientEditTextView list) { 15954a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira for (String address : addresses) { 15964a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira addAddressToList(address, list); 15974a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira } 15984a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira } 15994a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira 16004a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira private void addAddressToList(String address, RecipientEditTextView list) { 16014a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira if (address == null || list == null) 16024a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira return; 16034a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira 16044a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira Rfc822Token[] tokens = Rfc822Tokenizer.tokenize(address); 16054a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira 16064a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira for (int i = 0; i < tokens.length; i++) { 16074a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira list.append(tokens[i] + END_TOKEN); 16084a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira } 16094a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira } 16104a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira 16114a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira @VisibleForTesting 161265b06f52e5b6336493388923be88bdd2ded4e1d1mindyp protected Collection<String> initToRecipients(String accountEmail, String fullSenderAddress, 161365b06f52e5b6336493388923be88bdd2ded4e1d1mindyp String replyToAddress, String[] inToAddresses) { 16144a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira // The To recipient is the reply-to address specified in the original 16154a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira // message, unless it is: 16164a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira // the current user OR a custom from of the current user, in which case 16174a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira // it's the To recipient list of the original message. 16184a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira // OR missing, in which case use the sender of the original message 16194a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira Set<String> toAddresses = Sets.newHashSet(); 162065b06f52e5b6336493388923be88bdd2ded4e1d1mindyp if (!TextUtils.isEmpty(replyToAddress) && !recipientMatchesThisAccount(replyToAddress)) { 16213ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereira toAddresses.add(replyToAddress); 16224a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira } else { 162365b06f52e5b6336493388923be88bdd2ded4e1d1mindyp // In this case, the user is replying to a message in which their 162465b06f52e5b6336493388923be88bdd2ded4e1d1mindyp // current account or one of their custom from addresses is the only 162565b06f52e5b6336493388923be88bdd2ded4e1d1mindyp // recipient and they sent the original message. 162665b06f52e5b6336493388923be88bdd2ded4e1d1mindyp if (inToAddresses.length == 1 && recipientMatchesThisAccount(fullSenderAddress) 162765b06f52e5b6336493388923be88bdd2ded4e1d1mindyp && recipientMatchesThisAccount(inToAddresses[0])) { 162865b06f52e5b6336493388923be88bdd2ded4e1d1mindyp toAddresses.add(inToAddresses[0]); 162965b06f52e5b6336493388923be88bdd2ded4e1d1mindyp return toAddresses; 163065b06f52e5b6336493388923be88bdd2ded4e1d1mindyp } 163165b06f52e5b6336493388923be88bdd2ded4e1d1mindyp // This happens if the user replies to a message they originally 163265b06f52e5b6336493388923be88bdd2ded4e1d1mindyp // wrote. In this case, "reply" really means "re-send," so we 163365b06f52e5b6336493388923be88bdd2ded4e1d1mindyp // target the original recipients. This works as expected even 163465b06f52e5b6336493388923be88bdd2ded4e1d1mindyp // if the user sent the original message to themselves. 163565b06f52e5b6336493388923be88bdd2ded4e1d1mindyp for (String address : inToAddresses) { 163665b06f52e5b6336493388923be88bdd2ded4e1d1mindyp if (!recipientMatchesThisAccount(address)) { 163765b06f52e5b6336493388923be88bdd2ded4e1d1mindyp toAddresses.add(address); 1638fe8557b7a3aca8c41d85edbc9a094d96aacb08e5mindyp } 16391469b4e00ea101bc86adef274cf6b4705425b7fcMindy Pereira } 16404a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira } 16414a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira return toAddresses; 16424a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira } 16434a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira 1644cecc54a913a665af3556f3fcc11cfae4d54cb3beMindy Pereira private void addRecipients(String accountAddress, Set<String> recipients, String[] addresses) { 16454a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira for (String email : addresses) { 1646cecc54a913a665af3556f3fcc11cfae4d54cb3beMindy Pereira // Do not add this account, or any of its custom from addresses, to 1647cecc54a913a665af3556f3fcc11cfae4d54cb3beMindy Pereira // the list of recipients. 16484a20b708dd9ff3fb2b96f29b0b59012194c6fa34Mindy Pereira final String recipientAddress = Address.getEmailAddress(email).getAddress(); 16495ee5d69dc7ddbef52c6c62947757b3d86ac89f23mindyp if (!recipientMatchesThisAccount(recipientAddress)) { 16504a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira recipients.add(email.replace("\"\"", "")); 16514a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira } 16524a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira } 165346ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira } 165446ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira 1655cecc54a913a665af3556f3fcc11cfae4d54cb3beMindy Pereira /** 1656cecc54a913a665af3556f3fcc11cfae4d54cb3beMindy Pereira * A recipient matches this account if it has the same address as the 1657cecc54a913a665af3556f3fcc11cfae4d54cb3beMindy Pereira * currently selected account OR one of the custom from addresses associated 1658cecc54a913a665af3556f3fcc11cfae4d54cb3beMindy Pereira * with the currently selected account. 1659cecc54a913a665af3556f3fcc11cfae4d54cb3beMindy Pereira * @param accountAddress currently selected account 1660cecc54a913a665af3556f3fcc11cfae4d54cb3beMindy Pereira * @param recipientAddress address we are comparing with the currently selected account 1661cecc54a913a665af3556f3fcc11cfae4d54cb3beMindy Pereira * @return 1662cecc54a913a665af3556f3fcc11cfae4d54cb3beMindy Pereira */ 16635ee5d69dc7ddbef52c6c62947757b3d86ac89f23mindyp protected boolean recipientMatchesThisAccount(String recipientAddress) { 16645ee5d69dc7ddbef52c6c62947757b3d86ac89f23mindyp return ReplyFromAccount.matchesAccountOrCustomFrom(mAccount, recipientAddress, 1665fe8557b7a3aca8c41d85edbc9a094d96aacb08e5mindyp mAccount.getReplyFroms()); 1666cecc54a913a665af3556f3fcc11cfae4d54cb3beMindy Pereira } 1667cecc54a913a665af3556f3fcc11cfae4d54cb3beMindy Pereira 16683ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereira private void setSubject(Message refMessage, int action) { 16693ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereira String subject = refMessage.subject; 167046ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira String prefix; 167146ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira String correctedSubject = null; 167246ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira if (action == ComposeActivity.COMPOSE) { 167346ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira prefix = ""; 167446ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira } else if (action == ComposeActivity.FORWARD) { 167546ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira prefix = getString(R.string.forward_subject_label); 167646ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira } else { 167746ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira prefix = getString(R.string.reply_subject_label); 167846ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira } 167946ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira 168046ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira // Don't duplicate the prefix 1681c7a36999abb396ac965a981e0a3f658b537213acMindy Pereira if (!TextUtils.isEmpty(subject) 1682c7a36999abb396ac965a981e0a3f658b537213acMindy Pereira && subject.toLowerCase().startsWith(prefix.toLowerCase())) { 168346ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira correctedSubject = subject; 168446ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira } else { 168546ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira correctedSubject = String 168646ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira .format(getString(R.string.formatted_subject), prefix, subject); 168746ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira } 168846ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira mSubject.setText(correctedSubject); 168946ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira } 169046ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira 1691818143e2163648acc0c91f123b84777d65cd70cfMindy Pereira private void initRecipients() { 1692818143e2163648acc0c91f123b84777d65cd70cfMindy Pereira setupRecipients(mTo); 1693818143e2163648acc0c91f123b84777d65cd70cfMindy Pereira setupRecipients(mCc); 1694818143e2163648acc0c91f123b84777d65cd70cfMindy Pereira setupRecipients(mBcc); 1695eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira } 1696eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira 1697818143e2163648acc0c91f123b84777d65cd70cfMindy Pereira private void setupRecipients(RecipientEditTextView view) { 1698679a8cc895ec75d3b578dbc77db1e9c04dd7f8b0Paul Westbrook view.setAdapter(new RecipientAdapter(this, mAccount)); 1699c17d073dd43871df36ea70b3dea55963bdb98384Mindy Pereira view.setTokenizer(new Rfc822Tokenizer()); 170082cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira if (mValidator == null) { 1701679a8cc895ec75d3b578dbc77db1e9c04dd7f8b0Paul Westbrook final String accountName = mAccount.name; 170233fe908589dca6a7f58aa9f56d73f74a48ac42f6Mindy Pereira int offset = accountName.indexOf("@") + 1; 170333fe908589dca6a7f58aa9f56d73f74a48ac42f6Mindy Pereira String account = accountName; 1704c17d073dd43871df36ea70b3dea55963bdb98384Mindy Pereira if (offset > -1) { 170533fe908589dca6a7f58aa9f56d73f74a48ac42f6Mindy Pereira account = account.substring(accountName.indexOf("@") + 1); 1706c17d073dd43871df36ea70b3dea55963bdb98384Mindy Pereira } 170782cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira mValidator = new Rfc822Validator(account); 1708c17d073dd43871df36ea70b3dea55963bdb98384Mindy Pereira } 170982cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira view.setValidator(mValidator); 17108e9305ec0bbe23cec01eb34a2aee76c55199a10aMindy Pereira } 17118e9305ec0bbe23cec01eb34a2aee76c55199a10aMindy Pereira 17128e9305ec0bbe23cec01eb34a2aee76c55199a10aMindy Pereira @Override 17138e9305ec0bbe23cec01eb34a2aee76c55199a10aMindy Pereira public void onClick(View v) { 17148e9305ec0bbe23cec01eb34a2aee76c55199a10aMindy Pereira int id = v.getId(); 17158e9305ec0bbe23cec01eb34a2aee76c55199a10aMindy Pereira switch (id) { 1716a26b54e3a858de409be3746e65591bb8a0d6ea9aMindy Pereira case R.id.add_cc_bcc: 17178e9305ec0bbe23cec01eb34a2aee76c55199a10aMindy Pereira // Verify that cc/ bcc aren't showing. 17188e9305ec0bbe23cec01eb34a2aee76c55199a10aMindy Pereira // Animate in cc/bcc. 1719a26b54e3a858de409be3746e65591bb8a0d6ea9aMindy Pereira showCcBccViews(); 17208e9305ec0bbe23cec01eb34a2aee76c55199a10aMindy Pereira break; 1721cd0b0b950efebfc3964334067747b97e61c4f027mindyp case R.id.add_photo_attachment: 1722cd0b0b950efebfc3964334067747b97e61c4f027mindyp doAttach(MIME_TYPE_PHOTO); 1723cd0b0b950efebfc3964334067747b97e61c4f027mindyp break; 1724cd0b0b950efebfc3964334067747b97e61c4f027mindyp case R.id.add_video_attachment: 1725cd0b0b950efebfc3964334067747b97e61c4f027mindyp doAttach(MIME_TYPE_VIDEO); 1726cd0b0b950efebfc3964334067747b97e61c4f027mindyp break; 17278e9305ec0bbe23cec01eb34a2aee76c55199a10aMindy Pereira } 17288e9305ec0bbe23cec01eb34a2aee76c55199a10aMindy Pereira } 1729b47f3e286bcf78e85ab2d3389e38e99020d0634fMindy Pereira 1730b47f3e286bcf78e85ab2d3389e38e99020d0634fMindy Pereira @Override 1731b47f3e286bcf78e85ab2d3389e38e99020d0634fMindy Pereira public boolean onCreateOptionsMenu(Menu menu) { 1732b47f3e286bcf78e85ab2d3389e38e99020d0634fMindy Pereira super.onCreateOptionsMenu(menu); 1733b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira // Don't render any menu items when there are no accounts. 1734b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira if (mAccounts == null || mAccounts.length == 0) { 1735b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira return true; 1736b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira } 1737b47f3e286bcf78e85ab2d3389e38e99020d0634fMindy Pereira MenuInflater inflater = getMenuInflater(); 1738b47f3e286bcf78e85ab2d3389e38e99020d0634fMindy Pereira inflater.inflate(R.menu.compose_menu, menu); 17391d7e9145fa4f490ba87ade0ed70ce0fa1f33be81mindyp 17401d7e9145fa4f490ba87ade0ed70ce0fa1f33be81mindyp /* 17411d7e9145fa4f490ba87ade0ed70ce0fa1f33be81mindyp * Start save in the correct enabled state. 17421d7e9145fa4f490ba87ade0ed70ce0fa1f33be81mindyp * 1) If a user launches compose from within gmail, save is disabled 17431d7e9145fa4f490ba87ade0ed70ce0fa1f33be81mindyp * until they add something, at which point, save is enabled, auto save 17441d7e9145fa4f490ba87ade0ed70ce0fa1f33be81mindyp * on exit; if the user empties everything, save is disabled, exiting does not 17451d7e9145fa4f490ba87ade0ed70ce0fa1f33be81mindyp * auto-save 17461d7e9145fa4f490ba87ade0ed70ce0fa1f33be81mindyp * 2) if a user replies/ reply all/ forwards from within gmail, save is 17471d7e9145fa4f490ba87ade0ed70ce0fa1f33be81mindyp * disabled until they change something, at which point, save is 17481d7e9145fa4f490ba87ade0ed70ce0fa1f33be81mindyp * enabled, auto save on exit; if the user empties everything, save is 17491d7e9145fa4f490ba87ade0ed70ce0fa1f33be81mindyp * disabled, exiting does not auto-save. 17501d7e9145fa4f490ba87ade0ed70ce0fa1f33be81mindyp * 3) If a user launches compose from another application and something 17511d7e9145fa4f490ba87ade0ed70ce0fa1f33be81mindyp * gets populated (attachments, recipients, body, subject, etc), save is 17521d7e9145fa4f490ba87ade0ed70ce0fa1f33be81mindyp * enabled, auto save on exit; if the user empties everything, save is 17531d7e9145fa4f490ba87ade0ed70ce0fa1f33be81mindyp * disabled, exiting does not auto-save 17541d7e9145fa4f490ba87ade0ed70ce0fa1f33be81mindyp */ 175582cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira mSave = menu.findItem(R.id.save); 17561d7e9145fa4f490ba87ade0ed70ce0fa1f33be81mindyp String action = getIntent() != null ? getIntent().getAction() : null; 17571d7e9145fa4f490ba87ade0ed70ce0fa1f33be81mindyp enableSave(mSavedInstanceState != null ? 17581d7e9145fa4f490ba87ade0ed70ce0fa1f33be81mindyp mSavedInstanceState.getBoolean(EXTRA_SAVE_ENABLED) 17591d7e9145fa4f490ba87ade0ed70ce0fa1f33be81mindyp : (Intent.ACTION_SEND.equals(action) 17601d7e9145fa4f490ba87ade0ed70ce0fa1f33be81mindyp || Intent.ACTION_SEND_MULTIPLE.equals(action) 17611d7e9145fa4f490ba87ade0ed70ce0fa1f33be81mindyp || Intent.ACTION_SENDTO.equals(action) 17621d7e9145fa4f490ba87ade0ed70ce0fa1f33be81mindyp || shouldSave())); 17631d7e9145fa4f490ba87ade0ed70ce0fa1f33be81mindyp 176482cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira mSend = menu.findItem(R.id.send); 17653ca5bad62c075184920c5e331870280fc6acca16Mindy Pereira MenuItem helpItem = menu.findItem(R.id.help_info_menu_item); 17663ca5bad62c075184920c5e331870280fc6acca16Mindy Pereira MenuItem sendFeedbackItem = menu.findItem(R.id.feedback_menu_item); 17673ca5bad62c075184920c5e331870280fc6acca16Mindy Pereira if (helpItem != null) { 17683ca5bad62c075184920c5e331870280fc6acca16Mindy Pereira helpItem.setVisible(mAccount != null 17693ca5bad62c075184920c5e331870280fc6acca16Mindy Pereira && mAccount.supportsCapability(AccountCapabilities.HELP_CONTENT)); 17703ca5bad62c075184920c5e331870280fc6acca16Mindy Pereira } 17713ca5bad62c075184920c5e331870280fc6acca16Mindy Pereira if (sendFeedbackItem != null) { 17723ca5bad62c075184920c5e331870280fc6acca16Mindy Pereira sendFeedbackItem.setVisible(mAccount != null 17733ca5bad62c075184920c5e331870280fc6acca16Mindy Pereira && mAccount.supportsCapability(AccountCapabilities.SEND_FEEDBACK)); 17743ca5bad62c075184920c5e331870280fc6acca16Mindy Pereira } 1775b47f3e286bcf78e85ab2d3389e38e99020d0634fMindy Pereira return true; 1776b47f3e286bcf78e85ab2d3389e38e99020d0634fMindy Pereira } 1777b47f3e286bcf78e85ab2d3389e38e99020d0634fMindy Pereira 1778b47f3e286bcf78e85ab2d3389e38e99020d0634fMindy Pereira @Override 1779ec8b0edb23c0e0b7f1a8ce9558a919be31169d45Mindy Pereira public boolean onPrepareOptionsMenu(Menu menu) { 1780ec8b0edb23c0e0b7f1a8ce9558a919be31169d45Mindy Pereira MenuItem ccBcc = menu.findItem(R.id.add_cc_bcc); 1781818143e2163648acc0c91f123b84777d65cd70cfMindy Pereira if (ccBcc != null && mCc != null) { 1782ec8b0edb23c0e0b7f1a8ce9558a919be31169d45Mindy Pereira // Its possible there is a menu item OR a button. 1783ec8b0edb23c0e0b7f1a8ce9558a919be31169d45Mindy Pereira boolean ccFieldVisible = mCc.isShown(); 1784ec8b0edb23c0e0b7f1a8ce9558a919be31169d45Mindy Pereira boolean bccFieldVisible = mBcc.isShown(); 1785ec8b0edb23c0e0b7f1a8ce9558a919be31169d45Mindy Pereira if (!ccFieldVisible || !bccFieldVisible) { 1786ec8b0edb23c0e0b7f1a8ce9558a919be31169d45Mindy Pereira ccBcc.setVisible(true); 1787ec8b0edb23c0e0b7f1a8ce9558a919be31169d45Mindy Pereira ccBcc.setTitle(getString(!ccFieldVisible ? R.string.add_cc_label 1788ec8b0edb23c0e0b7f1a8ce9558a919be31169d45Mindy Pereira : R.string.add_bcc_label)); 1789ec8b0edb23c0e0b7f1a8ce9558a919be31169d45Mindy Pereira } else { 1790ec8b0edb23c0e0b7f1a8ce9558a919be31169d45Mindy Pereira ccBcc.setVisible(false); 1791ec8b0edb23c0e0b7f1a8ce9558a919be31169d45Mindy Pereira } 1792ec8b0edb23c0e0b7f1a8ce9558a919be31169d45Mindy Pereira } 1793ec8b0edb23c0e0b7f1a8ce9558a919be31169d45Mindy Pereira return true; 1794ec8b0edb23c0e0b7f1a8ce9558a919be31169d45Mindy Pereira } 1795ec8b0edb23c0e0b7f1a8ce9558a919be31169d45Mindy Pereira 1796ec8b0edb23c0e0b7f1a8ce9558a919be31169d45Mindy Pereira @Override 1797b47f3e286bcf78e85ab2d3389e38e99020d0634fMindy Pereira public boolean onOptionsItemSelected(MenuItem item) { 1798b47f3e286bcf78e85ab2d3389e38e99020d0634fMindy Pereira int id = item.getItemId(); 179975f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira boolean handled = true; 1800b47f3e286bcf78e85ab2d3389e38e99020d0634fMindy Pereira switch (id) { 18012db7d4a37b794e1721a5b9416068702aa799c5f8Mindy Pereira case R.id.add_photo_attachment: 18022db7d4a37b794e1721a5b9416068702aa799c5f8Mindy Pereira doAttach(MIME_TYPE_PHOTO); 18032db7d4a37b794e1721a5b9416068702aa799c5f8Mindy Pereira break; 18042db7d4a37b794e1721a5b9416068702aa799c5f8Mindy Pereira case R.id.add_video_attachment: 18052db7d4a37b794e1721a5b9416068702aa799c5f8Mindy Pereira doAttach(MIME_TYPE_VIDEO); 18067b56a61174eeb202eea468b7f68b79729737ded2Mindy Pereira break; 1807ec8b0edb23c0e0b7f1a8ce9558a919be31169d45Mindy Pereira case R.id.add_cc_bcc: 1808ec8b0edb23c0e0b7f1a8ce9558a919be31169d45Mindy Pereira showCcBccViews(); 1809b47f3e286bcf78e85ab2d3389e38e99020d0634fMindy Pereira break; 181033fe908589dca6a7f58aa9f56d73f74a48ac42f6Mindy Pereira case R.id.save: 181148e31b07b5ac7c83dc3a009242fa915afccddb9eMindy Pereira doSave(true); 181233fe908589dca6a7f58aa9f56d73f74a48ac42f6Mindy Pereira break; 181333fe908589dca6a7f58aa9f56d73f74a48ac42f6Mindy Pereira case R.id.send: 181433fe908589dca6a7f58aa9f56d73f74a48ac42f6Mindy Pereira doSend(); 181575f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira break; 1816efe3d25aa19da172fd5c3ec39539cdd91f29e927Mindy Pereira case R.id.discard: 1817efe3d25aa19da172fd5c3ec39539cdd91f29e927Mindy Pereira doDiscard(); 1818efe3d25aa19da172fd5c3ec39539cdd91f29e927Mindy Pereira break; 18191f93668e1186d48b507207841c1ca0529c3de292Mindy Pereira case R.id.settings: 18201f93668e1186d48b507207841c1ca0529c3de292Mindy Pereira Utils.showSettings(this, mAccount); 18211f93668e1186d48b507207841c1ca0529c3de292Mindy Pereira break; 1822fbe4019a262f6b1934a44e598009ae63dc5745eeMindy Pereira case android.R.id.home: 1823daecb4b9b20a609b27fc803390ecf4f524b76089Paul Westbrook onAppUpPressed(); 1824fbe4019a262f6b1934a44e598009ae63dc5745eeMindy Pereira break; 1825fbe4019a262f6b1934a44e598009ae63dc5745eeMindy Pereira case R.id.help_info_menu_item: 182630745b6e9c4d280ac578d1186fbc0cec9bd2a838Paul Westbrook Utils.showHelp(this, mAccount, getString(R.string.compose_help_context)); 1827fbe4019a262f6b1934a44e598009ae63dc5745eeMindy Pereira break; 1828fbe4019a262f6b1934a44e598009ae63dc5745eeMindy Pereira case R.id.feedback_menu_item: 182917beb0b8aee78a39a2094a48ba7f55a602f701cbPaul Westbrook Utils.sendFeedback(this, mAccount, false); 1830fbe4019a262f6b1934a44e598009ae63dc5745eeMindy Pereira break; 183175f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira default: 183275f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira handled = false; 183333fe908589dca6a7f58aa9f56d73f74a48ac42f6Mindy Pereira break; 1834b47f3e286bcf78e85ab2d3389e38e99020d0634fMindy Pereira } 1835b47f3e286bcf78e85ab2d3389e38e99020d0634fMindy Pereira return !handled ? super.onOptionsItemSelected(item) : handled; 1836b47f3e286bcf78e85ab2d3389e38e99020d0634fMindy Pereira } 1837326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira 1838b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira @Override 1839b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira public void onBackPressed() { 1840b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira // If we are showing the wait fragment, just exit. 1841b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira if (getWaitFragment() != null) { 1842b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira finish(); 1843b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira } else { 1844b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira super.onBackPressed(); 1845b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira } 1846b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira } 1847b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira 18481672ff8ed6741df5c245e55f7a4e847f6ccb8c52Vikram Aggarwal /** 18491672ff8ed6741df5c245e55f7a4e847f6ccb8c52Vikram Aggarwal * Carries out the "up" action in the action bar. 18501672ff8ed6741df5c245e55f7a4e847f6ccb8c52Vikram Aggarwal */ 1851daecb4b9b20a609b27fc803390ecf4f524b76089Paul Westbrook private void onAppUpPressed() { 1852daecb4b9b20a609b27fc803390ecf4f524b76089Paul Westbrook if (mLaunchedFromEmail) { 1853daecb4b9b20a609b27fc803390ecf4f524b76089Paul Westbrook // If this was started from Gmail, simply treat app up as the system back button, so 1854daecb4b9b20a609b27fc803390ecf4f524b76089Paul Westbrook // that the last view is restored. 1855daecb4b9b20a609b27fc803390ecf4f524b76089Paul Westbrook onBackPressed(); 1856daecb4b9b20a609b27fc803390ecf4f524b76089Paul Westbrook return; 1857daecb4b9b20a609b27fc803390ecf4f524b76089Paul Westbrook } 1858daecb4b9b20a609b27fc803390ecf4f524b76089Paul Westbrook 1859daecb4b9b20a609b27fc803390ecf4f524b76089Paul Westbrook // Fire the main activity to ensure it launches the "top" screen of mail. 1860daecb4b9b20a609b27fc803390ecf4f524b76089Paul Westbrook // Since the main Activity is singleTask, it should revive that task if it was already 1861daecb4b9b20a609b27fc803390ecf4f524b76089Paul Westbrook // started. 18620c3c2058f75487713c64634c7f08025fd78ba012Vikram Aggarwal final Intent mailIntent = Utils.createViewInboxIntent(mAccount); 1863daecb4b9b20a609b27fc803390ecf4f524b76089Paul Westbrook mailIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK | 1864daecb4b9b20a609b27fc803390ecf4f524b76089Paul Westbrook Intent.FLAG_ACTIVITY_TASK_ON_HOME); 1865daecb4b9b20a609b27fc803390ecf4f524b76089Paul Westbrook startActivity(mailIntent); 1866daecb4b9b20a609b27fc803390ecf4f524b76089Paul Westbrook finish(); 1867daecb4b9b20a609b27fc803390ecf4f524b76089Paul Westbrook } 1868daecb4b9b20a609b27fc803390ecf4f524b76089Paul Westbrook 186933fe908589dca6a7f58aa9f56d73f74a48ac42f6Mindy Pereira private void doSend() { 1870dd19b63d3f560aba8962435ed5a2e1f5ae794351Mark Wei sendOrSaveWithSanityChecks(false, true, false, false); 187133fe908589dca6a7f58aa9f56d73f74a48ac42f6Mindy Pereira } 187233fe908589dca6a7f58aa9f56d73f74a48ac42f6Mindy Pereira 187348e31b07b5ac7c83dc3a009242fa915afccddb9eMindy Pereira private void doSave(boolean showToast) { 1874dd19b63d3f560aba8962435ed5a2e1f5ae794351Mark Wei sendOrSaveWithSanityChecks(true, showToast, false, false); 187548e31b07b5ac7c83dc3a009242fa915afccddb9eMindy Pereira } 187648e31b07b5ac7c83dc3a009242fa915afccddb9eMindy Pereira 1877e011b1d1c8e2e674dfdf1985d9d13da8cc06d803Mindy Pereira @VisibleForTesting 1878e011b1d1c8e2e674dfdf1985d9d13da8cc06d803Mindy Pereira public interface SendOrSaveCallback { 187982cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira public void initializeSendOrSave(SendOrSaveTask sendOrSaveTask); 18807ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira public void notifyMessageIdAllocated(SendOrSaveMessage sendOrSaveMessage, Message message); 18817ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira public Message getMessage(); 188282cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira public void sendOrSaveFinished(SendOrSaveTask sendOrSaveTask, boolean success); 188382cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira } 188482cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira 1885e011b1d1c8e2e674dfdf1985d9d13da8cc06d803Mindy Pereira @VisibleForTesting 1886e011b1d1c8e2e674dfdf1985d9d13da8cc06d803Mindy Pereira public static class SendOrSaveTask implements Runnable { 188782cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira private final Context mContext; 188882cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira @VisibleForTesting 1889e011b1d1c8e2e674dfdf1985d9d13da8cc06d803Mindy Pereira public final SendOrSaveCallback mSendOrSaveCallback; 1890e011b1d1c8e2e674dfdf1985d9d13da8cc06d803Mindy Pereira @VisibleForTesting 1891e011b1d1c8e2e674dfdf1985d9d13da8cc06d803Mindy Pereira public final SendOrSaveMessage mSendOrSaveMessage; 189244a6339dd80f4b5b9e5d54567021698d92467c5emindyp private ReplyFromAccount mExistingDraftAccount; 189382cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira 189482cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira public SendOrSaveTask(Context context, SendOrSaveMessage message, 189544a6339dd80f4b5b9e5d54567021698d92467c5emindyp SendOrSaveCallback callback, ReplyFromAccount draftAccount) { 189682cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira mContext = context; 189782cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira mSendOrSaveCallback = callback; 189882cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira mSendOrSaveMessage = message; 189944a6339dd80f4b5b9e5d54567021698d92467c5emindyp mExistingDraftAccount = draftAccount; 190082cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira } 190182cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira 190282cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira @Override 190382cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira public void run() { 19047ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira final SendOrSaveMessage sendOrSaveMessage = mSendOrSaveMessage; 190582cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira 190692551d057965689f1952faeb06763f0762bc717fMindy Pereira final ReplyFromAccount selectedAccount = sendOrSaveMessage.mAccount; 19077ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira Message message = mSendOrSaveCallback.getMessage(); 19087ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira long messageId = message != null ? message.id : UIProvider.INVALID_MESSAGE_ID; 190982cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira // If a previous draft has been saved, in an account that is different 191082cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira // than what the user wants to send from, remove the old draft, and treat this 191182cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira // as a new message 191244a6339dd80f4b5b9e5d54567021698d92467c5emindyp if (mExistingDraftAccount != null 191344a6339dd80f4b5b9e5d54567021698d92467c5emindyp && !selectedAccount.account.uri.equals(mExistingDraftAccount.account.uri)) { 191482cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira if (messageId != UIProvider.INVALID_MESSAGE_ID) { 191582cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira ContentResolver resolver = mContext.getContentResolver(); 191682cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira ContentValues values = new ContentValues(); 191782cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira values.put(BaseColumns._ID, messageId); 1918febd226e871263aeb21d436bee81eb2f7dec3d03mindyp if (mExistingDraftAccount.account.expungeMessageUri != null) { 1919febd226e871263aeb21d436bee81eb2f7dec3d03mindyp new ContentProviderTask.UpdateTask() 1920febd226e871263aeb21d436bee81eb2f7dec3d03mindyp .run(resolver, mExistingDraftAccount.account.expungeMessageUri, 1921febd226e871263aeb21d436bee81eb2f7dec3d03mindyp values, null, null); 1922cfb7f33ff8ef9dc60b9143af32de64c7a3d71f36Mindy Pereira } else { 1923cfb7f33ff8ef9dc60b9143af32de64c7a3d71f36Mindy Pereira // TODO(mindyp) delete the conversation. 1924eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira } 192582cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira // reset messageId to 0, so a new message will be created 192682cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira messageId = UIProvider.INVALID_MESSAGE_ID; 192782cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira } 192882cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira } 192982cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira 193082cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira final long messageIdToSave = messageId; 193172e2ea860f66f496537e37ebc0ddd2c670d4c651Paul Westbrook sendOrSaveMessage(messageIdToSave, sendOrSaveMessage, selectedAccount, message); 193272e2ea860f66f496537e37ebc0ddd2c670d4c651Paul Westbrook 193372e2ea860f66f496537e37ebc0ddd2c670d4c651Paul Westbrook if (!sendOrSaveMessage.mSave) { 193472e2ea860f66f496537e37ebc0ddd2c670d4c651Paul Westbrook UIProvider.incrementRecipientsTimesContacted(mContext, 193572e2ea860f66f496537e37ebc0ddd2c670d4c651Paul Westbrook (String) sendOrSaveMessage.mValues.get(UIProvider.MessageColumns.TO)); 193672e2ea860f66f496537e37ebc0ddd2c670d4c651Paul Westbrook UIProvider.incrementRecipientsTimesContacted(mContext, 193772e2ea860f66f496537e37ebc0ddd2c670d4c651Paul Westbrook (String) sendOrSaveMessage.mValues.get(UIProvider.MessageColumns.CC)); 193872e2ea860f66f496537e37ebc0ddd2c670d4c651Paul Westbrook UIProvider.incrementRecipientsTimesContacted(mContext, 193972e2ea860f66f496537e37ebc0ddd2c670d4c651Paul Westbrook (String) sendOrSaveMessage.mValues.get(UIProvider.MessageColumns.BCC)); 194072e2ea860f66f496537e37ebc0ddd2c670d4c651Paul Westbrook } 194172e2ea860f66f496537e37ebc0ddd2c670d4c651Paul Westbrook mSendOrSaveCallback.sendOrSaveFinished(SendOrSaveTask.this, true); 194272e2ea860f66f496537e37ebc0ddd2c670d4c651Paul Westbrook } 194372e2ea860f66f496537e37ebc0ddd2c670d4c651Paul Westbrook 194472e2ea860f66f496537e37ebc0ddd2c670d4c651Paul Westbrook /** 194572e2ea860f66f496537e37ebc0ddd2c670d4c651Paul Westbrook * Send or Save a message. 194672e2ea860f66f496537e37ebc0ddd2c670d4c651Paul Westbrook */ 194772e2ea860f66f496537e37ebc0ddd2c670d4c651Paul Westbrook private void sendOrSaveMessage(long messageIdToSave, SendOrSaveMessage sendOrSaveMessage, 194872e2ea860f66f496537e37ebc0ddd2c670d4c651Paul Westbrook ReplyFromAccount selectedAccount, Message message) { 194972e2ea860f66f496537e37ebc0ddd2c670d4c651Paul Westbrook final ContentResolver resolver = mContext.getContentResolver(); 195072e2ea860f66f496537e37ebc0ddd2c670d4c651Paul Westbrook final boolean updateExistingMessage = messageIdToSave != UIProvider.INVALID_MESSAGE_ID; 195172e2ea860f66f496537e37ebc0ddd2c670d4c651Paul Westbrook 195272e2ea860f66f496537e37ebc0ddd2c670d4c651Paul Westbrook final String accountMethod = sendOrSaveMessage.mSave ? 195372e2ea860f66f496537e37ebc0ddd2c670d4c651Paul Westbrook UIProvider.AccountCallMethods.SAVE_MESSAGE : 195472e2ea860f66f496537e37ebc0ddd2c670d4c651Paul Westbrook UIProvider.AccountCallMethods.SEND_MESSAGE; 195572e2ea860f66f496537e37ebc0ddd2c670d4c651Paul Westbrook 19563c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook try { 19573c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook if (updateExistingMessage) { 19583c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook sendOrSaveMessage.mValues.put(BaseColumns._ID, messageIdToSave); 19593c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook 19603c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook final Bundle result = callAccountSendSaveMethod(resolver, 19613c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook selectedAccount.account, accountMethod, sendOrSaveMessage); 19623c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook if (result == null) { 19633c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook // TODO(pwestbro): Once Email supports the call api, remove this block 19643c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook // If null was returned, then the provider didn't handle the call method 19653c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook final Uri updateUri = Uri.parse(sendOrSaveMessage.mSave ? 19663c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook message.saveUri : message.sendUri); 19673c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook resolver.update(updateUri, sendOrSaveMessage.mValues, null, null); 19683c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook } 196972e2ea860f66f496537e37ebc0ddd2c670d4c651Paul Westbrook } else { 19703c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook final Uri messageUri; 19713c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook final Bundle result = callAccountSendSaveMethod(resolver, 19723c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook selectedAccount.account, accountMethod, sendOrSaveMessage); 19733c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook if (result != null) { 19743c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook // If a non-null value was returned, then the provider handled the call 19753c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook // method 19763c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook messageUri = result.getParcelable(UIProvider.MessageColumns.URI); 19773c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook } else { 19783c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook // TODO(pwestbro): Once Email supports the call api, remove this block 19793c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook messageUri = resolver.insert( 19803c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook sendOrSaveMessage.mSave ? selectedAccount.account.saveDraftUri 19813c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook : selectedAccount.account.sendMessageUri, 19823c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook sendOrSaveMessage.mValues); 19833c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook } 19843c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook if (sendOrSaveMessage.mSave && messageUri != null) { 19853c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook final Cursor messageCursor = resolver.query(messageUri, 19863c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook UIProvider.MESSAGE_PROJECTION, null, null, null); 19873c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook if (messageCursor != null) { 19883c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook try { 19893c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook if (messageCursor.moveToFirst()) { 19903c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook // Broadcast notification that a new message has 19913c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook // been allocated 19923c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook mSendOrSaveCallback.notifyMessageIdAllocated(sendOrSaveMessage, 19933c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook new Message(messageCursor)); 19943c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook } 19953c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook } finally { 19963c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook messageCursor.close(); 19973c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook } 19983c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook } 19993c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook } 200072e2ea860f66f496537e37ebc0ddd2c670d4c651Paul Westbrook } 20013c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook } finally { 20023c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook // Close any opened file descriptors 20033c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook closeOpenedAttachmentFds(sendOrSaveMessage); 20043c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook } 20053c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook } 20063c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook 20073c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook private void closeOpenedAttachmentFds(SendOrSaveMessage sendOrSaveMessage) { 20083c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook final Bundle openedFds = sendOrSaveMessage.attachmentFds(); 20093c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook if (openedFds != null) { 20103c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook final Set<String> keys = openedFds.keySet(); 20113c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook for (String key : keys) { 20123c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook final ParcelFileDescriptor fd = openedFds.getParcelable(key); 20133c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook if (fd != null) { 2014ba5584836c0a63c8dac96b10b569465bd56d5f7aPaul Westbrook try { 20153c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook fd.close(); 20163c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook } catch (IOException e) { 20173c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook // Do nothing 2018ba5584836c0a63c8dac96b10b569465bd56d5f7aPaul Westbrook } 20197ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira } 20207ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira } 202182cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira } 202272e2ea860f66f496537e37ebc0ddd2c670d4c651Paul Westbrook } 202382cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira 202472e2ea860f66f496537e37ebc0ddd2c670d4c651Paul Westbrook /** 202572e2ea860f66f496537e37ebc0ddd2c670d4c651Paul Westbrook * Use the {@link ContentResolver#call()} method to send or save the message. 202672e2ea860f66f496537e37ebc0ddd2c670d4c651Paul Westbrook * 202772e2ea860f66f496537e37ebc0ddd2c670d4c651Paul Westbrook * If this was successful, this method will return an non-null Bundle instance 202872e2ea860f66f496537e37ebc0ddd2c670d4c651Paul Westbrook */ 202972e2ea860f66f496537e37ebc0ddd2c670d4c651Paul Westbrook private Bundle callAccountSendSaveMethod(ContentResolver resolver, Account account, 203072e2ea860f66f496537e37ebc0ddd2c670d4c651Paul Westbrook String method, SendOrSaveMessage sendOrSaveMessage) { 203172e2ea860f66f496537e37ebc0ddd2c670d4c651Paul Westbrook // Copy all of the values from the content values to the bundle 203272e2ea860f66f496537e37ebc0ddd2c670d4c651Paul Westbrook final Bundle methodExtras = new Bundle(sendOrSaveMessage.mValues.size()); 203372e2ea860f66f496537e37ebc0ddd2c670d4c651Paul Westbrook final Set<Entry<String, Object>> valueSet = sendOrSaveMessage.mValues.valueSet(); 203472e2ea860f66f496537e37ebc0ddd2c670d4c651Paul Westbrook 203572e2ea860f66f496537e37ebc0ddd2c670d4c651Paul Westbrook for (Entry<String, Object> entry : valueSet) { 203672e2ea860f66f496537e37ebc0ddd2c670d4c651Paul Westbrook final Object entryValue = entry.getValue(); 203772e2ea860f66f496537e37ebc0ddd2c670d4c651Paul Westbrook final String key = entry.getKey(); 203872e2ea860f66f496537e37ebc0ddd2c670d4c651Paul Westbrook if (entryValue instanceof String) { 203972e2ea860f66f496537e37ebc0ddd2c670d4c651Paul Westbrook methodExtras.putString(key, (String)entryValue); 204072e2ea860f66f496537e37ebc0ddd2c670d4c651Paul Westbrook } else if (entryValue instanceof Boolean) { 204172e2ea860f66f496537e37ebc0ddd2c670d4c651Paul Westbrook methodExtras.putBoolean(key, (Boolean)entryValue); 204272e2ea860f66f496537e37ebc0ddd2c670d4c651Paul Westbrook } else if (entryValue instanceof Integer) { 204372e2ea860f66f496537e37ebc0ddd2c670d4c651Paul Westbrook methodExtras.putInt(key, (Integer)entryValue); 204472e2ea860f66f496537e37ebc0ddd2c670d4c651Paul Westbrook } else if (entryValue instanceof Long) { 204572e2ea860f66f496537e37ebc0ddd2c670d4c651Paul Westbrook methodExtras.putLong(key, (Long)entryValue); 204672e2ea860f66f496537e37ebc0ddd2c670d4c651Paul Westbrook } else { 204772e2ea860f66f496537e37ebc0ddd2c670d4c651Paul Westbrook LogUtils.wtf(LOG_TAG, "Unexpected object type: %s", 204872e2ea860f66f496537e37ebc0ddd2c670d4c651Paul Westbrook entryValue.getClass().getName()); 204972e2ea860f66f496537e37ebc0ddd2c670d4c651Paul Westbrook } 205082cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira } 205172e2ea860f66f496537e37ebc0ddd2c670d4c651Paul Westbrook 20523c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook // If the SendOrSaveMessage has some opened fds, add them to the bundle 20533c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook final Bundle fdMap = sendOrSaveMessage.attachmentFds(); 20543c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook if (fdMap != null) { 20553c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook methodExtras.putParcelable( 20563c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook UIProvider.SendOrSaveMethodParamKeys.OPENED_FD_MAP, fdMap); 20573c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook } 20583c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook 205972e2ea860f66f496537e37ebc0ddd2c670d4c651Paul Westbrook return resolver.call(account.uri, method, account.uri.toString(), methodExtras); 206082cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira } 206182cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira } 206282cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira 2063e011b1d1c8e2e674dfdf1985d9d13da8cc06d803Mindy Pereira @VisibleForTesting 2064e011b1d1c8e2e674dfdf1985d9d13da8cc06d803Mindy Pereira public static class SendOrSaveMessage { 206592551d057965689f1952faeb06763f0762bc717fMindy Pereira final ReplyFromAccount mAccount; 206682cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira final ContentValues mValues; 20673ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereira final String mRefMessageId; 2068e011b1d1c8e2e674dfdf1985d9d13da8cc06d803Mindy Pereira @VisibleForTesting 2069e011b1d1c8e2e674dfdf1985d9d13da8cc06d803Mindy Pereira public final boolean mSave; 207082cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira final int mRequestId; 20713c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook private final Bundle mAttachmentFds; 207282cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira 20733c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook public SendOrSaveMessage(Context context, ReplyFromAccount account, ContentValues values, 20743c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook String refMessageId, List<Attachment> attachments, boolean save) { 207582cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira mAccount = account; 207682cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira mValues = values; 207782cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira mRefMessageId = refMessageId; 207882cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira mSave = save; 207982cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira mRequestId = mValues.hashCode() ^ hashCode(); 20803c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook 20813c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook mAttachmentFds = initializeAttachmentFds(context, attachments); 208282cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira } 208382cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira 208482cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira int requestId() { 208582cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira return mRequestId; 208682cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira } 20873c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook 20883c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook Bundle attachmentFds() { 20893c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook return mAttachmentFds; 20903c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook } 20913c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook 20923c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook /** 20933c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook * Opens {@link ParcelFileDescriptor} for each of the attachments. This method must be 20943c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook * called before the ComposeActivity finishes. 20953c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook * Note: The caller is responsible for closing these file descriptors. 20963c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook */ 20973c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook private Bundle initializeAttachmentFds(Context context, List<Attachment> attachments) { 20983c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook if (attachments == null || attachments.size() == 0) { 20993c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook return null; 21003c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook } 21013c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook 21023c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook final Bundle result = new Bundle(attachments.size()); 21033c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook final ContentResolver resolver = context.getContentResolver(); 21043c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook 21053c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook for (Attachment attachment : attachments) { 21063c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook if (attachment == null || Utils.isEmpty(attachment.contentUri)) { 21073c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook continue; 21083c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook } 21093c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook 21103c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook ParcelFileDescriptor fileDescriptor; 21113c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook try { 21123c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook fileDescriptor = resolver.openFileDescriptor(attachment.contentUri, "r"); 21133c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook } catch (FileNotFoundException e) { 21143c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook LogUtils.e(LOG_TAG, e, "Exception attempting to open attachment"); 21153c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook fileDescriptor = null; 21163c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook } 21173c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook 21183c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook if (fileDescriptor != null) { 21193c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook result.putParcelable(attachment.contentUri.toString(), fileDescriptor); 21203c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook } 21213c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook } 21223c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook 21233c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook return result; 21243c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook } 212582cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira } 212682cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira 212782cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira /** 212882cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira * Get the to recipients. 212982cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira */ 213082cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira public String[] getToAddresses() { 213182cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira return getAddressesFromList(mTo); 213282cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira } 213382cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira 213482cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira /** 213582cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira * Get the cc recipients. 213682cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira */ 213782cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira public String[] getCcAddresses() { 213882cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira return getAddressesFromList(mCc); 213982cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira } 214082cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira 214182cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira /** 214282cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira * Get the bcc recipients. 214382cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira */ 214482cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira public String[] getBccAddresses() { 214582cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira return getAddressesFromList(mBcc); 214682cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira } 214782cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira 214882cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira public String[] getAddressesFromList(RecipientEditTextView list) { 214982cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira if (list == null) { 215082cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira return new String[0]; 215182cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira } 215282cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira Rfc822Token[] tokens = Rfc822Tokenizer.tokenize(list.getText()); 215382cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira int count = tokens.length; 215482cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira String[] result = new String[count]; 215582cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira for (int i = 0; i < count; i++) { 215682cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira result[i] = tokens[i].toString(); 215782cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira } 215882cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira return result; 215982cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira } 216082cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira 216182cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira /** 216282cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira * Check for invalid email addresses. 216382cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira * @param to String array of email addresses to check. 216482cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira * @param wrongEmailsOut Emails addresses that were invalid. 216582cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira */ 216682cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira public void checkInvalidEmails(String[] to, List<String> wrongEmailsOut) { 2167e5f20bf1c293497625b0f2865302e6712a854959Mindy Pereira if (mValidator == null) { 2168e5f20bf1c293497625b0f2865302e6712a854959Mindy Pereira return; 2169e5f20bf1c293497625b0f2865302e6712a854959Mindy Pereira } 217082cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira for (String email : to) { 217182cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira if (!mValidator.isValid(email)) { 217282cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira wrongEmailsOut.add(email); 217382cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira } 217482cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira } 217582cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira } 217682cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira 217782cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira /** 217882cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira * Show an error because the user has entered an invalid recipient. 217982cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira * @param message 218082cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira */ 218182cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira public void showRecipientErrorDialog(String message) { 218282cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira // Only 1 invalid recipients error dialog should be allowed up at a 218382cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira // time. 218482cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira if (mRecipientErrorDialog != null) { 218582cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira mRecipientErrorDialog.dismiss(); 218682cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira } 218782cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira mRecipientErrorDialog = new AlertDialog.Builder(this).setMessage(message).setTitle( 218882cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira R.string.recipient_error_dialog_title) 218982cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira .setIconAttribute(android.R.attr.alertDialogIcon) 219082cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira .setPositiveButton( 219182cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira R.string.ok, new Dialog.OnClickListener() { 21920bbc858506c95005f2840fa5dff495a9216d2665Marc Blank @Override 219382cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira public void onClick(DialogInterface dialog, int which) { 219482cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira // after the user dismisses the recipient error 219582cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira // dialog we want to make sure to refocus the 219682cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira // recipient to field so they can fix the issue 219782cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira // easily 219882cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira if (mTo != null) { 219982cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira mTo.requestFocus(); 220082cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira } 220182cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira mRecipientErrorDialog = null; 220282cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira } 220382cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira }).show(); 220482cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira } 220582cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira 220682cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira /** 220782cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira * Update the state of the UI based on whether or not the current draft 220882cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira * needs to be saved and the message is not empty. 220982cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira */ 2210eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira public void updateSaveUi() { 221182cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira if (mSave != null) { 221282cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira mSave.setEnabled((shouldSave() && !isBlank())); 221382cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira } 221482cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira } 221582cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira 221682cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira /** 221782cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira * Returns true if we need to save the current draft. 221882cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira */ 221982cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira private boolean shouldSave() { 22207ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira synchronized (mDraftLock) { 222182cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira // The message should only be saved if: 222282cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira // It hasn't been sent AND 222382cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira // Some text has been added to the message OR 222482cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira // an attachment has been added or removed 2225a214833a75ba2b27cdd166ceee9a2529b13a17c4Mindy Pereira // AND there is actually something in the draft to save. 2226d47877e3860ea4249eddb3f6efefbc6cd39f2320Andy Huang return (mTextChanged || mAttachmentsChanged || mReplyFromChanged) 2227a214833a75ba2b27cdd166ceee9a2529b13a17c4Mindy Pereira && !isBlank(); 222882cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira } 222982cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira } 223082cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira 223182cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira /** 2232bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira * Check if all fields are blank. 223382cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira * @return boolean 223482cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira */ 223582cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira public boolean isBlank() { 223682cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira return mSubject.getText().length() == 0 2237bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira && (mBodyView.getText().length() == 0 || getSignatureStartPosition(mSignature, 2238bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira mBodyView.getText().toString()) == 0) 2239bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira && mTo.length() == 0 2240bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira && mCc.length() == 0 && mBcc.length() == 0 2241bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira && mAttachmentsView.getAttachments().size() == 0; 2242bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira } 2243bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira 2244bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira @VisibleForTesting 2245bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira protected int getSignatureStartPosition(String signature, String bodyText) { 2246bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira int startPos = -1; 2247bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira 2248bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira if (TextUtils.isEmpty(signature) || TextUtils.isEmpty(bodyText)) { 2249bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira return startPos; 2250bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira } 2251bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira 2252bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira int bodyLength = bodyText.length(); 2253bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira int signatureLength = signature.length(); 2254bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira String printableVersion = convertToPrintableSignature(signature); 2255bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira int printableLength = printableVersion.length(); 2256bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira 2257bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira if (bodyLength >= printableLength 2258bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira && bodyText.substring(bodyLength - printableLength) 2259bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira .equals(printableVersion)) { 2260bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira startPos = bodyLength - printableLength; 2261bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira } else if (bodyLength >= signatureLength 2262bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira && bodyText.substring(bodyLength - signatureLength) 2263bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira .equals(signature)) { 2264bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira startPos = bodyLength - signatureLength; 2265bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira } 2266bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira return startPos; 226782cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira } 226882cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira 226982cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira /** 227082cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira * Allows any changes made by the user to be ignored. Called when the user 227182cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira * decides to discard a draft. 227282cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira */ 227382cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira private void discardChanges() { 227482cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira mTextChanged = false; 2275eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira mAttachmentsChanged = false; 227682cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira mReplyFromChanged = false; 227733fe908589dca6a7f58aa9f56d73f74a48ac42f6Mindy Pereira } 227833fe908589dca6a7f58aa9f56d73f74a48ac42f6Mindy Pereira 227982cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira /** 2280181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira * @param body 2281181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira * @param save 2282181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira * @param showToast 2283181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira * @return Whether the send or save succeeded. 2284181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira */ 2285181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira protected boolean sendOrSaveWithSanityChecks(final boolean save, final boolean showToast, 2286dd19b63d3f560aba8962435ed5a2e1f5ae794351Mark Wei final boolean orientationChanged, final boolean autoSend) { 2287009b3712ff1657fa839049826451321fdd938d32Mark Wei if (mAccounts == null || mAccount == null) { 2288009b3712ff1657fa839049826451321fdd938d32Mark Wei Toast.makeText(this, R.string.send_failed, Toast.LENGTH_SHORT).show(); 2289dd19b63d3f560aba8962435ed5a2e1f5ae794351Mark Wei if (autoSend) { 2290dd19b63d3f560aba8962435ed5a2e1f5ae794351Mark Wei finish(); 2291dd19b63d3f560aba8962435ed5a2e1f5ae794351Mark Wei } 2292009b3712ff1657fa839049826451321fdd938d32Mark Wei return false; 2293009b3712ff1657fa839049826451321fdd938d32Mark Wei } 2294009b3712ff1657fa839049826451321fdd938d32Mark Wei 2295181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira String[] to, cc, bcc; 2296181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira Editable body = mBodyView.getEditableText(); 2297181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira if (orientationChanged) { 2298181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira to = cc = bcc = new String[0]; 2299181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira } else { 2300181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira to = getToAddresses(); 2301181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira cc = getCcAddresses(); 2302181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira bcc = getBccAddresses(); 2303181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira } 2304181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira 2305181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira // Don't let the user send to nobody (but it's okay to save a message 2306181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira // with no recipients) 2307181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira if (!save && (to.length == 0 && cc.length == 0 && bcc.length == 0)) { 2308181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira showRecipientErrorDialog(getString(R.string.recipient_needed)); 2309181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira return false; 2310181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira } 2311181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira 2312181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira List<String> wrongEmails = new ArrayList<String>(); 2313181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira if (!save) { 2314181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira checkInvalidEmails(to, wrongEmails); 2315181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira checkInvalidEmails(cc, wrongEmails); 2316181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira checkInvalidEmails(bcc, wrongEmails); 2317181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira } 2318181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira 2319181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira // Don't let the user send an email with invalid recipients 2320181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira if (wrongEmails.size() > 0) { 2321181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira String errorText = String.format(getString(R.string.invalid_recipient), 2322181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira wrongEmails.get(0)); 2323181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira showRecipientErrorDialog(errorText); 2324181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira return false; 2325181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira } 2326181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira 2327181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira DialogInterface.OnClickListener listener = new DialogInterface.OnClickListener() { 23280bbc858506c95005f2840fa5dff495a9216d2665Marc Blank @Override 2329181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira public void onClick(DialogInterface dialog, int which) { 2330181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira sendOrSave(mBodyView.getEditableText(), save, showToast, orientationChanged); 2331181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira } 2332181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira }; 2333181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira 2334181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira // Show a warning before sending only if there are no attachments. 2335181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira if (!save) { 2336181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira if (mAttachmentsView.getAttachments().isEmpty() && showEmptyTextWarnings()) { 2337181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira boolean warnAboutEmptySubject = isSubjectEmpty(); 2338181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira boolean emptyBody = TextUtils.getTrimmedLength(body) == 0; 2339181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira 2340181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira // A warning about an empty body may not be warranted when 2341181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira // forwarding mails, since a common use case is to forward 2342181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira // quoted text and not append any more text. 2343181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira boolean warnAboutEmptyBody = emptyBody && (!mForward || isBodyEmpty()); 2344181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira 2345181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira // When we bring up a dialog warning the user about a send, 2346181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira // assume that they accept sending the message. If they do not, 2347181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira // the dialog listener is required to enable sending again. 2348181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira if (warnAboutEmptySubject) { 2349181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira showSendConfirmDialog(R.string.confirm_send_message_with_no_subject, listener); 2350181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira return true; 2351181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira } 2352181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira 2353181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira if (warnAboutEmptyBody) { 2354181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira showSendConfirmDialog(R.string.confirm_send_message_with_no_body, listener); 2355181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira return true; 2356181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira } 2357181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira } 2358181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira // Ask for confirmation to send (if always required) 2359181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira if (showSendConfirmation()) { 2360181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira showSendConfirmDialog(R.string.confirm_send_message, listener); 2361181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira return true; 2362181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira } 2363181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira } 2364181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira 2365181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira sendOrSave(body, save, showToast, false); 2366181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira return true; 2367181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira } 2368181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira 2369181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira /** 2370181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira * Returns a boolean indicating whether warnings should be shown for empty 2371181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira * subject and body fields 23725c5fd571b40a15b95ea5a5d6033f377706ffd0fbAndy Huang * 2373181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira * @return True if a warning should be shown for empty text fields 2374181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira */ 2375181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira protected boolean showEmptyTextWarnings() { 2376181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira return mAttachmentsView.getAttachments().size() == 0; 2377181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira } 2378181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira 2379181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira /** 2380181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira * Returns a boolean indicating whether the user should confirm each send 2381181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira * 2382181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira * @return True if a warning should be on each send 2383181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira */ 2384181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira protected boolean showSendConfirmation() { 2385181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira return mCachedSettings != null ? mCachedSettings.confirmSend : false; 2386181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira } 2387181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira 2388181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira private void showSendConfirmDialog(int messageId, DialogInterface.OnClickListener listener) { 2389181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira if (mSendConfirmDialog != null) { 2390181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira mSendConfirmDialog.dismiss(); 2391181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira mSendConfirmDialog = null; 2392181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira } 2393181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira mSendConfirmDialog = new AlertDialog.Builder(this).setMessage(messageId) 2394181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira .setTitle(R.string.confirm_send_title) 2395181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira .setIconAttribute(android.R.attr.alertDialogIcon) 2396181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira .setPositiveButton(R.string.send, listener) 23976edd597b1a6628660284f03442cce1f193af66dcMindy Pereira .setNegativeButton(R.string.cancel, this) 23986edd597b1a6628660284f03442cce1f193af66dcMindy Pereira .show(); 2399181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira } 2400181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira 2401181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira /** 2402181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira * Returns whether the ComposeArea believes there is any text in the body of 2403181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira * the composition. TODO: When ComposeArea controls the Body as well, add 2404181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira * that here. 2405181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira */ 2406181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira public boolean isBodyEmpty() { 2407181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira return !mQuotedTextView.isTextIncluded(); 2408181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira } 2409181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira 2410181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira /** 2411181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira * Test to see if the subject is empty. 2412181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira * 2413181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira * @return boolean. 2414181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira */ 2415181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira // TODO: this will likely go away when composeArea.focus() is implemented 2416181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira // after all the widget control is moved over. 2417181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira public boolean isSubjectEmpty() { 2418181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira return TextUtils.getTrimmedLength(mSubject.getText()) == 0; 2419181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira } 2420181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira 2421181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira /* package */ 2422e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira static int sendOrSaveInternal(Context context, ReplyFromAccount replyFromAccount, 242305b92b8ff275f85edae525623c71b65805ca3a51Paul Westbrook Message message, final Message refMessage, Spanned body, final CharSequence quotedText, 242444a6339dd80f4b5b9e5d54567021698d92467c5emindyp SendOrSaveCallback callback, Handler handler, boolean save, int composeMode, 242544a6339dd80f4b5b9e5d54567021698d92467c5emindyp ReplyFromAccount draftAccount) { 242629ef1b89b158281ffb693dd5f2c5291a894109fcMindy Pereira ContentValues values = new ContentValues(); 242729ef1b89b158281ffb693dd5f2c5291a894109fcMindy Pereira 2428c203197908a95f707e93621e5eb5f0fb8bfc7d1fMindy Pereira String refMessageId = refMessage != null ? refMessage.uri.toString() : ""; 2429c203197908a95f707e93621e5eb5f0fb8bfc7d1fMindy Pereira 2430e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira MessageModification.putToAddresses(values, message.getToAddresses()); 2431e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira MessageModification.putCcAddresses(values, message.getCcAddresses()); 2432e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira MessageModification.putBccAddresses(values, message.getBccAddresses()); 243329ef1b89b158281ffb693dd5f2c5291a894109fcMindy Pereira 24348960f0af431bc164003e09b3c8981aab808d9ec1Scott Kennedy MessageModification.putCustomFromAddress(values, message.getFrom()); 243592551d057965689f1952faeb06763f0762bc717fMindy Pereira 2436e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira MessageModification.putSubject(values, message.subject); 2437ed9c2f0e9b6b7d7556c3d048c78c072c21e587a1mindyp String htmlBody = Html.toHtml(new SpannableString(body.toString())); 243805b92b8ff275f85edae525623c71b65805ca3a51Paul Westbrook 243929ef1b89b158281ffb693dd5f2c5291a894109fcMindy Pereira boolean includeQuotedText = !TextUtils.isEmpty(quotedText); 244029ef1b89b158281ffb693dd5f2c5291a894109fcMindy Pereira StringBuilder fullBody = new StringBuilder(htmlBody); 244129ef1b89b158281ffb693dd5f2c5291a894109fcMindy Pereira if (includeQuotedText) { 2442e8caf1279a1c6ae720215405f678172a5cbf68d7Mindy Pereira // HTML gets converted to text for now 2443e8caf1279a1c6ae720215405f678172a5cbf68d7Mindy Pereira final String text = quotedText.toString(); 2444e8caf1279a1c6ae720215405f678172a5cbf68d7Mindy Pereira if (QuotedTextView.containsQuotedText(text)) { 2445e8caf1279a1c6ae720215405f678172a5cbf68d7Mindy Pereira int pos = QuotedTextView.getQuotedTextOffset(text); 244655271cf624269a5a19bb1989e5904df7adec7ef7Paul Westbrook final int quoteStartPos = fullBody.length() + pos; 244755271cf624269a5a19bb1989e5904df7adec7ef7Paul Westbrook fullBody.append(text); 244855271cf624269a5a19bb1989e5904df7adec7ef7Paul Westbrook MessageModification.putQuoteStartPos(values, quoteStartPos); 244912575866e5526e45eaf773c6c98c93c3a06fe156Mindy Pereira MessageModification.putForward(values, composeMode == ComposeActivity.FORWARD); 2450e8caf1279a1c6ae720215405f678172a5cbf68d7Mindy Pereira MessageModification.putAppendRefMessageContent(values, includeQuotedText); 245129ef1b89b158281ffb693dd5f2c5291a894109fcMindy Pereira } else { 2452e8caf1279a1c6ae720215405f678172a5cbf68d7Mindy Pereira LogUtils.w(LOG_TAG, "Couldn't find quoted text"); 2453e8caf1279a1c6ae720215405f678172a5cbf68d7Mindy Pereira // This shouldn't happen, but just use what we have, 2454e8caf1279a1c6ae720215405f678172a5cbf68d7Mindy Pereira // and don't do server-side expansion 2455e8caf1279a1c6ae720215405f678172a5cbf68d7Mindy Pereira fullBody.append(text); 245629ef1b89b158281ffb693dd5f2c5291a894109fcMindy Pereira } 245729ef1b89b158281ffb693dd5f2c5291a894109fcMindy Pereira } 2458002ff5244800c32f2d70c96cc1110657020ee65cMindy Pereira int draftType = getDraftType(composeMode); 245912575866e5526e45eaf773c6c98c93c3a06fe156Mindy Pereira MessageModification.putDraftType(values, draftType); 2460c6f1e2a8690bd3d4722a2e9386cdc98691135063Mindy Pereira if (refMessage != null) { 2461c6f1e2a8690bd3d4722a2e9386cdc98691135063Mindy Pereira if (!TextUtils.isEmpty(refMessage.bodyHtml)) { 2462c6f1e2a8690bd3d4722a2e9386cdc98691135063Mindy Pereira MessageModification.putBodyHtml(values, fullBody.toString()); 2463c6f1e2a8690bd3d4722a2e9386cdc98691135063Mindy Pereira } 2464c6f1e2a8690bd3d4722a2e9386cdc98691135063Mindy Pereira if (!TextUtils.isEmpty(refMessage.bodyText)) { 2465c59dd8270215f97d39697dae9e69976bcfe3642bmindyp MessageModification.putBody(values, 2466c59dd8270215f97d39697dae9e69976bcfe3642bmindyp Utils.convertHtmlToPlainText(fullBody.toString()).toString()); 2467c6f1e2a8690bd3d4722a2e9386cdc98691135063Mindy Pereira } 2468c6f1e2a8690bd3d4722a2e9386cdc98691135063Mindy Pereira } else { 2469c203197908a95f707e93621e5eb5f0fb8bfc7d1fMindy Pereira MessageModification.putBodyHtml(values, fullBody.toString()); 2470c59dd8270215f97d39697dae9e69976bcfe3642bmindyp MessageModification.putBody(values, Utils.convertHtmlToPlainText(fullBody.toString()) 2471c59dd8270215f97d39697dae9e69976bcfe3642bmindyp .toString()); 2472c203197908a95f707e93621e5eb5f0fb8bfc7d1fMindy Pereira } 2473e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira MessageModification.putAttachments(values, message.getAttachments()); 247412575866e5526e45eaf773c6c98c93c3a06fe156Mindy Pereira if (!TextUtils.isEmpty(refMessageId)) { 247512575866e5526e45eaf773c6c98c93c3a06fe156Mindy Pereira MessageModification.putRefMessageId(values, refMessageId); 247612575866e5526e45eaf773c6c98c93c3a06fe156Mindy Pereira } 24773c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook SendOrSaveMessage sendOrSaveMessage = new SendOrSaveMessage(context, replyFromAccount, 24783c7f94d02ff557c955c5d191cef45361a10be5c9Paul Westbrook values, refMessageId, message.getAttachments(), save); 247944a6339dd80f4b5b9e5d54567021698d92467c5emindyp SendOrSaveTask sendOrSaveTask = new SendOrSaveTask(context, sendOrSaveMessage, callback, 248044a6339dd80f4b5b9e5d54567021698d92467c5emindyp draftAccount); 248182cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira 2482181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira callback.initializeSendOrSave(sendOrSaveTask); 2483181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira // Do the send/save action on the specified handler to avoid possible 2484181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira // ANRs 2485181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira handler.post(sendOrSaveTask); 248682cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira 2487181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira return sendOrSaveMessage.requestId(); 2488181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira } 248982cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira 2490002ff5244800c32f2d70c96cc1110657020ee65cMindy Pereira private static int getDraftType(int mode) { 2491002ff5244800c32f2d70c96cc1110657020ee65cMindy Pereira int draftType = -1; 2492002ff5244800c32f2d70c96cc1110657020ee65cMindy Pereira switch (mode) { 2493002ff5244800c32f2d70c96cc1110657020ee65cMindy Pereira case ComposeActivity.COMPOSE: 2494002ff5244800c32f2d70c96cc1110657020ee65cMindy Pereira draftType = DraftType.COMPOSE; 2495002ff5244800c32f2d70c96cc1110657020ee65cMindy Pereira break; 2496002ff5244800c32f2d70c96cc1110657020ee65cMindy Pereira case ComposeActivity.REPLY: 2497002ff5244800c32f2d70c96cc1110657020ee65cMindy Pereira draftType = DraftType.REPLY; 2498002ff5244800c32f2d70c96cc1110657020ee65cMindy Pereira break; 2499002ff5244800c32f2d70c96cc1110657020ee65cMindy Pereira case ComposeActivity.REPLY_ALL: 2500002ff5244800c32f2d70c96cc1110657020ee65cMindy Pereira draftType = DraftType.REPLY_ALL; 2501002ff5244800c32f2d70c96cc1110657020ee65cMindy Pereira break; 2502002ff5244800c32f2d70c96cc1110657020ee65cMindy Pereira case ComposeActivity.FORWARD: 2503002ff5244800c32f2d70c96cc1110657020ee65cMindy Pereira draftType = DraftType.FORWARD; 2504002ff5244800c32f2d70c96cc1110657020ee65cMindy Pereira break; 2505002ff5244800c32f2d70c96cc1110657020ee65cMindy Pereira } 2506002ff5244800c32f2d70c96cc1110657020ee65cMindy Pereira return draftType; 2507002ff5244800c32f2d70c96cc1110657020ee65cMindy Pereira } 2508002ff5244800c32f2d70c96cc1110657020ee65cMindy Pereira 2509181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira private void sendOrSave(Spanned body, boolean save, boolean showToast, 2510181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira boolean orientationChanged) { 2511181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira // Check if user is a monkey. Monkeys can compose and hit send 2512181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira // button but are not allowed to send anything off the device. 25133ae824c79ffba25b0cda8b0300f41a28cfbfca7fPaul Westbrook if (ActivityManager.isUserAMonkey()) { 2514181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira return; 2515181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira } 251682cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira 2517181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira String[] to, cc, bcc; 2518181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira if (orientationChanged) { 2519181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira to = cc = bcc = new String[0]; 2520181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira } else { 2521181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira to = getToAddresses(); 2522181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira cc = getCcAddresses(); 2523181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira bcc = getBccAddresses(); 2524181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira } 252582cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira 2526181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira SendOrSaveCallback callback = new SendOrSaveCallback() { 25271f8f4dd8c53e6c18ae642235335ce492c9d1e520Andy Huang // FIXME: unused 252882cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira private int mRestoredRequestId; 252982cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira 25300bbc858506c95005f2840fa5dff495a9216d2665Marc Blank @Override 253182cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira public void initializeSendOrSave(SendOrSaveTask sendOrSaveTask) { 2532181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira synchronized (mActiveTasks) { 2533181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira int numTasks = mActiveTasks.size(); 2534181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira if (numTasks == 0) { 2535181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira // Start service so we won't be killed if this app is 2536181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira // put in the background. 2537181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira startService(new Intent(ComposeActivity.this, EmptyService.class)); 2538181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira } 2539181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira 2540181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira mActiveTasks.add(sendOrSaveTask); 2541181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira } 2542181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira if (sTestSendOrSaveCallback != null) { 2543181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira sTestSendOrSaveCallback.initializeSendOrSave(sendOrSaveTask); 2544181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira } 2545181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira } 254682cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira 25470bbc858506c95005f2840fa5dff495a9216d2665Marc Blank @Override 25487ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira public void notifyMessageIdAllocated(SendOrSaveMessage sendOrSaveMessage, 25497ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira Message message) { 2550181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira synchronized (mDraftLock) { 255144a6339dd80f4b5b9e5d54567021698d92467c5emindyp mDraftAccount = sendOrSaveMessage.mAccount; 2552181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira mDraftId = message.id; 2553181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira mDraft = message; 25547ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira if (sRequestMessageIdMap != null) { 25557ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira sRequestMessageIdMap.put(sendOrSaveMessage.requestId(), mDraftId); 25567ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira } 2557181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira // Cache request message map, in case the process is killed 2558181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira saveRequestMap(); 2559181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira } 2560181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira if (sTestSendOrSaveCallback != null) { 25617ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira sTestSendOrSaveCallback.notifyMessageIdAllocated(sendOrSaveMessage, message); 2562181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira } 2563181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira } 256482cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira 25650bbc858506c95005f2840fa5dff495a9216d2665Marc Blank @Override 25667ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira public Message getMessage() { 25677ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira synchronized (mDraftLock) { 25687ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira return mDraft; 25697ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira } 25707ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira } 257182cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira 25720bbc858506c95005f2840fa5dff495a9216d2665Marc Blank @Override 25737ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira public void sendOrSaveFinished(SendOrSaveTask task, boolean success) { 257447d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereira // Update the last sent from account. 257547d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereira if (mAccount != null) { 257647d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereira MailAppProvider.getInstance().setLastSentFromAccount(mAccount.uri.toString()); 257747d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereira } 25787ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira if (success) { 25797ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira // Successfully sent or saved so reset change markers 25807ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira discardChanges(); 25817ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira } else { 25827ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira // A failure happened with saving/sending the draft 25837ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira // TODO(pwestbro): add a better string that should be used 25847ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira // when failing to send or save 25857ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira Toast.makeText(ComposeActivity.this, R.string.send_failed, Toast.LENGTH_SHORT) 25867ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira .show(); 25877ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira } 258882cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira 25897ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira int numTasks; 25907ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira synchronized (mActiveTasks) { 25917ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira // Remove the task from the list of active tasks 25927ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira mActiveTasks.remove(task); 25937ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira numTasks = mActiveTasks.size(); 25947ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira } 259582cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira 25967ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira if (numTasks == 0) { 25977ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira // Stop service so we can be killed. 25987ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira stopService(new Intent(ComposeActivity.this, EmptyService.class)); 25997ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira } 26007ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira if (sTestSendOrSaveCallback != null) { 26017ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira sTestSendOrSaveCallback.sendOrSaveFinished(task, success); 26027ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira } 26037ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira } 2604181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira }; 2605181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira 2606181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira // Get the selected account if the from spinner has been setup. 260792551d057965689f1952faeb06763f0762bc717fMindy Pereira ReplyFromAccount selectedAccount = mReplyFromAccount; 2608181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira String fromAddress = selectedAccount.name; 2609181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira if (selectedAccount == null || fromAddress == null) { 2610181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira // We don't have either the selected account or from address, 2611181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira // use mAccount. 261292551d057965689f1952faeb06763f0762bc717fMindy Pereira selectedAccount = mReplyFromAccount; 2613181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira fromAddress = mAccount.name; 2614181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira } 2615181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira 2616181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira if (mSendSaveTaskHandler == null) { 2617181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira HandlerThread handlerThread = new HandlerThread("Send Message Task Thread"); 2618181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira handlerThread.start(); 2619181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira 2620181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira mSendSaveTaskHandler = new Handler(handlerThread.getLooper()); 2621181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira } 2622181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira 2623e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira Message msg = createMessage(mReplyFromAccount, getMode()); 262405b92b8ff275f85edae525623c71b65805ca3a51Paul Westbrook mRequestId = sendOrSaveInternal(this, mReplyFromAccount, msg, mRefMessage, body, 262505b92b8ff275f85edae525623c71b65805ca3a51Paul Westbrook mQuotedTextView.getQuotedTextIfIncluded(), callback, 262644a6339dd80f4b5b9e5d54567021698d92467c5emindyp mSendSaveTaskHandler, save, mComposeMode, mDraftAccount); 2627181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira 2628181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira if (mRecipient != null && mRecipient.equals(mAccount.name)) { 2629181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira mRecipient = selectedAccount.name; 2630181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira } 2631b1f573c59ec20f9149443e1e0cc8b64ff3a07feaPaul Westbrook setAccount(selectedAccount.account); 2632181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira 2633181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira // Don't display the toast if the user is just changing the orientation, 2634181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira // but we still need to save the draft to the cursor because this is how we restore 2635181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira // the attachments when the configuration change completes. 2636181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira if (showToast && (getChangingConfigurations() & ActivityInfo.CONFIG_ORIENTATION) == 0) { 2637181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira Toast.makeText(this, save ? R.string.message_saved : R.string.sending_message, 2638181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira Toast.LENGTH_LONG).show(); 2639181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira } 2640181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira 2641181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira // Need to update variables here because the send or save completes 2642181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira // asynchronously even though the toast shows right away. 2643181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira discardChanges(); 2644181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira updateSaveUi(); 2645181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira 2646181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira // If we are sending, finish the activity 2647181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira if (!save) { 2648181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira finish(); 2649181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira } 2650181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira } 2651181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira 2652181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira /** 2653181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira * Save the state of the request messageid map. This allows for the Gmail 2654181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira * process to be killed, but and still allow for ComposeActivity instances 2655181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira * to be recreated correctly. 2656181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira */ 2657181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira private void saveRequestMap() { 2658181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira // TODO: store the request map in user preferences. 2659181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira } 266082cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira 26612db7d4a37b794e1721a5b9416068702aa799c5f8Mindy Pereira private void doAttach(String type) { 2662013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira Intent i = new Intent(Intent.ACTION_GET_CONTENT); 2663013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira i.addCategory(Intent.CATEGORY_OPENABLE); 2664d6a9a3f94c69d05f23349a09d71cd36c6fb03613Paul Westbrook i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET); 26652db7d4a37b794e1721a5b9416068702aa799c5f8Mindy Pereira i.setType(type); 2666013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira mAddingAttachment = true; 2667181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira startActivityForResult(Intent.createChooser(i, getText(R.string.select_attachment_type)), 2668181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira RESULT_PICK_ATTACHMENT); 2669013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira } 2670013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira 2671ec8b0edb23c0e0b7f1a8ce9558a919be31169d45Mindy Pereira private void showCcBccViews() { 2672a26b54e3a858de409be3746e65591bb8a0d6ea9aMindy Pereira mCcBccView.show(true, true, true); 2673ec8b0edb23c0e0b7f1a8ce9558a919be31169d45Mindy Pereira if (mCcBccButton != null) { 2674cd0b0b950efebfc3964334067747b97e61c4f027mindyp mCcBccButton.setVisibility(View.INVISIBLE); 2675ec8b0edb23c0e0b7f1a8ce9558a919be31169d45Mindy Pereira } 2676ec8b0edb23c0e0b7f1a8ce9558a919be31169d45Mindy Pereira } 2677ec8b0edb23c0e0b7f1a8ce9558a919be31169d45Mindy Pereira 2678326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira @Override 2679326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira public boolean onNavigationItemSelected(int position, long itemId) { 2680a26b54e3a858de409be3746e65591bb8a0d6ea9aMindy Pereira int initialComposeMode = mComposeMode; 2681326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira if (position == ComposeActivity.REPLY) { 2682326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira mComposeMode = ComposeActivity.REPLY; 2683326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } else if (position == ComposeActivity.REPLY_ALL) { 2684326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira mComposeMode = ComposeActivity.REPLY_ALL; 2685326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } else if (position == ComposeActivity.FORWARD) { 2686326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira mComposeMode = ComposeActivity.FORWARD; 2687326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } 2688cbfb75a0f92a3ef5cf10ab94b451e4898cc78bfcMindy Pereira clearChangeListeners(); 2689a26b54e3a858de409be3746e65591bb8a0d6ea9aMindy Pereira if (initialComposeMode != mComposeMode) { 2690154386a287a9bfffb2eb3a4c05445f2774e1d4f0Mindy Pereira resetMessageForModeChange(); 269168c0bfcc4c5ee390305b6f677dc43ad0036371d8mindyp if (mRefMessage != null) { 26920aeaf7d8c2ee4bc882ca901531f985c61b4cc7c7Scott Kennedy setFieldsFromRefMessage(mComposeMode); 26938eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira } 2694ef38830943dac17adb4cade670b5ae0c6b4442c6Mindy Pereira boolean showCc = false; 2695ef38830943dac17adb4cade670b5ae0c6b4442c6Mindy Pereira boolean showBcc = false; 2696ef38830943dac17adb4cade670b5ae0c6b4442c6Mindy Pereira if (mDraft != null) { 2697ef38830943dac17adb4cade670b5ae0c6b4442c6Mindy Pereira // Following desktop behavior, if the user has added a BCC 2698ef38830943dac17adb4cade670b5ae0c6b4442c6Mindy Pereira // field to a draft, we show it regardless of compose mode. 26998960f0af431bc164003e09b3c8981aab808d9ec1Scott Kennedy showBcc = !TextUtils.isEmpty(mDraft.getBcc()); 2700ef38830943dac17adb4cade670b5ae0c6b4442c6Mindy Pereira // Use the draft to determine what to populate. 2701ef38830943dac17adb4cade670b5ae0c6b4442c6Mindy Pereira // If the Bcc field is showing, show the Cc field whether it is populated or not. 27028960f0af431bc164003e09b3c8981aab808d9ec1Scott Kennedy showCc = showBcc 27038960f0af431bc164003e09b3c8981aab808d9ec1Scott Kennedy || (!TextUtils.isEmpty(mDraft.getCc()) && mComposeMode == REPLY_ALL); 270468c0bfcc4c5ee390305b6f677dc43ad0036371d8mindyp } 270568c0bfcc4c5ee390305b6f677dc43ad0036371d8mindyp if (mRefMessage != null) { 27069b1ac57b10316cc1416c46f04811c54830e01529mindyp showCc = !TextUtils.isEmpty(mCc.getText()); 270768c0bfcc4c5ee390305b6f677dc43ad0036371d8mindyp showBcc = !TextUtils.isEmpty(mBcc.getText()); 2708ef38830943dac17adb4cade670b5ae0c6b4442c6Mindy Pereira } 2709ef38830943dac17adb4cade670b5ae0c6b4442c6Mindy Pereira mCcBccView.show(false, showCc, showBcc); 2710a26b54e3a858de409be3746e65591bb8a0d6ea9aMindy Pereira } 2711ef38830943dac17adb4cade670b5ae0c6b4442c6Mindy Pereira updateHideOrShowCcBcc(); 2712cbfb75a0f92a3ef5cf10ab94b451e4898cc78bfcMindy Pereira initChangeListeners(); 2713326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira return true; 2714326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } 2715326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira 2716b3112a2bf7b805695259e412b0e2bc0e0e73e9d6Mindy Pereira @VisibleForTesting 2717b3112a2bf7b805695259e412b0e2bc0e0e73e9d6Mindy Pereira protected void resetMessageForModeChange() { 2718154386a287a9bfffb2eb3a4c05445f2774e1d4f0Mindy Pereira // When switching between reply, reply all, forward, 2719154386a287a9bfffb2eb3a4c05445f2774e1d4f0Mindy Pereira // follow the behavior of webview. 2720154386a287a9bfffb2eb3a4c05445f2774e1d4f0Mindy Pereira // The contents of the following fields are cleared 2721154386a287a9bfffb2eb3a4c05445f2774e1d4f0Mindy Pereira // so that they can be populated directly from the 2722154386a287a9bfffb2eb3a4c05445f2774e1d4f0Mindy Pereira // ref message: 2723154386a287a9bfffb2eb3a4c05445f2774e1d4f0Mindy Pereira // 1) Any recipient fields 2724154386a287a9bfffb2eb3a4c05445f2774e1d4f0Mindy Pereira // 2) The subject 2725154386a287a9bfffb2eb3a4c05445f2774e1d4f0Mindy Pereira mTo.setText(""); 2726154386a287a9bfffb2eb3a4c05445f2774e1d4f0Mindy Pereira mCc.setText(""); 2727154386a287a9bfffb2eb3a4c05445f2774e1d4f0Mindy Pereira mBcc.setText(""); 2728154386a287a9bfffb2eb3a4c05445f2774e1d4f0Mindy Pereira // Any edits to the subject are replaced with the original subject. 2729154386a287a9bfffb2eb3a4c05445f2774e1d4f0Mindy Pereira mSubject.setText(""); 2730154386a287a9bfffb2eb3a4c05445f2774e1d4f0Mindy Pereira 2731154386a287a9bfffb2eb3a4c05445f2774e1d4f0Mindy Pereira // Any changes to the contents of the following fields are kept: 2732154386a287a9bfffb2eb3a4c05445f2774e1d4f0Mindy Pereira // 1) Body 2733154386a287a9bfffb2eb3a4c05445f2774e1d4f0Mindy Pereira // 2) Attachments 2734154386a287a9bfffb2eb3a4c05445f2774e1d4f0Mindy Pereira // If the user made changes to attachments, keep their changes. 2735154386a287a9bfffb2eb3a4c05445f2774e1d4f0Mindy Pereira if (!mAttachmentsChanged) { 2736154386a287a9bfffb2eb3a4c05445f2774e1d4f0Mindy Pereira mAttachmentsView.deleteAllAttachments(); 2737154386a287a9bfffb2eb3a4c05445f2774e1d4f0Mindy Pereira } 2738154386a287a9bfffb2eb3a4c05445f2774e1d4f0Mindy Pereira } 2739154386a287a9bfffb2eb3a4c05445f2774e1d4f0Mindy Pereira 2740326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira private class ComposeModeAdapter extends ArrayAdapter<String> { 2741326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira 2742326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira private LayoutInflater mInflater; 2743326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira 2744326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira public ComposeModeAdapter(Context context) { 2745326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira super(context, R.layout.compose_mode_item, R.id.mode, getResources() 2746326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira .getStringArray(R.array.compose_modes)); 2747326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } 2748326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira 2749326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira private LayoutInflater getInflater() { 2750326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira if (mInflater == null) { 2751326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira mInflater = LayoutInflater.from(getContext()); 2752326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } 2753326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira return mInflater; 2754326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } 2755326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira 2756326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira @Override 2757326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira public View getView(int position, View convertView, ViewGroup parent) { 2758326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira if (convertView == null) { 2759326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira convertView = getInflater().inflate(R.layout.compose_mode_display_item, null); 2760326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } 2761326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira ((TextView) convertView.findViewById(R.id.mode)).setText(getItem(position)); 2762326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira return super.getView(position, convertView, parent); 2763326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } 2764326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } 276546ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira 276646ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira @Override 276746ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira public void onRespondInline(String text) { 276846ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira appendToBody(text, false); 276940882430c874ff29890ec6fa31f7649788cbc470mindyp mQuotedTextView.setUpperDividerVisible(false); 27701623f9bfde8ced840a52820da28a0939bcaa32f9mindyp mRespondedInline = true; 277109dd373fae26156a847bb99d88474a7538b9e7c1mindyp if (!mBodyView.hasFocus()) { 27728654d4fcc09ba68872e677b2a57877a46d27fdb5mindyp mBodyView.requestFocus(); 277309dd373fae26156a847bb99d88474a7538b9e7c1mindyp } 277446ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira } 277546ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira 277646ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira /** 277746ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira * Append text to the body of the message. If there is no existing body 277846ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira * text, just sets the body to text. 277946ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira * 278046ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira * @param text 278146ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira * @param withSignature True to append a signature. 278246ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira */ 278346ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira public void appendToBody(CharSequence text, boolean withSignature) { 2784eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira Editable bodyText = mBodyView.getEditableText(); 278546ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira if (bodyText != null && bodyText.length() > 0) { 278646ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira bodyText.append(text); 278746ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira } else { 278846ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira setBody(text, withSignature); 278946ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira } 279046ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira } 279146ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira 279246ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira /** 279346ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira * Set the body of the message. 2794bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira * 279546ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira * @param text 279646ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira * @param withSignature True to append a signature. 279746ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira */ 279846ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira public void setBody(CharSequence text, boolean withSignature) { 2799eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira mBodyView.setText(text); 2800bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira if (withSignature) { 2801bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira appendSignature(); 2802bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira } 2803bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira } 2804bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira 2805bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira private void appendSignature() { 2806b13917c3d753c6674db2a226668a7f3048ddc4b5Mindy Pereira String newSignature = mCachedSettings != null ? mCachedSettings.signature : null; 2807433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira boolean hasFocus = mBodyView.hasFocus(); 28082708306e0b6f8dde22b2571d0dbcc28a53c9f29bmindyp int signaturePos = getSignatureStartPosition(mSignature, mBodyView.getText().toString()); 28092708306e0b6f8dde22b2571d0dbcc28a53c9f29bmindyp if (!TextUtils.equals(newSignature, mSignature) || signaturePos < 0) { 2810b13917c3d753c6674db2a226668a7f3048ddc4b5Mindy Pereira mSignature = newSignature; 28112708306e0b6f8dde22b2571d0dbcc28a53c9f29bmindyp if (!TextUtils.isEmpty(mSignature)) { 2812b13917c3d753c6674db2a226668a7f3048ddc4b5Mindy Pereira // Appending a signature does not count as changing text. 2813b13917c3d753c6674db2a226668a7f3048ddc4b5Mindy Pereira mBodyView.removeTextChangedListener(this); 2814b13917c3d753c6674db2a226668a7f3048ddc4b5Mindy Pereira mBodyView.append(convertToPrintableSignature(mSignature)); 2815b13917c3d753c6674db2a226668a7f3048ddc4b5Mindy Pereira mBodyView.addTextChangedListener(this); 2816b13917c3d753c6674db2a226668a7f3048ddc4b5Mindy Pereira } 2817433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira if (hasFocus) { 2818433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira focusBody(); 2819433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira } 2820bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira } 2821bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira } 2822bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira 2823bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira private String convertToPrintableSignature(String signature) { 2824bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira String signatureResource = getResources().getString(R.string.signature); 2825bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira if (signature == null) { 2826bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira signature = ""; 2827bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira } 2828bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira return String.format(signatureResource, signature); 282946ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira } 28301a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira 28315a85e2b7485a5c407c581219fe1b44417f050529Mindy Pereira @Override 28325a85e2b7485a5c407c581219fe1b44417f050529Mindy Pereira public void onAccountChanged() { 283392551d057965689f1952faeb06763f0762bc717fMindy Pereira mReplyFromAccount = mFromSpinner.getCurrentAccount(); 283492551d057965689f1952faeb06763f0762bc717fMindy Pereira if (!mAccount.equals(mReplyFromAccount.account)) { 2835f432dbce53a73eabed150b35033f2ec1a70c9725mindyp // Clear a signature, if there was one. 2836f432dbce53a73eabed150b35033f2ec1a70c9725mindyp mBodyView.removeTextChangedListener(this); 2837f432dbce53a73eabed150b35033f2ec1a70c9725mindyp String oldSignature = mSignature; 2838f432dbce53a73eabed150b35033f2ec1a70c9725mindyp String bodyText = getBody().getText().toString(); 2839f432dbce53a73eabed150b35033f2ec1a70c9725mindyp if (!TextUtils.isEmpty(oldSignature)) { 2840f432dbce53a73eabed150b35033f2ec1a70c9725mindyp int pos = getSignatureStartPosition(oldSignature, bodyText); 2841f432dbce53a73eabed150b35033f2ec1a70c9725mindyp if (pos > -1) { 2842f432dbce53a73eabed150b35033f2ec1a70c9725mindyp mBodyView.setText(bodyText.substring(0, pos)); 2843f432dbce53a73eabed150b35033f2ec1a70c9725mindyp } 2844f432dbce53a73eabed150b35033f2ec1a70c9725mindyp } 2845b1f573c59ec20f9149443e1e0cc8b64ff3a07feaPaul Westbrook setAccount(mReplyFromAccount.account); 2846f432dbce53a73eabed150b35033f2ec1a70c9725mindyp mBodyView.addTextChangedListener(this); 2847181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira // TODO: handle discarding attachments when switching accounts. 2848181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira // Only enable save for this draft if there is any other content 2849181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira // in the message. 2850181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira if (!isBlank()) { 2851181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira enableSave(true); 2852181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira } 2853181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira mReplyFromChanged = true; 2854181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira initRecipients(); 285582cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira } 28561a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira } 285782cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira 285882cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira public void enableSave(boolean enabled) { 285982cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira if (mSave != null) { 286082cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira mSave.setEnabled(enabled); 286182cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira } 286282cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira } 286382cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira 286482cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira public void enableSend(boolean enabled) { 286582cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira if (mSend != null) { 286682cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira mSend.setEnabled(enabled); 286782cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira } 286882cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira } 286982cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira 287082cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira /** 287182cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira * Handles button clicks from any error dialogs dealing with sending 287282cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira * a message. 287382cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira */ 287482cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira @Override 287582cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira public void onClick(DialogInterface dialog, int which) { 287682cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira switch (which) { 287782cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira case DialogInterface.BUTTON_POSITIVE: { 287882cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira doDiscardWithoutConfirmation(true /* show toast */ ); 287982cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira break; 288082cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira } 288182cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira case DialogInterface.BUTTON_NEGATIVE: { 288282cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira // If the user cancels the send, re-enable the send button. 288382cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira enableSend(true); 288482cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira break; 288582cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira } 288682cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira } 288782cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira 288882cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira } 288982cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira 2890efe3d25aa19da172fd5c3ec39539cdd91f29e927Mindy Pereira private void doDiscard() { 2891efe3d25aa19da172fd5c3ec39539cdd91f29e927Mindy Pereira new AlertDialog.Builder(this).setMessage(R.string.confirm_discard_text) 2892efe3d25aa19da172fd5c3ec39539cdd91f29e927Mindy Pereira .setPositiveButton(R.string.ok, this) 2893efe3d25aa19da172fd5c3ec39539cdd91f29e927Mindy Pereira .setNegativeButton(R.string.cancel, null) 2894efe3d25aa19da172fd5c3ec39539cdd91f29e927Mindy Pereira .create().show(); 2895efe3d25aa19da172fd5c3ec39539cdd91f29e927Mindy Pereira } 289682cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira /** 289782cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira * Effectively discard the current message. 289882cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira * 289982cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira * This method is either invoked from the menu or from the dialog 290082cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira * once the user has confirmed that they want to discard the message. 290182cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira * @param showToast show "Message discarded" toast if true 290282cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira */ 290382cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira private void doDiscardWithoutConfirmation(boolean showToast) { 29047ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira synchronized (mDraftLock) { 290582cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira if (mDraftId != UIProvider.INVALID_MESSAGE_ID) { 290682cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira ContentValues values = new ContentValues(); 2907b7050e62aab7133dea300d7fb3266311da99ec80Paul Westbrook values.put(BaseColumns._ID, mDraftId); 290878ea8e20c7d678c79153a1f814d0740f2bf3e462Marc Blank if (!mAccount.expungeMessageUri.equals(Uri.EMPTY)) { 2909cfb7f33ff8ef9dc60b9143af32de64c7a3d71f36Mindy Pereira getContentResolver().update(mAccount.expungeMessageUri, values, null, null); 2910cfb7f33ff8ef9dc60b9143af32de64c7a3d71f36Mindy Pereira } else { 29110bbc858506c95005f2840fa5dff495a9216d2665Marc Blank getContentResolver().delete(mDraft.uri, null, null); 2912cfb7f33ff8ef9dc60b9143af32de64c7a3d71f36Mindy Pereira } 291382cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira // This is not strictly necessary (since we should not try to 291482cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira // save the draft after calling this) but it ensures that if we 291582cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira // do save again for some reason we make a new draft rather than 291682cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira // trying to resave an expunged draft. 291782cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira mDraftId = UIProvider.INVALID_MESSAGE_ID; 291882cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira } 291982cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira } 292082cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira 292182cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira if (showToast) { 292282cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira // Display a toast to let the user know 292382cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira Toast.makeText(this, R.string.message_discarded, Toast.LENGTH_SHORT).show(); 292482cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira } 292582cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira 292682cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira // This prevents the draft from being saved in onPause(). 292782cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira discardChanges(); 292882cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira finish(); 292982cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira } 293082cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira 2931eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira private void saveIfNeeded() { 2932eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira if (mAccount == null) { 2933eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira // We have not chosen an account yet so there's no way that we can save. This is ok, 2934eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira // though, since we are saving our state before AccountsActivity is activated. Thus, the 2935eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira // user has not interacted with us yet and there is no real state to save. 2936eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira return; 2937eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira } 2938eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira 2939eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira if (shouldSave()) { 294048e31b07b5ac7c83dc3a009242fa915afccddb9eMindy Pereira doSave(!mAddingAttachment /* show toast */); 2941eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira } 2942eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira } 2943eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira 2944eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira @Override 2945eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira public void onAttachmentDeleted() { 2946eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira mAttachmentsChanged = true; 294740882430c874ff29890ec6fa31f7649788cbc470mindyp // If we are showing any attachments, make sure we have an upper 294840882430c874ff29890ec6fa31f7649788cbc470mindyp // divider. 294940882430c874ff29890ec6fa31f7649788cbc470mindyp mQuotedTextView.setUpperDividerVisible(mAttachmentsView.getAttachments().size() > 0); 2950eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira updateSaveUi(); 2951eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira } 295275f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira 295340882430c874ff29890ec6fa31f7649788cbc470mindyp @Override 295440882430c874ff29890ec6fa31f7649788cbc470mindyp public void onAttachmentAdded() { 295540882430c874ff29890ec6fa31f7649788cbc470mindyp mQuotedTextView.setUpperDividerVisible(mAttachmentsView.getAttachments().size() > 0); 295640882430c874ff29890ec6fa31f7649788cbc470mindyp mAttachmentsView.focusLastAttachment(); 295740882430c874ff29890ec6fa31f7649788cbc470mindyp } 295875f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira 295975f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira /** 296075f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira * This is called any time one of our text fields changes. 296175f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira */ 29620bbc858506c95005f2840fa5dff495a9216d2665Marc Blank @Override 296375f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira public void afterTextChanged(Editable s) { 296475f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira mTextChanged = true; 296575f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira updateSaveUi(); 296675f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira } 296775f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira 296875f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira @Override 296975f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira public void beforeTextChanged(CharSequence s, int start, int count, int after) { 297075f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira // Do nothing. 297175f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira } 297275f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira 29730bbc858506c95005f2840fa5dff495a9216d2665Marc Blank @Override 297475f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira public void onTextChanged(CharSequence s, int start, int before, int count) { 297575f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira // Do nothing. 297675f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira } 297775f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira 297875f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira 297975f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira // There is a big difference between the text associated with an address changing 298075f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira // to add the display name or to format properly and a recipient being added or deleted. 298175f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira // Make sure we only notify of changes when a recipient has been added or deleted. 298275f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira private class RecipientTextWatcher implements TextWatcher { 298375f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira private HashMap<String, Integer> mContent = new HashMap<String, Integer>(); 298475f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira 298575f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira private RecipientEditTextView mView; 298675f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira 298775f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira private TextWatcher mListener; 298875f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira 298975f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira public RecipientTextWatcher(RecipientEditTextView view, TextWatcher listener) { 299075f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira mView = view; 299175f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira mListener = listener; 299275f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira } 299375f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira 299475f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira @Override 299575f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira public void afterTextChanged(Editable s) { 299675f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira if (hasChanged()) { 299775f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira mListener.afterTextChanged(s); 299875f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira } 299975f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira } 300075f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira 300175f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira private boolean hasChanged() { 300275f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira String[] currRecips = tokenizeRecips(getAddressesFromList(mView)); 300375f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira int totalCount = currRecips.length; 300475f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira int totalPrevCount = 0; 300575f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira for (Entry<String, Integer> entry : mContent.entrySet()) { 300675f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira totalPrevCount += entry.getValue(); 300775f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira } 300875f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira if (totalCount != totalPrevCount) { 300975f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira return true; 301075f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira } 301175f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira 301275f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira for (String recip : currRecips) { 301375f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira if (!mContent.containsKey(recip)) { 301475f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira return true; 301575f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira } else { 301675f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira int count = mContent.get(recip) - 1; 301775f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira if (count < 0) { 301875f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira return true; 301975f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira } else { 302075f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira mContent.put(recip, count); 302175f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira } 302275f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira } 302375f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira } 302475f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira return false; 302575f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira } 302675f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira 302775f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira private String[] tokenizeRecips(String[] recips) { 302875f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira // Tokenize them all and put them in the list. 302975f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira String[] recipAddresses = new String[recips.length]; 303075f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira for (int i = 0; i < recips.length; i++) { 303175f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira recipAddresses[i] = Rfc822Tokenizer.tokenize(recips[i])[0].getAddress(); 303275f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira } 303375f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira return recipAddresses; 303475f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira } 303575f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira 303675f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira @Override 303775f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira public void beforeTextChanged(CharSequence s, int start, int count, int after) { 303875f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira String[] recips = tokenizeRecips(getAddressesFromList(mView)); 303975f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira for (String recip : recips) { 304075f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira if (!mContent.containsKey(recip)) { 304175f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira mContent.put(recip, 1); 304275f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira } else { 304375f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira mContent.put(recip, (mContent.get(recip)) + 1); 304475f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira } 304575f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira } 304675f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira } 304775f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira 304875f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira @Override 304975f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira public void onTextChanged(CharSequence s, int start, int before, int count) { 305075f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira // Do nothing. 305175f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira } 305275f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira } 3053e011b1d1c8e2e674dfdf1985d9d13da8cc06d803Mindy Pereira 3054e011b1d1c8e2e674dfdf1985d9d13da8cc06d803Mindy Pereira public static void registerTestSendOrSaveCallback(SendOrSaveCallback testCallback) { 3055e011b1d1c8e2e674dfdf1985d9d13da8cc06d803Mindy Pereira if (sTestSendOrSaveCallback != null && testCallback != null) { 3056e011b1d1c8e2e674dfdf1985d9d13da8cc06d803Mindy Pereira throw new IllegalStateException("Attempting to register more than one test callback"); 3057e011b1d1c8e2e674dfdf1985d9d13da8cc06d803Mindy Pereira } 3058e011b1d1c8e2e674dfdf1985d9d13da8cc06d803Mindy Pereira sTestSendOrSaveCallback = testCallback; 3059e011b1d1c8e2e674dfdf1985d9d13da8cc06d803Mindy Pereira } 3060bddd6f39f34aa15fed2e757f7d3e4163272ca02cMindy Pereira 3061bddd6f39f34aa15fed2e757f7d3e4163272ca02cMindy Pereira @VisibleForTesting 3062bddd6f39f34aa15fed2e757f7d3e4163272ca02cMindy Pereira protected ArrayList<Attachment> getAttachments() { 3063bddd6f39f34aa15fed2e757f7d3e4163272ca02cMindy Pereira return mAttachmentsView.getAttachments(); 3064bddd6f39f34aa15fed2e757f7d3e4163272ca02cMindy Pereira } 306596a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira 306696a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira @Override 306796a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira public Loader<Cursor> onCreateLoader(int id, Bundle args) { 306896a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira switch (id) { 306996a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira case REFERENCE_MESSAGE_LOADER: 307096a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira return new CursorLoader(this, mRefMessageUri, UIProvider.MESSAGE_PROJECTION, null, 307196a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira null, null); 3072b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira case LOADER_ACCOUNT_CURSOR: 3073b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira return new CursorLoader(this, MailAppProvider.getAccountsUri(), 3074b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira UIProvider.ACCOUNTS_PROJECTION, null, null, null); 307596a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira } 307696a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira return null; 307796a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira } 307896a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira 307996a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira @Override 308096a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira public void onLoadFinished(Loader<Cursor> loader, Cursor data) { 3081b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira int id = loader.getId(); 3082b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira switch (id) { 3083b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira case REFERENCE_MESSAGE_LOADER: 3084b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira if (data != null && data.moveToFirst()) { 3085b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira mRefMessage = new Message(data); 3086b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira Intent intent = getIntent(); 3087b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira int action = intent.getIntExtra(EXTRA_ACTION, COMPOSE); 30880aeaf7d8c2ee4bc882ca901531f985c61b4cc7c7Scott Kennedy initFromRefMessage(action); 3089b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira finishSetup(action, intent, null, true); 3090b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira if (action != FORWARD) { 3091b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira String to = intent.getStringExtra(EXTRA_TO); 3092b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira if (!TextUtils.isEmpty(to)) { 30930aeaf7d8c2ee4bc882ca901531f985c61b4cc7c7Scott Kennedy mRefMessage.setTo(null); 30940aeaf7d8c2ee4bc882ca901531f985c61b4cc7c7Scott Kennedy mRefMessage.setFrom(null); 3095b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira clearChangeListeners(); 3096b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira mTo.append(to); 3097b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira initChangeListeners(); 3098b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira } 3099b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira } 3100b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira } else { 3101b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira finish(); 310296a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira } 3103b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira break; 3104b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira case LOADER_ACCOUNT_CURSOR: 3105b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira if (data != null && data.moveToFirst()) { 3106b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira // there are accounts now! 3107b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira Account account; 3108faa742fcff868e17fb7e78c4c3f3ffdb01386f57Paul Westbrook final ArrayList<Account> accounts = new ArrayList<Account>(); 3109faa742fcff868e17fb7e78c4c3f3ffdb01386f57Paul Westbrook final ArrayList<Account> initializedAccounts = new ArrayList<Account>(); 3110b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira do { 3111b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira account = new Account(data); 3112dfa1dec0cfdc263c51e971dc3c41b90386a24340Paul Westbrook if (account.isAccountReady()) { 3113b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira initializedAccounts.add(account); 3114b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira } 3115b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira accounts.add(account); 3116b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira } while (data.moveToNext()); 3117b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira if (initializedAccounts.size() > 0) { 3118b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira findViewById(R.id.wait).setVisibility(View.GONE); 3119b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira getLoaderManager().destroyLoader(LOADER_ACCOUNT_CURSOR); 3120b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira findViewById(R.id.compose).setVisibility(View.VISIBLE); 3121faa742fcff868e17fb7e78c4c3f3ffdb01386f57Paul Westbrook mAccounts = initializedAccounts.toArray( 3122faa742fcff868e17fb7e78c4c3f3ffdb01386f57Paul Westbrook new Account[initializedAccounts.size()]); 3123faa742fcff868e17fb7e78c4c3f3ffdb01386f57Paul Westbrook 3124b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira finishCreate(); 3125b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira invalidateOptionsMenu(); 3126b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira } else { 3127b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira // Show "waiting" 3128b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira account = accounts.size() > 0 ? accounts.get(0) : null; 3129b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira showWaitFragment(account); 3130b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira } 3131b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira } 3132b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira break; 3133b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira } 3134b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira } 3135b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira 3136b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira private void showWaitFragment(Account account) { 3137b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira WaitFragment fragment = getWaitFragment(); 3138b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira if (fragment != null) { 3139b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira fragment.updateAccount(account); 314096a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira } else { 3141b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira findViewById(R.id.wait).setVisibility(View.VISIBLE); 3142b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira replaceFragment(WaitFragment.newInstance(account, true), 3143b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira FragmentTransaction.TRANSIT_FRAGMENT_OPEN, TAG_WAIT); 314496a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira } 314596a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira } 314696a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira 3147b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira private WaitFragment getWaitFragment() { 3148b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira return (WaitFragment) getFragmentManager().findFragmentByTag(TAG_WAIT); 3149b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira } 3150b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira 3151b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira private int replaceFragment(Fragment fragment, int transition, String tag) { 3152b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira FragmentTransaction fragmentTransaction = getFragmentManager().beginTransaction(); 3153b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira fragmentTransaction.addToBackStack(null); 3154b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira fragmentTransaction.setTransition(transition); 3155b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira fragmentTransaction.replace(R.id.wait, fragment, tag); 3156b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira final int transactionId = fragmentTransaction.commitAllowingStateLoss(); 3157b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira return transactionId; 3158b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira } 3159b199d172dcb568e2c09ea60eeb109922eec2f07eMindy Pereira 316096a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira @Override 316196a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira public void onLoaderReset(Loader<Cursor> arg0) { 316296a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira // Do nothing. 316396a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira } 31641f8f4dd8c53e6c18ae642235335ce492c9d1e520Andy Huang} 3165