ComposeActivity.java revision d47877e3860ea4249eddb3f6efefbc6cd39f2320
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 19ebc4bda7184ce659144eb95c7e73cb77ce3384daAndrew Sappersteinimport android.animation.LayoutTransition; 20326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereiraimport android.app.ActionBar; 215c5fd571b40a15b95ea5a5d6033f377706ffd0fbAndy Huangimport android.app.ActionBar.OnNavigationListener; 225c5fd571b40a15b95ea5a5d6033f377706ffd0fbAndy Huangimport android.app.Activity; 2382cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereiraimport android.app.ActivityManager; 2482cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereiraimport android.app.AlertDialog; 2582cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereiraimport android.app.Dialog; 2696a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereiraimport android.app.LoaderManager; 276349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereiraimport android.content.ContentResolver; 2882cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereiraimport android.content.ContentValues; 296349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereiraimport android.content.Context; 3096a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereiraimport android.content.CursorLoader; 3182cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereiraimport android.content.DialogInterface; 326349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereiraimport android.content.Intent; 3396a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereiraimport android.content.Loader; 3482cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereiraimport android.content.pm.ActivityInfo; 357ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereiraimport android.database.Cursor; 366349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereiraimport android.net.Uri; 378e9305ec0bbe23cec01eb34a2aee76c55199a10aMindy Pereiraimport android.os.Bundle; 3882cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereiraimport android.os.Handler; 3982cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereiraimport android.os.HandlerThread; 40f97588bd03fdcd318e24a9d74a283e73d1fbd37cPaul Westbrookimport android.os.Parcelable; 4182cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereiraimport android.provider.BaseColumns; 4246ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereiraimport android.text.Editable; 4382cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereiraimport android.text.Html; 4482cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereiraimport android.text.Spanned; 45c182762df95fd382faf8e4a25e5cf7783ea10176Paul Westbrookimport android.text.TextUtils; 4682cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereiraimport android.text.TextWatcher; 4746ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereiraimport android.text.util.Rfc822Token; 48c17d073dd43871df36ea70b3dea55963bdb98384Mindy Pereiraimport android.text.util.Rfc822Tokenizer; 493cd4f40dab2c0810cb5ecd77256abf022863b2b5Mindy Pereiraimport android.view.Gravity; 50326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereiraimport android.view.LayoutInflater; 51b47f3e286bcf78e85ab2d3389e38e99020d0634fMindy Pereiraimport android.view.Menu; 52b47f3e286bcf78e85ab2d3389e38e99020d0634fMindy Pereiraimport android.view.MenuInflater; 53b47f3e286bcf78e85ab2d3389e38e99020d0634fMindy Pereiraimport android.view.MenuItem; 548e9305ec0bbe23cec01eb34a2aee76c55199a10aMindy Pereiraimport android.view.View; 558e9305ec0bbe23cec01eb34a2aee76c55199a10aMindy Pereiraimport android.view.View.OnClickListener; 565c5fd571b40a15b95ea5a5d6033f377706ffd0fbAndy Huangimport android.view.ViewGroup; 57eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereiraimport android.view.inputmethod.BaseInputConnection; 58326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereiraimport android.widget.ArrayAdapter; 598e9305ec0bbe23cec01eb34a2aee76c55199a10aMindy Pereiraimport android.widget.Button; 60433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereiraimport android.widget.EditText; 611f93668e1186d48b507207841c1ca0529c3de292Mindy Pereiraimport android.widget.ImageView; 626349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereiraimport android.widget.TextView; 63013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereiraimport android.widget.Toast; 647b56a61174eeb202eea468b7f68b79729737ded2Mindy Pereira 65c17d073dd43871df36ea70b3dea55963bdb98384Mindy Pereiraimport com.android.common.Rfc822Validator; 665c5fd571b40a15b95ea5a5d6033f377706ffd0fbAndy Huangimport com.android.ex.chips.RecipientEditTextView; 675c5fd571b40a15b95ea5a5d6033f377706ffd0fbAndy Huangimport com.android.mail.R; 68eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereiraimport com.android.mail.compose.AttachmentsView.AttachmentDeletedListener; 699932dee248718d2cec993d93b5115973d1389d0aMindy Pereiraimport com.android.mail.compose.AttachmentsView.AttachmentFailureException; 705a85e2b7485a5c407c581219fe1b44417f050529Mindy Pereiraimport com.android.mail.compose.FromAddressSpinner.OnAccountChangedListener; 7130e2c24b056542f3b1b438aeb798305d1226d0c8Andy Huangimport com.android.mail.compose.QuotedTextView.RespondInlineListener; 7233fe908589dca6a7f58aa9f56d73f74a48ac42f6Mindy Pereiraimport com.android.mail.providers.Account; 7330e2c24b056542f3b1b438aeb798305d1226d0c8Andy Huangimport com.android.mail.providers.Address; 7430e2c24b056542f3b1b438aeb798305d1226d0c8Andy Huangimport com.android.mail.providers.Attachment; 755ad02918f663bc52522a2505de985df9ef5ea347Mindy Pereiraimport com.android.mail.providers.Folder; 7647d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereiraimport com.android.mail.providers.MailAppProvider; 773ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereiraimport com.android.mail.providers.Message; 7882cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereiraimport com.android.mail.providers.MessageModification; 7992551d057965689f1952faeb06763f0762bc717fMindy Pereiraimport com.android.mail.providers.ReplyFromAccount; 80181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereiraimport com.android.mail.providers.Settings; 8130e2c24b056542f3b1b438aeb798305d1226d0c8Andy Huangimport com.android.mail.providers.UIProvider; 823ca5bad62c075184920c5e331870280fc6acca16Mindy Pereiraimport com.android.mail.providers.UIProvider.AccountCapabilities; 8312575866e5526e45eaf773c6c98c93c3a06fe156Mindy Pereiraimport com.android.mail.providers.UIProvider.DraftType; 84fa20c1a4e36e0da2577baddbbb38a988b2017339Mindy Pereiraimport com.android.mail.ui.MailActivity; 8592227f6b35b3bec54609dc0feb9dd6756c2a43e6Paul Westbrookimport com.android.mail.utils.AccountUtils; 86b334c9035e9b7a38766bb66c29da2208525d1e11Paul Westbrookimport com.android.mail.utils.LogTag; 8730e2c24b056542f3b1b438aeb798305d1226d0c8Andy Huangimport com.android.mail.utils.LogUtils; 8830e2c24b056542f3b1b438aeb798305d1226d0c8Andy Huangimport com.android.mail.utils.Utils; 8946ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereiraimport com.google.common.annotations.VisibleForTesting; 9082cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereiraimport com.google.common.collect.Lists; 914a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereiraimport com.google.common.collect.Sets; 928e9305ec0bbe23cec01eb34a2aee76c55199a10aMindy Pereira 9362de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereiraimport org.json.JSONException; 9462de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira 958eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereiraimport java.io.UnsupportedEncodingException; 968eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereiraimport java.net.URLDecoder; 9746ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereiraimport java.util.ArrayList; 98bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrookimport java.util.Arrays; 9946ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereiraimport java.util.Collection; 10075f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereiraimport java.util.HashMap; 10146ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereiraimport java.util.HashSet; 10246ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereiraimport java.util.List; 1031c078cff1958b29e280100bfa6221103ec46b555Paul Westbrookimport java.util.Map.Entry; 104bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrookimport java.util.Set; 10582cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereiraimport java.util.concurrent.ConcurrentHashMap; 10646ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira 10746ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereirapublic class ComposeActivity extends Activity implements OnClickListener, OnNavigationListener, 1085a85e2b7485a5c407c581219fe1b44417f050529Mindy Pereira RespondInlineListener, DialogInterface.OnClickListener, TextWatcher, 10996a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira AttachmentDeletedListener, OnAccountChangedListener, LoaderManager.LoaderCallbacks<Cursor> { 1106349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira // Identifiers for which type of composition this is 11136bbcaeff2a6e57189e4f4818e0ccdf6317ce836Mindy Pereira static final int COMPOSE = -1; 11236bbcaeff2a6e57189e4f4818e0ccdf6317ce836Mindy Pereira static final int REPLY = 0; 11336bbcaeff2a6e57189e4f4818e0ccdf6317ce836Mindy Pereira static final int REPLY_ALL = 1; 11436bbcaeff2a6e57189e4f4818e0ccdf6317ce836Mindy Pereira static final int FORWARD = 2; 11536bbcaeff2a6e57189e4f4818e0ccdf6317ce836Mindy Pereira static final int EDIT_DRAFT = 3; 1166349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira 1176349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira // Integer extra holding one of the above compose action 11896a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira protected static final String EXTRA_ACTION = "action"; 1196349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira 120326689d531da1d2579fa7daaf6e307e24a05f993Mindy Pereira private static final String EXTRA_SHOW_CC = "showCc"; 121326689d531da1d2579fa7daaf6e307e24a05f993Mindy Pereira private static final String EXTRA_SHOW_BCC = "showBcc"; 122a34c9a054c9aef6f83abe56515c132a31d71b3c8Mindy Pereira 1238eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira private static final String UTF8_ENCODING_NAME = "UTF-8"; 1248eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira 1258eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira private static final String MAIL_TO = "mailto"; 1268eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira 1278eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira private static final String EXTRA_SUBJECT = "subject"; 1288eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira 1298eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira private static final String EXTRA_BODY = "body"; 1308eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira 1319a42bb4f11c502dd5c2cf92249ac214a6c2f1a70Mindy Pereira private static final String EXTRA_FROM_ACCOUNT_STRING = "fromAccountString"; 1329a42bb4f11c502dd5c2cf92249ac214a6c2f1a70Mindy Pereira 1338eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira // Extra that we can get passed from other activities 1348eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira private static final String EXTRA_TO = "to"; 1358eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira private static final String EXTRA_CC = "cc"; 1368eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira private static final String EXTRA_BCC = "bcc"; 1378eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira 1388eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira // List of all the fields 1398eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira static final String[] ALL_EXTRAS = { EXTRA_SUBJECT, EXTRA_BODY, EXTRA_TO, EXTRA_CC, EXTRA_BCC }; 1408eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira 14182cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira private static SendOrSaveCallback sTestSendOrSaveCallback = null; 14282cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira // Map containing information about requests to create new messages, and the id of the 14382cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira // messages that were the result of those requests. 14482cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira // 14582cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira // This map is used when the activity that initiated the save a of a new message, is killed 14682cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira // before the save has completed (and when we know the id of the newly created message). When 14782cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira // a save is completed, the service that is running in the background, will update the map 14882cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira // 14982cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira // When a new ComposeActivity instance is created, it will attempt to use the information in 15082cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira // the previously instantiated map. If ComposeActivity.onCreate() is called, with a bundle 15182cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira // (restoring data from a previous instance), and the map hasn't been created, we will attempt 15282cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira // to populate the map with data stored in shared preferences. 15382cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira private static ConcurrentHashMap<Integer, Long> sRequestMessageIdMap = null; 15482cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira // Key used to store the above map 15582cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira private static final String CACHED_MESSAGE_REQUEST_IDS_KEY = "cache-message-request-ids"; 1566349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira /** 1576349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira * Notifies the {@code Activity} that the caller is an Email 1586349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira * {@code Activity}, so that the back behavior may be modified accordingly. 1596349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira * 1606349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira * @see #onAppUpPressed 1616349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira */ 162daecb4b9b20a609b27fc803390ecf4f524b76089Paul Westbrook public static final String EXTRA_FROM_EMAIL_TASK = "fromemail"; 1636349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira 164e011b1d1c8e2e674dfdf1985d9d13da8cc06d803Mindy Pereira public static final String EXTRA_ATTACHMENTS = "attachments"; 165f97588bd03fdcd318e24a9d74a283e73d1fbd37cPaul Westbrook 1663ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereira // If this is a reply/forward then this extra will hold the original message 16736bbcaeff2a6e57189e4f4818e0ccdf6317ce836Mindy Pereira private static final String EXTRA_IN_REFERENCE_TO_MESSAGE = "in-reference-to-message"; 168b18e5a9341c73541d7201830c513cb0ed247e935Mindy Pereira // If this is a reply/forward then this extra will hold a uri we must query 169b18e5a9341c73541d7201830c513cb0ed247e935Mindy Pereira // to get the original message. 170b18e5a9341c73541d7201830c513cb0ed247e935Mindy Pereira protected static final String EXTRA_IN_REFERENCE_TO_MESSAGE_URI = "in-reference-to-message-uri"; 171bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook // If this is an action to edit an existing draft messagge, this extra will hold the 172bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook // draft message 173bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook private static final String ORIGINAL_DRAFT_MESSAGE = "original-draft-message"; 1744a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira private static final String END_TOKEN = ", "; 175b334c9035e9b7a38766bb66c29da2208525d1e11Paul Westbrook private static final String LOG_TAG = LogTag.getLogTag(); 176013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira // Request numbers for activities we start 177013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira private static final int RESULT_PICK_ATTACHMENT = 1; 178013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira private static final int RESULT_CREATE_ACCOUNT = 2; 1798eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira // TODO(mindyp) set mime-type for auto send? 180e011b1d1c8e2e674dfdf1985d9d13da8cc06d803Mindy Pereira public static final String AUTO_SEND_ACTION = "com.android.mail.action.AUTO_SEND"; 1818eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira 182e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira private static final String EXTRA_SELECTED_REPLY_FROM_ACCOUNT = "replyFromAccount"; 183e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira private static final String EXTRA_REQUEST_ID = "requestId"; 184e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira private static final String EXTRA_FOCUS_SELECTION_START = "focusSelectionStart"; 185e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira private static final String EXTRA_FOCUS_SELECTION_END = null; 186e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira private static final String EXTRA_MESSAGE = "extraMessage"; 18796a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira private static final int REFERENCE_MESSAGE_LOADER = 0; 18847d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereira private static final String EXTRA_SELECTED_ACCOUNT = "selectedAccount"; 1898e9305ec0bbe23cec01eb34a2aee76c55199a10aMindy Pereira 19082cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira /** 19182cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira * A single thread for running tasks in the background. 19282cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira */ 19382cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira private Handler mSendSaveTaskHandler = null; 194c17d073dd43871df36ea70b3dea55963bdb98384Mindy Pereira private RecipientEditTextView mTo; 195c17d073dd43871df36ea70b3dea55963bdb98384Mindy Pereira private RecipientEditTextView mCc; 196c17d073dd43871df36ea70b3dea55963bdb98384Mindy Pereira private RecipientEditTextView mBcc; 1978e9305ec0bbe23cec01eb34a2aee76c55199a10aMindy Pereira private Button mCcBccButton; 1988e9305ec0bbe23cec01eb34a2aee76c55199a10aMindy Pereira private CcBccView mCcBccView; 1997b56a61174eeb202eea468b7f68b79729737ded2Mindy Pereira private AttachmentsView mAttachmentsView; 20033fe908589dca6a7f58aa9f56d73f74a48ac42f6Mindy Pereira private Account mAccount; 20192551d057965689f1952faeb06763f0762bc717fMindy Pereira private ReplyFromAccount mReplyFromAccount; 202181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira private Settings mCachedSettings; 20382cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira private Rfc822Validator mValidator; 2046349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira private TextView mSubject; 2056349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira 206326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira private ComposeModeAdapter mComposeModeAdapter; 207326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira private int mComposeMode = -1; 20846ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira private boolean mForward; 20946ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira private String mRecipient; 21046ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira private QuotedTextView mQuotedTextView; 211433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira private EditText mBodyView; 2121a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira private View mFromStatic; 2132eb173211741adf7454bbf1990ba1b9d1e1f6a64Mindy Pereira private TextView mFromStaticText; 214eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira private View mFromSpinnerWrapper; 2151883b346928322a9f045bc5b7426ddcd6af9beb3Mindy Pereira @VisibleForTesting 2161883b346928322a9f045bc5b7426ddcd6af9beb3Mindy Pereira protected FromAddressSpinner mFromSpinner; 217013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira private boolean mAddingAttachment; 218eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira private boolean mAttachmentsChanged; 21982cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira private boolean mTextChanged; 22082cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira private boolean mReplyFromChanged; 22182cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira private MenuItem mSave; 22282cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira private MenuItem mSend; 22382cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira private AlertDialog mRecipientErrorDialog; 224eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira private AlertDialog mSendConfirmDialog; 225b3112a2bf7b805695259e412b0e2bc0e0e73e9d6Mindy Pereira @VisibleForTesting 226b3112a2bf7b805695259e412b0e2bc0e0e73e9d6Mindy Pereira protected Message mRefMessage; 2277ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira private long mDraftId = UIProvider.INVALID_MESSAGE_ID; 2287ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira private Message mDraft; 2297ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira private Object mDraftLock = new Object(); 2301f93668e1186d48b507207841c1ca0529c3de292Mindy Pereira private ImageView mAttachmentsButton; 2313ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereira 232326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira /** 233daecb4b9b20a609b27fc803390ecf4f524b76089Paul Westbrook * Boolean indicating whether ComposeActivity was launched from a Gmail controlled view. 234daecb4b9b20a609b27fc803390ecf4f524b76089Paul Westbrook */ 235daecb4b9b20a609b27fc803390ecf4f524b76089Paul Westbrook private boolean mLaunchedFromEmail = false; 236cbfb75a0f92a3ef5cf10ab94b451e4898cc78bfcMindy Pereira private RecipientTextWatcher mToListener; 237cbfb75a0f92a3ef5cf10ab94b451e4898cc78bfcMindy Pereira private RecipientTextWatcher mCcListener; 238cbfb75a0f92a3ef5cf10ab94b451e4898cc78bfcMindy Pereira private RecipientTextWatcher mBccListener; 239b18e5a9341c73541d7201830c513cb0ed247e935Mindy Pereira private Uri mRefMessageUri; 240daecb4b9b20a609b27fc803390ecf4f524b76089Paul Westbrook 241daecb4b9b20a609b27fc803390ecf4f524b76089Paul Westbrook 242daecb4b9b20a609b27fc803390ecf4f524b76089Paul Westbrook /** 243326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira * Can be called from a non-UI thread. 244326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira */ 2453ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereira public static void editDraft(Context launcher, Account account, Message message) { 246bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook launch(launcher, account, message, EDIT_DRAFT); 247326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } 248326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira 2496349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira /** 2506349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira * Can be called from a non-UI thread. 2516349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira */ 25233fe908589dca6a7f58aa9f56d73f74a48ac42f6Mindy Pereira public static void compose(Context launcher, Account account) { 2536349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira launch(launcher, account, null, COMPOSE); 2546349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira } 2556349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira 2566349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira /** 2576349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira * Can be called from a non-UI thread. 2586349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira */ 2593ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereira public static void reply(Context launcher, Account account, Message message) { 2603ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereira launch(launcher, account, message, REPLY); 2616349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira } 2626349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira 2636349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira /** 2646349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira * Can be called from a non-UI thread. 2656349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira */ 2663ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereira public static void replyAll(Context launcher, Account account, Message message) { 2673ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereira launch(launcher, account, message, REPLY_ALL); 2686349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira } 2696349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira 2706349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira /** 2716349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira * Can be called from a non-UI thread. 2726349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira */ 2733ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereira public static void forward(Context launcher, Account account, Message message) { 2743ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereira launch(launcher, account, message, FORWARD); 2756349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira } 2766349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira 2773ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereira private static void launch(Context launcher, Account account, Message message, int action) { 2786349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira Intent intent = new Intent(launcher, ComposeActivity.class); 2796349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira intent.putExtra(EXTRA_FROM_EMAIL_TASK, true); 2806349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira intent.putExtra(EXTRA_ACTION, action); 2816349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira intent.putExtra(Utils.EXTRA_ACCOUNT, account); 282bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook if (action == EDIT_DRAFT) { 283bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook intent.putExtra(ORIGINAL_DRAFT_MESSAGE, message); 284bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook } else { 285bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook intent.putExtra(EXTRA_IN_REFERENCE_TO_MESSAGE, message); 286bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook } 2876349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira launcher.startActivity(intent); 2886349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira } 2898e9305ec0bbe23cec01eb34a2aee76c55199a10aMindy Pereira 2908e9305ec0bbe23cec01eb34a2aee76c55199a10aMindy Pereira @Override 2918e9305ec0bbe23cec01eb34a2aee76c55199a10aMindy Pereira public void onCreate(Bundle savedInstanceState) { 2928e9305ec0bbe23cec01eb34a2aee76c55199a10aMindy Pereira super.onCreate(savedInstanceState); 2938e9305ec0bbe23cec01eb34a2aee76c55199a10aMindy Pereira setContentView(R.layout.compose); 29446ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira findViews(); 295818143e2163648acc0c91f123b84777d65cd70cfMindy Pereira Intent intent = getIntent(); 296e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira Message message; 29771c9e569c06ee362840c14093cf1973ecf297059Mindy Pereira boolean showQuotedText = false; 298e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira int action; 29947d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereira // Check for any of the possibly supplied accounts.; 30047d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereira Account account = null; 301f7fc6c339da7f73755041cceb9b8f8447680728aMindy Pereira if (hadSavedInstanceStateMessage(savedInstanceState)) { 302e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira action = savedInstanceState.getInt(EXTRA_ACTION, COMPOSE); 303e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira account = savedInstanceState.getParcelable(Utils.EXTRA_ACCOUNT); 304e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira message = (Message) savedInstanceState.getParcelable(EXTRA_MESSAGE); 305e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira mRefMessage = (Message) savedInstanceState.getParcelable(EXTRA_IN_REFERENCE_TO_MESSAGE); 306e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira } else { 30747d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereira account = obtainAccount(intent); 308e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira action = intent.getIntExtra(EXTRA_ACTION, COMPOSE); 309e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira // Initialize the message from the message in the intent 310e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira message = (Message) intent.getParcelableExtra(ORIGINAL_DRAFT_MESSAGE); 311e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira mRefMessage = (Message) intent.getParcelableExtra(EXTRA_IN_REFERENCE_TO_MESSAGE); 312b18e5a9341c73541d7201830c513cb0ed247e935Mindy Pereira mRefMessageUri = (Uri) intent.getParcelableExtra(EXTRA_IN_REFERENCE_TO_MESSAGE_URI); 313e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira } 31492227f6b35b3bec54609dc0feb9dd6756c2a43e6Paul Westbrook 31592227f6b35b3bec54609dc0feb9dd6756c2a43e6Paul Westbrook setAccount(account); 316818143e2163648acc0c91f123b84777d65cd70cfMindy Pereira if (mAccount == null) { 317818143e2163648acc0c91f123b84777d65cd70cfMindy Pereira return; 318818143e2163648acc0c91f123b84777d65cd70cfMindy Pereira } 319bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook 320daecb4b9b20a609b27fc803390ecf4f524b76089Paul Westbrook if (intent.getBooleanExtra(EXTRA_FROM_EMAIL_TASK, false)) { 321daecb4b9b20a609b27fc803390ecf4f524b76089Paul Westbrook mLaunchedFromEmail = true; 322daecb4b9b20a609b27fc803390ecf4f524b76089Paul Westbrook } else if (Intent.ACTION_SEND.equals(intent.getAction())) { 323daecb4b9b20a609b27fc803390ecf4f524b76089Paul Westbrook final Uri dataUri = intent.getData(); 324daecb4b9b20a609b27fc803390ecf4f524b76089Paul Westbrook if (dataUri != null) { 325daecb4b9b20a609b27fc803390ecf4f524b76089Paul Westbrook final String dataScheme = intent.getData().getScheme(); 326daecb4b9b20a609b27fc803390ecf4f524b76089Paul Westbrook final String accountScheme = mAccount.composeIntentUri.getScheme(); 327daecb4b9b20a609b27fc803390ecf4f524b76089Paul Westbrook mLaunchedFromEmail = TextUtils.equals(dataScheme, accountScheme); 328daecb4b9b20a609b27fc803390ecf4f524b76089Paul Westbrook } 329daecb4b9b20a609b27fc803390ecf4f524b76089Paul Westbrook } 330daecb4b9b20a609b27fc803390ecf4f524b76089Paul Westbrook 33196a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira if (mRefMessageUri != null) { 33296a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira // We have a referenced message that we must look up. 33396a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira getLoaderManager().initLoader(REFERENCE_MESSAGE_LOADER, null, this); 33496a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira return; 33596a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira } else if (message != null && action != EDIT_DRAFT) { 336e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira initFromDraftMessage(message); 337e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira initQuotedTextFromRefMessage(mRefMessage, action); 338a34c9a054c9aef6f83abe56515c132a31d71b3c8Mindy Pereira showCcBcc(savedInstanceState); 33971c9e569c06ee362840c14093cf1973ecf297059Mindy Pereira showQuotedText = message.appendRefMessageContent; 340e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira } else if (action == EDIT_DRAFT) { 341e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira initFromDraftMessage(message); 342ef38830943dac17adb4cade670b5ae0c6b4442c6Mindy Pereira boolean showBcc = !TextUtils.isEmpty(message.bcc); 343ef38830943dac17adb4cade670b5ae0c6b4442c6Mindy Pereira boolean showCc = showBcc || !TextUtils.isEmpty(message.cc); 344ef38830943dac17adb4cade670b5ae0c6b4442c6Mindy Pereira mCcBccView.show(false, showCc, showBcc); 345bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook // Update the action to the draft type of the previous draft 346bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook switch (message.draftType) { 347bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook case UIProvider.DraftType.REPLY: 348bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook action = REPLY; 349bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook break; 350bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook case UIProvider.DraftType.REPLY_ALL: 351bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook action = REPLY_ALL; 352bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook break; 353bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook case UIProvider.DraftType.FORWARD: 354bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook action = FORWARD; 355bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook break; 356bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook case UIProvider.DraftType.COMPOSE: 357bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook default: 358bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook action = COMPOSE; 359bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook break; 360bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook } 361e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira initQuotedTextFromRefMessage(mRefMessage, action); 36271c9e569c06ee362840c14093cf1973ecf297059Mindy Pereira showQuotedText = message.appendRefMessageContent; 363e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira } else if ((action == REPLY || action == REPLY_ALL || action == FORWARD)) { 364e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira if (mRefMessage != null) { 365e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira initFromRefMessage(action, mAccount.name); 36671c9e569c06ee362840c14093cf1973ecf297059Mindy Pereira showQuotedText = true; 367e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira } 3688eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira } else { 3698eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira initFromExtras(intent); 370bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook } 37196a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira finishSetup(action, intent, savedInstanceState, showQuotedText); 37296a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira } 373bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook 37447d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereira private Account obtainAccount(Intent intent) { 37547d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereira Account account = null; 37647d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereira Object accountExtra = null; 37747d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereira if (intent != null && intent.getExtras() != null) { 37847d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereira accountExtra = intent.getExtras().get(Utils.EXTRA_ACCOUNT); 37947d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereira if (accountExtra instanceof Account) { 38047d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereira return (Account) accountExtra; 38147d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereira } 38247d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereira accountExtra = intent.getStringExtra(EXTRA_SELECTED_ACCOUNT); 38347d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereira } 38447d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereira if (account == null) { 38547d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereira final String lastAccountUri = MailAppProvider.getInstance().getLastSentFromAccount(); 38647d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereira if (!TextUtils.isEmpty(lastAccountUri)) { 38747d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereira accountExtra = Uri.parse(lastAccountUri); 38847d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereira } 38947d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereira } 39047d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereira final Account[] syncingAccounts = AccountUtils.getSyncingAccounts(this); 39147d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereira if (syncingAccounts.length > 0) { 39247d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereira if (accountExtra instanceof String && !TextUtils.isEmpty((String) accountExtra)) { 39347d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereira // For backwards compatibility, we need to check account 39447d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereira // names. 39547d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereira for (Account a : syncingAccounts) { 39647d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereira if (a.name.equals(accountExtra)) { 39747d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereira account = a; 39847d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereira } 39947d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereira } 40047d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereira } else if (accountExtra instanceof Uri) { 40147d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereira // The uri of the last viewed account is what is stored in 40247d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereira // the current code base. 40347d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereira for (Account a : syncingAccounts) { 40447d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereira if (a.uri.equals(accountExtra)) { 40547d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereira account = a; 40647d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereira } 40747d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereira } 408fa20c1a4e36e0da2577baddbbb38a988b2017339Mindy Pereira } else { 409fa20c1a4e36e0da2577baddbbb38a988b2017339Mindy Pereira account = syncingAccounts[0]; 41047d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereira } 41147d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereira } 41247d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereira return account; 41347d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereira } 41447d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereira 41596a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira private void finishSetup(int action, Intent intent, Bundle savedInstanceState, 41696a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira boolean showQuotedText) { 417bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook if (action == COMPOSE) { 418eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira mQuotedTextView.setVisibility(View.GONE); 41946ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira } 420818143e2163648acc0c91f123b84777d65cd70cfMindy Pereira initRecipients(); 421f7fc6c339da7f73755041cceb9b8f8447680728aMindy Pereira // Don't bother with the intent if we have procured a message from the 422f7fc6c339da7f73755041cceb9b8f8447680728aMindy Pereira // intent already. 423f7fc6c339da7f73755041cceb9b8f8447680728aMindy Pereira if (!hadSavedInstanceStateMessage(savedInstanceState)) { 424f7fc6c339da7f73755041cceb9b8f8447680728aMindy Pereira initAttachmentsFromIntent(intent); 425f7fc6c339da7f73755041cceb9b8f8447680728aMindy Pereira } 4261a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira initActionBar(action); 427e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira initFromSpinner(savedInstanceState != null ? savedInstanceState : intent.getExtras(), 428e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira action); 42975f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira initChangeListeners(); 430433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira setFocus(action); 431326689d531da1d2579fa7daaf6e307e24a05f993Mindy Pereira updateHideOrShowCcBcc(); 43271c9e569c06ee362840c14093cf1973ecf297059Mindy Pereira updateHideOrShowQuotedText(showQuotedText); 43371c9e569c06ee362840c14093cf1973ecf297059Mindy Pereira } 43471c9e569c06ee362840c14093cf1973ecf297059Mindy Pereira 435f7fc6c339da7f73755041cceb9b8f8447680728aMindy Pereira private boolean hadSavedInstanceStateMessage(Bundle savedInstanceState) { 436f7fc6c339da7f73755041cceb9b8f8447680728aMindy Pereira return savedInstanceState != null && savedInstanceState.containsKey(EXTRA_MESSAGE); 437f7fc6c339da7f73755041cceb9b8f8447680728aMindy Pereira } 438f7fc6c339da7f73755041cceb9b8f8447680728aMindy Pereira 43971c9e569c06ee362840c14093cf1973ecf297059Mindy Pereira private void updateHideOrShowQuotedText(boolean showQuotedText) { 44071c9e569c06ee362840c14093cf1973ecf297059Mindy Pereira mQuotedTextView.updateCheckedState(showQuotedText); 441433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira } 442433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira 443433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira private void setFocus(int action) { 444433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira if (action == EDIT_DRAFT) { 445433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira int type = mDraft.draftType; 446433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira switch (type) { 447433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira case UIProvider.DraftType.COMPOSE: 448433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira case UIProvider.DraftType.FORWARD: 449433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira action = COMPOSE; 450433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira break; 451433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira case UIProvider.DraftType.REPLY: 452433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira case UIProvider.DraftType.REPLY_ALL: 453433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira default: 454433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira action = REPLY; 455433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira break; 456433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira } 457433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira } 458433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira switch (action) { 459433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira case FORWARD: 460433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira case COMPOSE: 461433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira mTo.requestFocus(); 462433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira break; 463433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira case REPLY: 464433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira case REPLY_ALL: 465433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira default: 466433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira focusBody(); 467433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira break; 468433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira } 469433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira } 470433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira 471433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira /** 472433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira * Focus the body of the message. 473433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira */ 474433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira public void focusBody() { 475433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira mBodyView.requestFocus(); 476433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira int length = mBodyView.getText().length(); 477433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira 478433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira int signatureStartPos = getSignatureStartPosition( 479433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira mSignature, mBodyView.getText().toString()); 480433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira if (signatureStartPos > -1) { 481433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira // In case the user deleted the newlines... 482433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira mBodyView.setSelection(signatureStartPos); 483433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira } else if (length > 0) { 484433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira // Move cursor to the end. 485433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira mBodyView.setSelection(length); 486433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira } 4871a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira } 4881a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira 4891a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira @Override 4901a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira protected void onResume() { 4911a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira super.onResume(); 4921a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira // Update the from spinner as other accounts 4931a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira // may now be available. 494818143e2163648acc0c91f123b84777d65cd70cfMindy Pereira if (mFromSpinner != null && mAccount != null) { 49562de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira mFromSpinner.asyncInitFromSpinner(mComposeMode, mAccount); 496818143e2163648acc0c91f123b84777d65cd70cfMindy Pereira } 4971a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira } 4981a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira 499eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira @Override 500eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira protected void onPause() { 501eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira super.onPause(); 502eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira 503eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira if (mSendConfirmDialog != null) { 504eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira mSendConfirmDialog.dismiss(); 505eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira } 506eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira if (mRecipientErrorDialog != null) { 507eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira mRecipientErrorDialog.dismiss(); 508eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira } 509a214833a75ba2b27cdd166ceee9a2529b13a17c4Mindy Pereira // When the user exits the compose view, see if this draft needs saving. 510a214833a75ba2b27cdd166ceee9a2529b13a17c4Mindy Pereira if (isFinishing()) { 511a214833a75ba2b27cdd166ceee9a2529b13a17c4Mindy Pereira saveIfNeeded(); 512a214833a75ba2b27cdd166ceee9a2529b13a17c4Mindy Pereira } 513eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira } 514eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira 515eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira @Override 516eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira protected final void onActivityResult(int request, int result, Intent data) { 517eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira mAddingAttachment = false; 518eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira 519eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira if (result == RESULT_OK && request == RESULT_PICK_ATTACHMENT) { 520eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira addAttachmentAndUpdateView(data); 521eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira } 522eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira } 523eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira 524eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira @Override 525e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira public final void onRestoreInstanceState(Bundle savedInstanceState) { 526e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira super.onRestoreInstanceState(savedInstanceState); 527e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira if (savedInstanceState != null) { 528e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira if (savedInstanceState.containsKey(EXTRA_FOCUS_SELECTION_START)) { 529e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira int selectionStart = savedInstanceState.getInt(EXTRA_FOCUS_SELECTION_START); 530e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira int selectionEnd = savedInstanceState.getInt(EXTRA_FOCUS_SELECTION_END); 531e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira // There should be a focus and it should be an EditText since we 532e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira // only save these extras if these conditions are true. 533e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira EditText focusEditText = (EditText) getCurrentFocus(); 534e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira final int length = focusEditText.getText().length(); 535e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira if (selectionStart < length && selectionEnd < length) { 536e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira focusEditText.setSelection(selectionStart, selectionEnd); 537e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira } 538e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira } 539e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira } 540e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira } 541e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira 542e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira @Override 543eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira public final void onSaveInstanceState(Bundle state) { 544eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira super.onSaveInstanceState(state); 545e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira // The framework is happy to save and restore the selection but only if it also saves and 546e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira // restores the contents of the edit text. That's a lot of text to put in a bundle so we do 547e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira // this manually. 548e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira View focus = getCurrentFocus(); 549e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira if (focus != null && focus instanceof EditText) { 550e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira EditText focusEditText = (EditText) focus; 551e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira state.putInt(EXTRA_FOCUS_SELECTION_START, focusEditText.getSelectionStart()); 552e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira state.putInt(EXTRA_FOCUS_SELECTION_END, focusEditText.getSelectionEnd()); 553e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira } 5546273e96b7204a33ea44823fb36fd7fc8baf5ba20Paul Westbrook 5556273e96b7204a33ea44823fb36fd7fc8baf5ba20Paul Westbrook final List<ReplyFromAccount> replyFromAccounts = mFromSpinner.getReplyFromAccounts(); 556151f1ad1613ecac0207144472872440517172b5aPaul Westbrook final int selectedPos = mFromSpinner.getSelectedItemPosition(); 557d90f7ac9b1a62e8beefdac3ceda9e4cb75ef000cMindy Pereira final ReplyFromAccount selectedReplyFromAccount = (replyFromAccounts != null 558d90f7ac9b1a62e8beefdac3ceda9e4cb75ef000cMindy Pereira && replyFromAccounts.size() > 0 && replyFromAccounts.size() > selectedPos) ? 559d90f7ac9b1a62e8beefdac3ceda9e4cb75ef000cMindy Pereira replyFromAccounts.get(selectedPos) : null; 560e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira if (selectedReplyFromAccount != null) { 561e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira state.putString(EXTRA_SELECTED_REPLY_FROM_ACCOUNT, selectedReplyFromAccount.serialize() 562e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira .toString()); 563e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira state.putParcelable(Utils.EXTRA_ACCOUNT, selectedReplyFromAccount.account); 564e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira } else { 565e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira state.putParcelable(Utils.EXTRA_ACCOUNT, mAccount); 566e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira } 567eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira 568e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira if (mDraftId == UIProvider.INVALID_MESSAGE_ID && mRequestId !=0) { 569e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira // We don't have a draft id, and we have a request id, 570e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira // save the request id. 571e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira state.putInt(EXTRA_REQUEST_ID, mRequestId); 572e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira } 573e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira 574e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira // We want to restore the current mode after a pause 575e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira // or rotation. 576e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira int mode = getMode(); 577e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira state.putInt(EXTRA_ACTION, mode); 578e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira 579e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira Message message = createMessage(selectedReplyFromAccount, mode); 580e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira state.putParcelable(EXTRA_MESSAGE, message); 581e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira 582e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira if (mRefMessage != null) { 583e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira state.putParcelable(EXTRA_IN_REFERENCE_TO_MESSAGE, mRefMessage); 584e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira } 585326689d531da1d2579fa7daaf6e307e24a05f993Mindy Pereira state.putBoolean(EXTRA_SHOW_CC, mCcBccView.isCcVisible()); 586326689d531da1d2579fa7daaf6e307e24a05f993Mindy Pereira state.putBoolean(EXTRA_SHOW_BCC, mCcBccView.isBccVisible()); 587e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira } 588e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira 589e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira private int getMode() { 590e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira int mode = ComposeActivity.COMPOSE; 591e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira ActionBar actionBar = getActionBar(); 592e011b1d1c8e2e674dfdf1985d9d13da8cc06d803Mindy Pereira if (actionBar != null 593e011b1d1c8e2e674dfdf1985d9d13da8cc06d803Mindy Pereira && actionBar.getNavigationMode() == ActionBar.NAVIGATION_MODE_LIST) { 594e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira mode = actionBar.getSelectedNavigationIndex(); 595e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira } 596e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira return mode; 597e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira } 598e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira 599e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira private Message createMessage(ReplyFromAccount selectedReplyFromAccount, int mode) { 600e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira Message message = new Message(); 601e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira message.id = UIProvider.INVALID_MESSAGE_ID; 602d47877e3860ea4249eddb3f6efefbc6cd39f2320Andy Huang message.serverId = null; 603e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira message.uri = null; 604e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira message.conversationUri = null; 605e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira message.subject = mSubject.getText().toString(); 606e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira message.snippet = null; 6071eedc7520600a315afba4fc114a9fc5bf1adacd7Mindy Pereira message.from = selectedReplyFromAccount != null ? selectedReplyFromAccount.address 608b67aa8f5975082434dc6b8ebeedf2f1333dbf86dMindy Pereira : mAccount != null ? mAccount.name : null; 6093c9115813343861a44133b805fb9f55512d20948Mindy Pereira message.to = formatSenders(mTo.getText().toString()); 6103c9115813343861a44133b805fb9f55512d20948Mindy Pereira message.cc = formatSenders(mCc.getText().toString()); 6113c9115813343861a44133b805fb9f55512d20948Mindy Pereira message.bcc = formatSenders(mBcc.getText().toString()); 612e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira message.replyTo = null; 613e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira message.dateReceivedMs = 0; 614e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira String htmlBody = Html.toHtml(mBodyView.getText()); 615e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira StringBuilder fullBody = new StringBuilder(htmlBody); 616e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira message.bodyHtml = fullBody.toString(); 617e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira message.bodyText = mBodyView.getText().toString(); 618e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira message.embedsExternalResources = false; 619e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira message.refMessageId = mRefMessage != null ? mRefMessage.uri.toString() : null; 620d2bef8b371784d95f60dd3f89aa0ac3557c945efMindy Pereira message.draftType = getDraftType(mode); 621e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira message.appendRefMessageContent = mQuotedTextView.getQuotedTextIfIncluded() != null; 622e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira ArrayList<Attachment> attachments = mAttachmentsView.getAttachments(); 623e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira message.hasAttachments = attachments != null && attachments.size() > 0; 624e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira message.attachmentListUri = null; 625e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira message.messageFlags = 0; 626e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira message.saveUri = null; 627e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira message.sendUri = null; 628e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira message.alwaysShowImages = false; 629e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira message.attachmentsJson = Attachment.toJSONArray(attachments); 630e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira CharSequence quotedText = mQuotedTextView.getQuotedText(); 631e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira message.quotedTextOffset = !TextUtils.isEmpty(quotedText) ? QuotedTextView 632e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira .getQuotedTextOffset(quotedText.toString()) : -1; 633e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira message.accountUri = null; 634e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira return message; 635eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira } 636eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira 6373c9115813343861a44133b805fb9f55512d20948Mindy Pereira private String formatSenders(String string) { 6383c9115813343861a44133b805fb9f55512d20948Mindy Pereira if (!TextUtils.isEmpty(string) && string.charAt(string.length() - 1) == ',') { 6393c9115813343861a44133b805fb9f55512d20948Mindy Pereira return string.substring(0, string.length() - 1); 6403c9115813343861a44133b805fb9f55512d20948Mindy Pereira } 6413c9115813343861a44133b805fb9f55512d20948Mindy Pereira return string; 6423c9115813343861a44133b805fb9f55512d20948Mindy Pereira } 6433c9115813343861a44133b805fb9f55512d20948Mindy Pereira 644818143e2163648acc0c91f123b84777d65cd70cfMindy Pereira @VisibleForTesting 645818143e2163648acc0c91f123b84777d65cd70cfMindy Pereira void setAccount(Account account) { 646bb5217ee950c156d761a086bfd0d1d392d224cf4Mindy Pereira if (account == null) { 647bb5217ee950c156d761a086bfd0d1d392d224cf4Mindy Pereira return; 648bb5217ee950c156d761a086bfd0d1d392d224cf4Mindy Pereira } 64923e9fdec6872f9b4d0fbe675745cb25becf7878cMindy Pereira if (!account.equals(mAccount)) { 65023e9fdec6872f9b4d0fbe675745cb25becf7878cMindy Pereira mAccount = account; 651b1f573c59ec20f9149443e1e0cc8b64ff3a07feaPaul Westbrook mCachedSettings = mAccount.settings; 652b1f573c59ec20f9149443e1e0cc8b64ff3a07feaPaul Westbrook appendSignature(); 65323e9fdec6872f9b4d0fbe675745cb25becf7878cMindy Pereira } 654fa20c1a4e36e0da2577baddbbb38a988b2017339Mindy Pereira if (mAccount != null) { 655fa20c1a4e36e0da2577baddbbb38a988b2017339Mindy Pereira MailActivity.setForegroundNdef(MailActivity.getMailtoNdef(mAccount.name)); 656fa20c1a4e36e0da2577baddbbb38a988b2017339Mindy Pereira } 657818143e2163648acc0c91f123b84777d65cd70cfMindy Pereira } 658818143e2163648acc0c91f123b84777d65cd70cfMindy Pereira 659e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira private void initFromSpinner(Bundle bundle, int action) { 6609a42bb4f11c502dd5c2cf92249ac214a6c2f1a70Mindy Pereira String accountString = null; 661e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira if (action == EDIT_DRAFT && mDraft.draftType == UIProvider.DraftType.COMPOSE) { 66262de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira action = COMPOSE; 66362de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira } 66462de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira mFromSpinner.asyncInitFromSpinner(action, mAccount); 6659a42bb4f11c502dd5c2cf92249ac214a6c2f1a70Mindy Pereira if (bundle != null) { 6669a42bb4f11c502dd5c2cf92249ac214a6c2f1a70Mindy Pereira if (bundle.containsKey(EXTRA_SELECTED_REPLY_FROM_ACCOUNT)) { 6679a42bb4f11c502dd5c2cf92249ac214a6c2f1a70Mindy Pereira mReplyFromAccount = ReplyFromAccount.deserialize(mAccount, 6689a42bb4f11c502dd5c2cf92249ac214a6c2f1a70Mindy Pereira bundle.getString(EXTRA_SELECTED_REPLY_FROM_ACCOUNT)); 6699a42bb4f11c502dd5c2cf92249ac214a6c2f1a70Mindy Pereira } else if (bundle.containsKey(EXTRA_FROM_ACCOUNT_STRING)) { 6709a42bb4f11c502dd5c2cf92249ac214a6c2f1a70Mindy Pereira accountString = bundle.getString(EXTRA_FROM_ACCOUNT_STRING); 6719a42bb4f11c502dd5c2cf92249ac214a6c2f1a70Mindy Pereira mReplyFromAccount = mFromSpinner.getMatchingReplyFromAccount(accountString); 6729a42bb4f11c502dd5c2cf92249ac214a6c2f1a70Mindy Pereira } 673e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira } 674e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira if (mReplyFromAccount == null) { 675e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira if (mDraft != null) { 676e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira mReplyFromAccount = getReplyFromAccountFromDraft(mAccount, mDraft); 677e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira } else if (mRefMessage != null) { 678e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira mReplyFromAccount = getReplyFromAccountForReply(mAccount, mRefMessage); 679e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira } 68062de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira } 68162de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira if (mReplyFromAccount == null) { 68262de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira mReplyFromAccount = new ReplyFromAccount(mAccount, mAccount.uri, mAccount.name, 683cd970ddaba4e212b668588db2104dc46ad3ad793Mindy Pereira mAccount.name, mAccount.name, true, false); 68462de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira } 6859a42bb4f11c502dd5c2cf92249ac214a6c2f1a70Mindy Pereira 68662de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira mFromSpinner.setCurrentAccount(mReplyFromAccount); 6879a42bb4f11c502dd5c2cf92249ac214a6c2f1a70Mindy Pereira 68862de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira if (mFromSpinner.getCount() > 1) { 689a83e708e162ad1f4b04b41738882bf318e217f64Mindy Pereira // If there is only 1 account, just show that account. 690a83e708e162ad1f4b04b41738882bf318e217f64Mindy Pereira // Otherwise, give the user the ability to choose which account to 69162de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira // send mail from / save drafts to. 69262de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira mFromStatic.setVisibility(View.GONE); 693a83e708e162ad1f4b04b41738882bf318e217f64Mindy Pereira mFromStaticText.setText(mAccount.name); 69462de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira mFromSpinnerWrapper.setVisibility(View.VISIBLE); 695a83e708e162ad1f4b04b41738882bf318e217f64Mindy Pereira } else { 696a83e708e162ad1f4b04b41738882bf318e217f64Mindy Pereira mFromStatic.setVisibility(View.VISIBLE); 697a83e708e162ad1f4b04b41738882bf318e217f64Mindy Pereira mFromStaticText.setText(mAccount.name); 698a83e708e162ad1f4b04b41738882bf318e217f64Mindy Pereira mFromSpinnerWrapper.setVisibility(View.GONE); 699a83e708e162ad1f4b04b41738882bf318e217f64Mindy Pereira } 70046ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira } 70146ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira 70262de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira private ReplyFromAccount getReplyFromAccountForReply(Account account, Message refMessage) { 70362de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira if (refMessage.accountUri != null) { 70462de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira // This must be from combined inbox. 70562de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira List<ReplyFromAccount> replyFromAccounts = mFromSpinner.getReplyFromAccounts(); 70662de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira for (ReplyFromAccount from : replyFromAccounts) { 70762de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira if (from.account.uri.equals(refMessage.accountUri)) { 70862de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira return from; 70962de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira } 71062de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira } 71162de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira return null; 71262de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira } else { 71362de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira return getReplyFromAccount(account, refMessage); 71462de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira } 71562de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira } 71662de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira 71762de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira /** 71862de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira * Given an account and which email address the message was sent to, 71962de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira * return who the message should be sent from. 72062de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira * @param account Account in which the message arrived. 72162de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira * @param sentTo Email address to which the message was sent. 72262de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira * @return the address from which to reply. 72362de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira */ 72462de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira public ReplyFromAccount getReplyFromAccount(Account account, Message refMessage) { 72562de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira // First see if we are supposed to use the default address or 72662de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira // the address it was sentTo. 727326689d531da1d2579fa7daaf6e307e24a05f993Mindy Pereira if (mCachedSettings.forceReplyFromDefault) { 72862de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira return getDefaultReplyFromAccount(account); 72962de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira } else { 73089bae5713b830ec1182073de22c3091d3613ac3eMindy Pereira // If we aren't explicitly told which account to look for, look at 73162de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira // all the message recipients and find one that matches 73262de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira // a custom from or account. 73362de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira List<String> allRecipients = new ArrayList<String>(); 73462de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira allRecipients.addAll(Arrays.asList(Utils.splitCommaSeparatedString(refMessage.to))); 73562de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira allRecipients.addAll(Arrays.asList(Utils.splitCommaSeparatedString(refMessage.cc))); 73662de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira return getMatchingRecipient(account, allRecipients); 73762de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira } 73862de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira } 73962de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira 74062de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira /** 74162de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira * Compare all the recipients of an email to the current account and all 74262de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira * custom addresses associated with that account. Return the match if there 74362de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira * is one, or the default account if there isn't. 74462de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira */ 74562de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira protected ReplyFromAccount getMatchingRecipient(Account account, List<String> sentTo) { 74662de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira // Tokenize the list and place in a hashmap. 74762de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira ReplyFromAccount matchingReplyFrom = null; 74862de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira Rfc822Token[] tokens; 74962de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira HashSet<String> recipientsMap = new HashSet<String>(); 75062de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira for (String address : sentTo) { 75162de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira tokens = Rfc822Tokenizer.tokenize(address); 75262de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira for (int i = 0; i < tokens.length; i++) { 75362de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira recipientsMap.add(tokens[i].getAddress()); 75462de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira } 75562de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira } 75662de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira 75762de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira int matchingAddressCount = 0; 75862de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira List<ReplyFromAccount> customFroms; 75962de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira try { 76062de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira customFroms = FromAddressSpinner.getAccountSpecificFroms(account); 76162de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira if (customFroms != null) { 76262de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira for (ReplyFromAccount entry : customFroms) { 76362de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira if (recipientsMap.contains(entry.address)) { 76462de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira matchingReplyFrom = entry; 76562de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira matchingAddressCount++; 76662de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira } 76762de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira } 76862de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira } 76962de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira } catch (JSONException e) { 77062de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira LogUtils.wtf(LOG_TAG, "Exception parsing from addresses for account %s", 77162de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira account.name); 77262de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira } 77362de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira if (matchingAddressCount > 1) { 77462de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira matchingReplyFrom = getDefaultReplyFromAccount(account); 77562de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira } 77662de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira return matchingReplyFrom; 77762de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira } 77862de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira 77962de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira private ReplyFromAccount getDefaultReplyFromAccount(Account account) { 78062de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira List<ReplyFromAccount> replyFromAccounts = mFromSpinner.getReplyFromAccounts(); 78162de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira for (ReplyFromAccount from : replyFromAccounts) { 78262de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira if (from.isDefault) { 78362de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira return from; 78462de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira } 78562de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira } 786cd970ddaba4e212b668588db2104dc46ad3ad793Mindy Pereira return new ReplyFromAccount(account, account.uri, account.name, account.name, account.name, 787cd970ddaba4e212b668588db2104dc46ad3ad793Mindy Pereira true, false); 78862de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira } 78962de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira 790e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira private ReplyFromAccount getReplyFromAccountFromDraft(Account account, Message msg) { 791e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira String sender = msg.from; 79262de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira ReplyFromAccount replyFromAccount = null; 79362de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira List<ReplyFromAccount> replyFromAccounts = mFromSpinner.getReplyFromAccounts(); 79462de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira if (TextUtils.equals(account.name, sender)) { 79562de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira replyFromAccount = new ReplyFromAccount(mAccount, mAccount.uri, mAccount.name, 796cd970ddaba4e212b668588db2104dc46ad3ad793Mindy Pereira mAccount.name, mAccount.name, true, false); 79762de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira } else { 79862de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira for (ReplyFromAccount fromAccount : replyFromAccounts) { 79962de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira if (TextUtils.equals(fromAccount.name, sender)) { 80062de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira replyFromAccount = fromAccount; 80162de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira break; 80262de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira } 80362de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira } 80462de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira } 80562de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira return replyFromAccount; 80662de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira } 80762de1b104635b09e7f00b0941268ba1fa5460ddbMindy Pereira 80846ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira private void findViews() { 809a26b54e3a858de409be3746e65591bb8a0d6ea9aMindy Pereira mCcBccButton = (Button) findViewById(R.id.add_cc_bcc); 8108e9305ec0bbe23cec01eb34a2aee76c55199a10aMindy Pereira if (mCcBccButton != null) { 8118e9305ec0bbe23cec01eb34a2aee76c55199a10aMindy Pereira mCcBccButton.setOnClickListener(this); 8128e9305ec0bbe23cec01eb34a2aee76c55199a10aMindy Pereira } 8138e9305ec0bbe23cec01eb34a2aee76c55199a10aMindy Pereira mCcBccView = (CcBccView) findViewById(R.id.cc_bcc_wrapper); 8147b56a61174eeb202eea468b7f68b79729737ded2Mindy Pereira mAttachmentsView = (AttachmentsView)findViewById(R.id.attachments); 815ca87d6d907e6d00670c8af607cf82cf7a73f7b39Andrew Sapperstein LayoutTransition transition = 816ca87d6d907e6d00670c8af607cf82cf7a73f7b39Andrew Sapperstein ((ViewGroup) findViewById(R.id.content)).getLayoutTransition(); 817ca87d6d907e6d00670c8af607cf82cf7a73f7b39Andrew Sapperstein mAttachmentsView.setComposeLayoutTransition(transition); 8181f93668e1186d48b507207841c1ca0529c3de292Mindy Pereira mAttachmentsButton = (ImageView) findViewById(R.id.add_attachment); 8191f93668e1186d48b507207841c1ca0529c3de292Mindy Pereira if (mAttachmentsButton != null) { 8201f93668e1186d48b507207841c1ca0529c3de292Mindy Pereira mAttachmentsButton.setOnClickListener(this); 8211f93668e1186d48b507207841c1ca0529c3de292Mindy Pereira } 822818143e2163648acc0c91f123b84777d65cd70cfMindy Pereira mTo = (RecipientEditTextView) findViewById(R.id.to); 823818143e2163648acc0c91f123b84777d65cd70cfMindy Pereira mCc = (RecipientEditTextView) findViewById(R.id.cc); 824818143e2163648acc0c91f123b84777d65cd70cfMindy Pereira mBcc = (RecipientEditTextView) findViewById(R.id.bcc); 82582cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira // TODO: add special chips text change watchers before adding 82682cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira // this as a text changed watcher to the to, cc, bcc fields. 8276349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira mSubject = (TextView) findViewById(R.id.subject); 82846ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira mQuotedTextView = (QuotedTextView) findViewById(R.id.quoted_text_view); 82946ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira mQuotedTextView.setRespondInlineListener(this); 830433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira mBodyView = (EditText) findViewById(R.id.body); 8311a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira mFromStatic = findViewById(R.id.static_from_content); 8322eb173211741adf7454bbf1990ba1b9d1e1f6a64Mindy Pereira mFromStaticText = (TextView) findViewById(R.id.from_account_name); 833eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira mFromSpinnerWrapper = findViewById(R.id.spinner_from_content); 8345a85e2b7485a5c407c581219fe1b44417f050529Mindy Pereira mFromSpinner = (FromAddressSpinner) findViewById(R.id.from_picker); 835326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } 836326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira 837e011b1d1c8e2e674dfdf1985d9d13da8cc06d803Mindy Pereira protected TextView getBody() { 838e011b1d1c8e2e674dfdf1985d9d13da8cc06d803Mindy Pereira return mBodyView; 839e011b1d1c8e2e674dfdf1985d9d13da8cc06d803Mindy Pereira } 840e011b1d1c8e2e674dfdf1985d9d13da8cc06d803Mindy Pereira 841e011b1d1c8e2e674dfdf1985d9d13da8cc06d803Mindy Pereira @VisibleForTesting 842e011b1d1c8e2e674dfdf1985d9d13da8cc06d803Mindy Pereira public Account getFromAccount() { 843e011b1d1c8e2e674dfdf1985d9d13da8cc06d803Mindy Pereira return mReplyFromAccount != null && mReplyFromAccount.account != null ? 844e011b1d1c8e2e674dfdf1985d9d13da8cc06d803Mindy Pereira mReplyFromAccount.account : mAccount; 845e011b1d1c8e2e674dfdf1985d9d13da8cc06d803Mindy Pereira } 846e011b1d1c8e2e674dfdf1985d9d13da8cc06d803Mindy Pereira 847cbfb75a0f92a3ef5cf10ab94b451e4898cc78bfcMindy Pereira private void clearChangeListeners() { 848cbfb75a0f92a3ef5cf10ab94b451e4898cc78bfcMindy Pereira mSubject.removeTextChangedListener(this); 849cbfb75a0f92a3ef5cf10ab94b451e4898cc78bfcMindy Pereira mBodyView.removeTextChangedListener(this); 850cbfb75a0f92a3ef5cf10ab94b451e4898cc78bfcMindy Pereira mTo.removeTextChangedListener(mToListener); 851cbfb75a0f92a3ef5cf10ab94b451e4898cc78bfcMindy Pereira mCc.removeTextChangedListener(mCcListener); 852cbfb75a0f92a3ef5cf10ab94b451e4898cc78bfcMindy Pereira mBcc.removeTextChangedListener(mBccListener); 853cbfb75a0f92a3ef5cf10ab94b451e4898cc78bfcMindy Pereira mFromSpinner.setOnAccountChangedListener(null); 854cbfb75a0f92a3ef5cf10ab94b451e4898cc78bfcMindy Pereira mAttachmentsView.setAttachmentChangesListener(null); 855cbfb75a0f92a3ef5cf10ab94b451e4898cc78bfcMindy Pereira } 856cbfb75a0f92a3ef5cf10ab94b451e4898cc78bfcMindy Pereira 85775f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira // Now that the message has been initialized from any existing draft or 85875f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira // ref message data, set up listeners for any changes that occur to the 85975f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira // message. 86075f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira private void initChangeListeners() { 86175f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira mSubject.addTextChangedListener(this); 86275f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira mBodyView.addTextChangedListener(this); 863cbfb75a0f92a3ef5cf10ab94b451e4898cc78bfcMindy Pereira if (mToListener == null) { 864cbfb75a0f92a3ef5cf10ab94b451e4898cc78bfcMindy Pereira mToListener = new RecipientTextWatcher(mTo, this); 865cbfb75a0f92a3ef5cf10ab94b451e4898cc78bfcMindy Pereira } 866cbfb75a0f92a3ef5cf10ab94b451e4898cc78bfcMindy Pereira mTo.addTextChangedListener(mToListener); 867cbfb75a0f92a3ef5cf10ab94b451e4898cc78bfcMindy Pereira if (mCcListener == null) { 868cbfb75a0f92a3ef5cf10ab94b451e4898cc78bfcMindy Pereira mCcListener = new RecipientTextWatcher(mCc, this); 869cbfb75a0f92a3ef5cf10ab94b451e4898cc78bfcMindy Pereira } 870cbfb75a0f92a3ef5cf10ab94b451e4898cc78bfcMindy Pereira mCc.addTextChangedListener(mCcListener); 871cbfb75a0f92a3ef5cf10ab94b451e4898cc78bfcMindy Pereira if (mBccListener == null) { 872cbfb75a0f92a3ef5cf10ab94b451e4898cc78bfcMindy Pereira mBccListener = new RecipientTextWatcher(mBcc, this); 873cbfb75a0f92a3ef5cf10ab94b451e4898cc78bfcMindy Pereira } 874cbfb75a0f92a3ef5cf10ab94b451e4898cc78bfcMindy Pereira mBcc.addTextChangedListener(mBccListener); 87575f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira mFromSpinner.setOnAccountChangedListener(this); 876818143e2163648acc0c91f123b84777d65cd70cfMindy Pereira mAttachmentsView.setAttachmentChangesListener(this); 87775f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira } 87875f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira 879326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira private void initActionBar(int action) { 880326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira mComposeMode = action; 881eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira ActionBar actionBar = getActionBar(); 882e011b1d1c8e2e674dfdf1985d9d13da8cc06d803Mindy Pereira if (actionBar == null) { 883e011b1d1c8e2e674dfdf1985d9d13da8cc06d803Mindy Pereira return; 884e011b1d1c8e2e674dfdf1985d9d13da8cc06d803Mindy Pereira } 885326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira if (action == ComposeActivity.COMPOSE) { 886eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_STANDARD); 887eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira actionBar.setTitle(R.string.compose); 888326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } else { 889eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira actionBar.setTitle(null); 890326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira if (mComposeModeAdapter == null) { 891326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira mComposeModeAdapter = new ComposeModeAdapter(this); 892326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } 893eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_LIST); 894eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira actionBar.setListNavigationCallbacks(mComposeModeAdapter, this); 895326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira switch (action) { 896326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira case ComposeActivity.REPLY: 897eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira actionBar.setSelectedNavigationItem(0); 898326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira break; 899326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira case ComposeActivity.REPLY_ALL: 900eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira actionBar.setSelectedNavigationItem(1); 901326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira break; 902326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira case ComposeActivity.FORWARD: 903eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira actionBar.setSelectedNavigationItem(2); 904326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira break; 905326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } 9066349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira } 907fbe4019a262f6b1934a44e598009ae63dc5745eeMindy Pereira actionBar.setDisplayOptions(ActionBar.DISPLAY_HOME_AS_UP | ActionBar.DISPLAY_SHOW_HOME, 908fbe4019a262f6b1934a44e598009ae63dc5745eeMindy Pereira ActionBar.DISPLAY_HOME_AS_UP | ActionBar.DISPLAY_SHOW_HOME); 909fbe4019a262f6b1934a44e598009ae63dc5745eeMindy Pereira actionBar.setHomeButtonEnabled(true); 9106349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira } 9116349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira 91246ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira private void initFromRefMessage(int action, String recipientAddress) { 91396a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira setFieldsFromRefMessage(action, recipientAddress); 91496a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira if (mRefMessage != null) { 91596a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira // CC field only gets populated when doing REPLY_ALL. 91696a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira // BCC never gets auto-populated, unless the user is editing 91796a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira // a draft with one. 91829a717e1047a2b50574e358c94a8ee8a41f377e9Mindy Pereira if (!TextUtils.isEmpty(mCc.getText()) && action == REPLY_ALL) { 91996a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira mCcBccView.show(false, true, false); 92096a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira } 92196a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira } 92296a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira updateHideOrShowCcBcc(); 92396a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira } 92496a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira 92596a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira private void setFieldsFromRefMessage(int action, String recipientAddress) { 9268eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira setSubject(mRefMessage, action); 9278eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira // Setup recipients 9288eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira if (action == FORWARD) { 9298eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira mForward = true; 9308eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira } 9318eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira initRecipientsFromRefMessage(recipientAddress, mRefMessage, action); 932e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira initQuotedTextFromRefMessage(mRefMessage, action); 9338eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira if (action == ComposeActivity.FORWARD || mAttachmentsChanged) { 9348eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira initAttachments(mRefMessage); 9356349a043bce28ec999d72635222ae0eb576eb9cdMindy Pereira } 936c17d073dd43871df36ea70b3dea55963bdb98384Mindy Pereira } 937c17d073dd43871df36ea70b3dea55963bdb98384Mindy Pereira 938e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira private void initFromDraftMessage(Message message) { 939bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook LogUtils.d(LOG_TAG, "Intializing draft from previous draft message"); 940bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook 941bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook mDraft = message; 942bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook mDraftId = message.id; 943bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook mSubject.setText(message.subject); 944bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook mForward = message.draftType == UIProvider.DraftType.FORWARD; 945bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook final List<String> toAddresses = Arrays.asList(message.getToAddresses()); 946bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook addToAddresses(toAddresses); 947bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook addCcAddresses(Arrays.asList(message.getCcAddresses()), toAddresses); 948bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook addBccAddresses(Arrays.asList(message.getBccAddresses())); 9492421dc8d6d0b4c727ab7ab0e5ce730f415089e86Mindy Pereira if (message.hasAttachments) { 9502421dc8d6d0b4c727ab7ab0e5ce730f415089e86Mindy Pereira List<Attachment> attachments = message.getAttachments(); 9512421dc8d6d0b4c727ab7ab0e5ce730f415089e86Mindy Pereira for (Attachment a : attachments) { 9525c5fd571b40a15b95ea5a5d6033f377706ffd0fbAndy Huang addAttachmentAndUpdateView(a); 9532421dc8d6d0b4c727ab7ab0e5ce730f415089e86Mindy Pereira } 9542421dc8d6d0b4c727ab7ab0e5ce730f415089e86Mindy Pereira } 955cc8e7db940b2ad6c673e84ca7addae9295c10a33Mindy Pereira int quotedTextIndex = message.appendRefMessageContent ? 956002ff5244800c32f2d70c96cc1110657020ee65cMindy Pereira message.quotedTextOffset : -1; 957bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook // Set the body 958002ff5244800c32f2d70c96cc1110657020ee65cMindy Pereira CharSequence quotedText = null; 959bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook if (!TextUtils.isEmpty(message.bodyHtml)) { 960752222d839d9afeb5c4665669eab81645e413495Mindy Pereira CharSequence htmlText = ""; 961002ff5244800c32f2d70c96cc1110657020ee65cMindy Pereira if (quotedTextIndex > -1) { 962752222d839d9afeb5c4665669eab81645e413495Mindy Pereira // Find the offset in the htmltext of the actual quoted text and strip it out. 963752222d839d9afeb5c4665669eab81645e413495Mindy Pereira quotedTextIndex = QuotedTextView.findQuotedTextIndex(message.bodyHtml); 964752222d839d9afeb5c4665669eab81645e413495Mindy Pereira if (quotedTextIndex > -1) { 965752222d839d9afeb5c4665669eab81645e413495Mindy Pereira htmlText = Html.fromHtml(message.bodyHtml.substring(0, quotedTextIndex)); 966752222d839d9afeb5c4665669eab81645e413495Mindy Pereira quotedText = message.bodyHtml.subSequence(quotedTextIndex, 967752222d839d9afeb5c4665669eab81645e413495Mindy Pereira message.bodyHtml.length()); 968752222d839d9afeb5c4665669eab81645e413495Mindy Pereira } 969002ff5244800c32f2d70c96cc1110657020ee65cMindy Pereira } 970002ff5244800c32f2d70c96cc1110657020ee65cMindy Pereira mBodyView.setText(htmlText); 971bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook } else { 972752222d839d9afeb5c4665669eab81645e413495Mindy Pereira final String body = message.bodyText; 973752222d839d9afeb5c4665669eab81645e413495Mindy Pereira final CharSequence bodyText = !TextUtils.isEmpty(body) ? 974752222d839d9afeb5c4665669eab81645e413495Mindy Pereira (quotedTextIndex > -1 ? 975752222d839d9afeb5c4665669eab81645e413495Mindy Pereira message.bodyText.substring(0, quotedTextIndex) : message.bodyText) 976752222d839d9afeb5c4665669eab81645e413495Mindy Pereira : ""; 977002ff5244800c32f2d70c96cc1110657020ee65cMindy Pereira if (quotedTextIndex > -1) { 978752222d839d9afeb5c4665669eab81645e413495Mindy Pereira quotedText = !TextUtils.isEmpty(body) ? message.bodyText.substring(quotedTextIndex) 979752222d839d9afeb5c4665669eab81645e413495Mindy Pereira : null; 980002ff5244800c32f2d70c96cc1110657020ee65cMindy Pereira } 981002ff5244800c32f2d70c96cc1110657020ee65cMindy Pereira mBodyView.setText(bodyText); 982002ff5244800c32f2d70c96cc1110657020ee65cMindy Pereira } 983002ff5244800c32f2d70c96cc1110657020ee65cMindy Pereira if (quotedTextIndex > -1 && quotedText != null) { 9843971323f24b15b541f7460c1a4db42d78eb1873bMindy Pereira mQuotedTextView.setQuotedTextFromDraft(quotedText, mForward); 985bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook } 986bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook } 987bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook 9888eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira /** 9898eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira * Fill all the widgets with the content found in the Intent Extra, if any. 9908eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira * Also apply the same style to all widgets. Note: if initFromExtras is 9918eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira * called as a result of switching between reply, reply all, and forward per 9928eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira * the latest revision of Gmail, and the user has already made changes to 9938eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira * attachments on a previous incarnation of the message (as a reply, reply 9948eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira * all, or forward), the original attachments from the message will not be 9958eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira * re-instantiated. The user's changes will be respected. This follows the 9968eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira * web gmail interaction. 9978eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira */ 9988eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira public void initFromExtras(Intent intent) { 9998eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira // If we were invoked with a SENDTO intent, the value 10008eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira // should take precedence 10018eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira final Uri dataUri = intent.getData(); 10028eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira if (dataUri != null) { 10038eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira if (MAIL_TO.equals(dataUri.getScheme())) { 10048eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira initFromMailTo(dataUri.toString()); 10058eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira } else { 10060b4f28ed53a7f1617dadf3b34de8c743a1733ce5Mindy Pereira if (!mAccount.composeIntentUri.equals(dataUri)) { 10078eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira String toText = dataUri.getSchemeSpecificPart(); 10088eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira if (toText != null) { 10098eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira mTo.setText(""); 1010dbe8996d8ba382bfe1a23894abbc4711e36c9daeMindy Pereira addToAddresses(Arrays.asList(TextUtils.split(toText, ","))); 10118eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira } 10128eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira } 10138eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira } 10148eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira } 10158eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira 10168eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira String[] extraStrings = intent.getStringArrayExtra(Intent.EXTRA_EMAIL); 10178eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira if (extraStrings != null) { 10188eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira addToAddresses(Arrays.asList(extraStrings)); 10198eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira } 10208eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira extraStrings = intent.getStringArrayExtra(Intent.EXTRA_CC); 10218eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira if (extraStrings != null) { 10228eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira addCcAddresses(Arrays.asList(extraStrings), null); 10238eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira } 10248eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira extraStrings = intent.getStringArrayExtra(Intent.EXTRA_BCC); 10258eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira if (extraStrings != null) { 10268eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira addBccAddresses(Arrays.asList(extraStrings)); 10278eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira } 10288eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira 10298eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira String extraString = intent.getStringExtra(Intent.EXTRA_SUBJECT); 10308eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira if (extraString != null) { 10318eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira mSubject.setText(extraString); 10328eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira } 10338eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira 10348eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira for (String extra : ALL_EXTRAS) { 10358eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira if (intent.hasExtra(extra)) { 10368eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira String value = intent.getStringExtra(extra); 10378eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira if (EXTRA_TO.equals(extra)) { 1038dbe8996d8ba382bfe1a23894abbc4711e36c9daeMindy Pereira addToAddresses(Arrays.asList(TextUtils.split(value, ","))); 10398eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira } else if (EXTRA_CC.equals(extra)) { 1040dbe8996d8ba382bfe1a23894abbc4711e36c9daeMindy Pereira addCcAddresses(Arrays.asList(TextUtils.split(value, ",")), null); 10418eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira } else if (EXTRA_BCC.equals(extra)) { 1042dbe8996d8ba382bfe1a23894abbc4711e36c9daeMindy Pereira addBccAddresses(Arrays.asList(TextUtils.split(value, ","))); 10438eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira } else if (EXTRA_SUBJECT.equals(extra)) { 10448eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira mSubject.setText(value); 10458eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira } else if (EXTRA_BODY.equals(extra)) { 10468eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira setBody(value, true /* with signature */); 10478eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira } 10488eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira } 10498eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira } 10508eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira 10518eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira Bundle extras = intent.getExtras(); 10528eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira if (extras != null) { 10538eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira CharSequence text = extras.getCharSequence(Intent.EXTRA_TEXT); 10548eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira if (text != null) { 10558eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira setBody(text, true /* with signature */); 10568eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira } 10578eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira } 1058e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira } 1059e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira 10608eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira @VisibleForTesting 10618eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira protected String decodeEmailInUri(String s) throws UnsupportedEncodingException { 1062a4069f2f16c05c6d2948baa39b0c463be4c7a360Mindy Pereira // TODO: handle the case where there are spaces in the display name as 1063a4069f2f16c05c6d2948baa39b0c463be4c7a360Mindy Pereira // well as the email such as "Guy with spaces <guy+with+spaces@gmail.com>" 1064a4069f2f16c05c6d2948baa39b0c463be4c7a360Mindy Pereira // as they could be encoded ambiguously. 10658eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira // Since URLDecode.decode changes + into ' ', and + is a valid 10668eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira // email character, we need to find/ replace these ourselves before 10678eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira // decoding. 10688eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira String replacePlus = s.replace("+", "%2B"); 1069a4069f2f16c05c6d2948baa39b0c463be4c7a360Mindy Pereira try { 1070a4069f2f16c05c6d2948baa39b0c463be4c7a360Mindy Pereira return URLDecoder.decode(replacePlus, UTF8_ENCODING_NAME); 1071a4069f2f16c05c6d2948baa39b0c463be4c7a360Mindy Pereira } catch (IllegalArgumentException e) { 1072a4069f2f16c05c6d2948baa39b0c463be4c7a360Mindy Pereira if (LogUtils.isLoggable(LOG_TAG, LogUtils.VERBOSE)) { 1073a4069f2f16c05c6d2948baa39b0c463be4c7a360Mindy Pereira LogUtils.e(LOG_TAG, "%s while decoding '%s'", e.getMessage(), s); 1074a4069f2f16c05c6d2948baa39b0c463be4c7a360Mindy Pereira } else { 1075a4069f2f16c05c6d2948baa39b0c463be4c7a360Mindy Pereira LogUtils.e(LOG_TAG, e, "Exception while decoding mailto address"); 1076a4069f2f16c05c6d2948baa39b0c463be4c7a360Mindy Pereira } 1077a4069f2f16c05c6d2948baa39b0c463be4c7a360Mindy Pereira return null; 1078a4069f2f16c05c6d2948baa39b0c463be4c7a360Mindy Pereira } 10798eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira } 10808eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira 10818eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira /** 10828eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira * Initialize the compose view from a String representing a mailTo uri. 10838eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira * @param mailToString The uri as a string. 10848eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira */ 10858eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira public void initFromMailTo(String mailToString) { 10868eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira // We need to disguise this string as a URI in order to parse it 10878eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira // TODO: Remove this hack when http://b/issue?id=1445295 gets fixed 10888eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira Uri uri = Uri.parse("foo://" + mailToString); 10898eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira int index = mailToString.indexOf("?"); 10908eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira int length = "mailto".length() + 1; 10918eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira String to; 10928eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira try { 10938eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira // Extract the recipient after mailto: 10948eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira if (index == -1) { 10958eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira to = decodeEmailInUri(mailToString.substring(length)); 10968eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira } else { 10978eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira to = decodeEmailInUri(mailToString.substring(length, index)); 10988eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira } 1099a4069f2f16c05c6d2948baa39b0c463be4c7a360Mindy Pereira if (!TextUtils.isEmpty(to)) { 1100a4069f2f16c05c6d2948baa39b0c463be4c7a360Mindy Pereira addToAddresses(Arrays.asList(TextUtils.split(to, ","))); 1101a4069f2f16c05c6d2948baa39b0c463be4c7a360Mindy Pereira } 11028eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira } catch (UnsupportedEncodingException e) { 11038eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira if (LogUtils.isLoggable(LOG_TAG, LogUtils.VERBOSE)) { 11048eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira LogUtils.e(LOG_TAG, "%s while decoding '%s'", e.getMessage(), mailToString); 11058eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira } else { 11068eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira LogUtils.e(LOG_TAG, e, "Exception while decoding mailto address"); 11078eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira } 11088eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira } 11098eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira 11108eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira List<String> cc = uri.getQueryParameters("cc"); 11118eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira addCcAddresses(Arrays.asList(cc.toArray(new String[cc.size()])), null); 11128eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira 11138eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira List<String> otherTo = uri.getQueryParameters("to"); 11148eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira addToAddresses(Arrays.asList(otherTo.toArray(new String[otherTo.size()]))); 11158eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira 11168eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira List<String> bcc = uri.getQueryParameters("bcc"); 11178eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira addBccAddresses(Arrays.asList(bcc.toArray(new String[bcc.size()]))); 11188eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira 11198eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira List<String> subject = uri.getQueryParameters("subject"); 11208eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira if (subject.size() > 0) { 11218eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira try { 11228eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira mSubject.setText(URLDecoder.decode(subject.get(0), UTF8_ENCODING_NAME)); 11238eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira } catch (UnsupportedEncodingException e) { 11248eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira LogUtils.e(LOG_TAG, "%s while decoding subject '%s'", 11258eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira e.getMessage(), subject); 11268eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira } 11278eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira } 11288eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira 11298eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira List<String> body = uri.getQueryParameters("body"); 11308eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira if (body.size() > 0) { 11318eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira try { 11328eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira setBody(URLDecoder.decode(body.get(0), UTF8_ENCODING_NAME), 11338eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira true /* with signature */); 11348eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira } catch (UnsupportedEncodingException e) { 11358eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira LogUtils.e(LOG_TAG, "%s while decoding body '%s'", e.getMessage(), body); 11368eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira } 11378eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira } 11388eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira } 11398eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira 1140bddd6f39f34aa15fed2e757f7d3e4163272ca02cMindy Pereira @VisibleForTesting 1141bddd6f39f34aa15fed2e757f7d3e4163272ca02cMindy Pereira protected void initAttachments(Message refMessage) { 11423cd4f40dab2c0810cb5ecd77256abf022863b2b5Mindy Pereira try { 11433cd4f40dab2c0810cb5ecd77256abf022863b2b5Mindy Pereira mAttachmentsView.addAttachments(mAccount, refMessage); 11443cd4f40dab2c0810cb5ecd77256abf022863b2b5Mindy Pereira } catch (AttachmentFailureException e) { 11453cd4f40dab2c0810cb5ecd77256abf022863b2b5Mindy Pereira LogUtils.e(LOG_TAG, e, "Error adding attachment"); 11463cd4f40dab2c0810cb5ecd77256abf022863b2b5Mindy Pereira showAttachmentTooBigToast(); 11473cd4f40dab2c0810cb5ecd77256abf022863b2b5Mindy Pereira } 11483cd4f40dab2c0810cb5ecd77256abf022863b2b5Mindy Pereira } 11493cd4f40dab2c0810cb5ecd77256abf022863b2b5Mindy Pereira 11503cd4f40dab2c0810cb5ecd77256abf022863b2b5Mindy Pereira /** 11513cd4f40dab2c0810cb5ecd77256abf022863b2b5Mindy Pereira * When an attachment is too large to be added to a message, show a toast. 11523cd4f40dab2c0810cb5ecd77256abf022863b2b5Mindy Pereira * This method also updates the position of the toast so that it is shown 11533cd4f40dab2c0810cb5ecd77256abf022863b2b5Mindy Pereira * clearly above they keyboard if it happens to be open. 11543cd4f40dab2c0810cb5ecd77256abf022863b2b5Mindy Pereira */ 11553cd4f40dab2c0810cb5ecd77256abf022863b2b5Mindy Pereira private void showAttachmentTooBigToast() { 11563cd4f40dab2c0810cb5ecd77256abf022863b2b5Mindy Pereira showErrorToast(R.string.too_large_to_attach); 11573cd4f40dab2c0810cb5ecd77256abf022863b2b5Mindy Pereira } 11583cd4f40dab2c0810cb5ecd77256abf022863b2b5Mindy Pereira 11593cd4f40dab2c0810cb5ecd77256abf022863b2b5Mindy Pereira private void showErrorToast(int resId) { 11603cd4f40dab2c0810cb5ecd77256abf022863b2b5Mindy Pereira Toast t = Toast.makeText(this, resId, Toast.LENGTH_LONG); 11613cd4f40dab2c0810cb5ecd77256abf022863b2b5Mindy Pereira t.setText(resId); 11623cd4f40dab2c0810cb5ecd77256abf022863b2b5Mindy Pereira t.setGravity(Gravity.CENTER_HORIZONTAL, 0, 11633cd4f40dab2c0810cb5ecd77256abf022863b2b5Mindy Pereira getResources().getDimensionPixelSize(R.dimen.attachment_toast_yoffset)); 11643cd4f40dab2c0810cb5ecd77256abf022863b2b5Mindy Pereira t.show(); 1165eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira } 1166eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira 1167f97588bd03fdcd318e24a9d74a283e73d1fbd37cPaul Westbrook private void initAttachmentsFromIntent(Intent intent) { 116803ee971afd8d766dea81b72fe77593e3be3ab798Paul Westbrook Bundle extras = intent.getExtras(); 116903ee971afd8d766dea81b72fe77593e3be3ab798Paul Westbrook if (extras == null) { 117003ee971afd8d766dea81b72fe77593e3be3ab798Paul Westbrook extras = Bundle.EMPTY; 117103ee971afd8d766dea81b72fe77593e3be3ab798Paul Westbrook } 1172f97588bd03fdcd318e24a9d74a283e73d1fbd37cPaul Westbrook final String action = intent.getAction(); 1173f97588bd03fdcd318e24a9d74a283e73d1fbd37cPaul Westbrook if (!mAttachmentsChanged) { 1174f97588bd03fdcd318e24a9d74a283e73d1fbd37cPaul Westbrook long totalSize = 0; 1175f97588bd03fdcd318e24a9d74a283e73d1fbd37cPaul Westbrook if (extras.containsKey(EXTRA_ATTACHMENTS)) { 1176f97588bd03fdcd318e24a9d74a283e73d1fbd37cPaul Westbrook String[] uris = (String[]) extras.getSerializable(EXTRA_ATTACHMENTS); 1177f97588bd03fdcd318e24a9d74a283e73d1fbd37cPaul Westbrook for (String uriString : uris) { 1178f97588bd03fdcd318e24a9d74a283e73d1fbd37cPaul Westbrook final Uri uri = Uri.parse(uriString); 1179f97588bd03fdcd318e24a9d74a283e73d1fbd37cPaul Westbrook long size = 0; 1180f97588bd03fdcd318e24a9d74a283e73d1fbd37cPaul Westbrook try { 11815c5fd571b40a15b95ea5a5d6033f377706ffd0fbAndy Huang size = mAttachmentsView.addAttachment(mAccount, uri); 1182f97588bd03fdcd318e24a9d74a283e73d1fbd37cPaul Westbrook } catch (AttachmentFailureException e) { 1183f97588bd03fdcd318e24a9d74a283e73d1fbd37cPaul Westbrook LogUtils.e(LOG_TAG, e, "Error adding attachment"); 11843cd4f40dab2c0810cb5ecd77256abf022863b2b5Mindy Pereira showAttachmentTooBigToast(); 1185f97588bd03fdcd318e24a9d74a283e73d1fbd37cPaul Westbrook } 1186f97588bd03fdcd318e24a9d74a283e73d1fbd37cPaul Westbrook totalSize += size; 1187f97588bd03fdcd318e24a9d74a283e73d1fbd37cPaul Westbrook } 1188f97588bd03fdcd318e24a9d74a283e73d1fbd37cPaul Westbrook } 1189f97588bd03fdcd318e24a9d74a283e73d1fbd37cPaul Westbrook if (Intent.ACTION_SEND.equals(action) && extras.containsKey(Intent.EXTRA_STREAM)) { 1190f97588bd03fdcd318e24a9d74a283e73d1fbd37cPaul Westbrook final Uri uri = (Uri) extras.getParcelable(Intent.EXTRA_STREAM); 1191f97588bd03fdcd318e24a9d74a283e73d1fbd37cPaul Westbrook long size = 0; 1192f97588bd03fdcd318e24a9d74a283e73d1fbd37cPaul Westbrook try { 11935c5fd571b40a15b95ea5a5d6033f377706ffd0fbAndy Huang size = mAttachmentsView.addAttachment(mAccount, uri); 1194f97588bd03fdcd318e24a9d74a283e73d1fbd37cPaul Westbrook } catch (AttachmentFailureException e) { 1195f97588bd03fdcd318e24a9d74a283e73d1fbd37cPaul Westbrook LogUtils.e(LOG_TAG, e, "Error adding attachment"); 11963cd4f40dab2c0810cb5ecd77256abf022863b2b5Mindy Pereira showAttachmentTooBigToast(); 1197f97588bd03fdcd318e24a9d74a283e73d1fbd37cPaul Westbrook } 1198f97588bd03fdcd318e24a9d74a283e73d1fbd37cPaul Westbrook totalSize += size; 1199f97588bd03fdcd318e24a9d74a283e73d1fbd37cPaul Westbrook } 1200f97588bd03fdcd318e24a9d74a283e73d1fbd37cPaul Westbrook 1201f97588bd03fdcd318e24a9d74a283e73d1fbd37cPaul Westbrook if (Intent.ACTION_SEND_MULTIPLE.equals(action) 1202f97588bd03fdcd318e24a9d74a283e73d1fbd37cPaul Westbrook && extras.containsKey(Intent.EXTRA_STREAM)) { 1203f97588bd03fdcd318e24a9d74a283e73d1fbd37cPaul Westbrook ArrayList<Parcelable> uris = extras.getParcelableArrayList(Intent.EXTRA_STREAM); 1204f97588bd03fdcd318e24a9d74a283e73d1fbd37cPaul Westbrook for (Parcelable uri : uris) { 1205f97588bd03fdcd318e24a9d74a283e73d1fbd37cPaul Westbrook long size = 0; 1206f97588bd03fdcd318e24a9d74a283e73d1fbd37cPaul Westbrook try { 12075c5fd571b40a15b95ea5a5d6033f377706ffd0fbAndy Huang size = mAttachmentsView.addAttachment(mAccount, (Uri) uri); 1208f97588bd03fdcd318e24a9d74a283e73d1fbd37cPaul Westbrook } catch (AttachmentFailureException e) { 1209f97588bd03fdcd318e24a9d74a283e73d1fbd37cPaul Westbrook LogUtils.e(LOG_TAG, e, "Error adding attachment"); 12103cd4f40dab2c0810cb5ecd77256abf022863b2b5Mindy Pereira showAttachmentTooBigToast(); 1211f97588bd03fdcd318e24a9d74a283e73d1fbd37cPaul Westbrook } 1212f97588bd03fdcd318e24a9d74a283e73d1fbd37cPaul Westbrook totalSize += size; 1213f97588bd03fdcd318e24a9d74a283e73d1fbd37cPaul Westbrook } 1214f97588bd03fdcd318e24a9d74a283e73d1fbd37cPaul Westbrook } 1215f97588bd03fdcd318e24a9d74a283e73d1fbd37cPaul Westbrook 1216f97588bd03fdcd318e24a9d74a283e73d1fbd37cPaul Westbrook if (totalSize > 0) { 1217f97588bd03fdcd318e24a9d74a283e73d1fbd37cPaul Westbrook mAttachmentsChanged = true; 1218f97588bd03fdcd318e24a9d74a283e73d1fbd37cPaul Westbrook updateSaveUi(); 1219f97588bd03fdcd318e24a9d74a283e73d1fbd37cPaul Westbrook } 1220f97588bd03fdcd318e24a9d74a283e73d1fbd37cPaul Westbrook } 1221f97588bd03fdcd318e24a9d74a283e73d1fbd37cPaul Westbrook } 1222f97588bd03fdcd318e24a9d74a283e73d1fbd37cPaul Westbrook 1223f97588bd03fdcd318e24a9d74a283e73d1fbd37cPaul Westbrook 1224e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira private void initQuotedTextFromRefMessage(Message refMessage, int action) { 1225e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira if (mRefMessage != null && (action == REPLY || action == REPLY_ALL || action == FORWARD)) { 12269932dee248718d2cec993d93b5115973d1389d0aMindy Pereira mQuotedTextView.setQuotedText(action, refMessage, action != FORWARD); 12279932dee248718d2cec993d93b5115973d1389d0aMindy Pereira } 122846ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira } 122946ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira 123046ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira private void updateHideOrShowCcBcc() { 1231ec8b0edb23c0e0b7f1a8ce9558a919be31169d45Mindy Pereira // Its possible there is a menu item OR a button. 1232326689d531da1d2579fa7daaf6e307e24a05f993Mindy Pereira boolean ccVisible = mCcBccView.isCcVisible(); 1233326689d531da1d2579fa7daaf6e307e24a05f993Mindy Pereira boolean bccVisible = mCcBccView.isBccVisible(); 1234ec8b0edb23c0e0b7f1a8ce9558a919be31169d45Mindy Pereira if (mCcBccButton != null) { 1235326689d531da1d2579fa7daaf6e307e24a05f993Mindy Pereira if (!ccVisible || !bccVisible) { 1236ec8b0edb23c0e0b7f1a8ce9558a919be31169d45Mindy Pereira mCcBccButton.setVisibility(View.VISIBLE); 1237326689d531da1d2579fa7daaf6e307e24a05f993Mindy Pereira mCcBccButton.setText(getString(!ccVisible ? R.string.add_cc_label 1238ec8b0edb23c0e0b7f1a8ce9558a919be31169d45Mindy Pereira : R.string.add_bcc_label)); 1239ec8b0edb23c0e0b7f1a8ce9558a919be31169d45Mindy Pereira } else { 1240ec8b0edb23c0e0b7f1a8ce9558a919be31169d45Mindy Pereira mCcBccButton.setVisibility(View.GONE); 1241ec8b0edb23c0e0b7f1a8ce9558a919be31169d45Mindy Pereira } 1242ec8b0edb23c0e0b7f1a8ce9558a919be31169d45Mindy Pereira } 124346ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira } 124446ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira 1245a34c9a054c9aef6f83abe56515c132a31d71b3c8Mindy Pereira private void showCcBcc(Bundle state) { 1246326689d531da1d2579fa7daaf6e307e24a05f993Mindy Pereira if (state != null && state.containsKey(EXTRA_SHOW_CC)) { 1247326689d531da1d2579fa7daaf6e307e24a05f993Mindy Pereira boolean showCc = state.getBoolean(EXTRA_SHOW_CC); 1248326689d531da1d2579fa7daaf6e307e24a05f993Mindy Pereira boolean showBcc = state.getBoolean(EXTRA_SHOW_BCC); 1249326689d531da1d2579fa7daaf6e307e24a05f993Mindy Pereira if (showCc || showBcc) { 1250326689d531da1d2579fa7daaf6e307e24a05f993Mindy Pereira mCcBccView.show(false, showCc, showBcc); 1251326689d531da1d2579fa7daaf6e307e24a05f993Mindy Pereira } 1252326689d531da1d2579fa7daaf6e307e24a05f993Mindy Pereira } 1253326689d531da1d2579fa7daaf6e307e24a05f993Mindy Pereira } 1254326689d531da1d2579fa7daaf6e307e24a05f993Mindy Pereira 1255013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira /** 1256013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira * Add attachment and update the compose area appropriately. 1257013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira * @param data 1258013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira */ 1259013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira public void addAttachmentAndUpdateView(Intent data) { 12602421dc8d6d0b4c727ab7ab0e5ce730f415089e86Mindy Pereira addAttachmentAndUpdateView(data != null ? data.getData() : (Uri) null); 12612421dc8d6d0b4c727ab7ab0e5ce730f415089e86Mindy Pereira } 12622421dc8d6d0b4c727ab7ab0e5ce730f415089e86Mindy Pereira 12635c5fd571b40a15b95ea5a5d6033f377706ffd0fbAndy Huang public void addAttachmentAndUpdateView(Uri contentUri) { 12645c5fd571b40a15b95ea5a5d6033f377706ffd0fbAndy Huang if (contentUri == null) { 12652421dc8d6d0b4c727ab7ab0e5ce730f415089e86Mindy Pereira return; 12662421dc8d6d0b4c727ab7ab0e5ce730f415089e86Mindy Pereira } 1267013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira try { 12685c5fd571b40a15b95ea5a5d6033f377706ffd0fbAndy Huang addAttachmentAndUpdateView(mAttachmentsView.generateLocalAttachment(contentUri)); 12695c5fd571b40a15b95ea5a5d6033f377706ffd0fbAndy Huang } catch (AttachmentFailureException e) { 12705c5fd571b40a15b95ea5a5d6033f377706ffd0fbAndy Huang LogUtils.e(LOG_TAG, e, "Error adding attachment"); 12713cd4f40dab2c0810cb5ecd77256abf022863b2b5Mindy Pereira showErrorToast(R.string.generic_attachment_problem); 12725c5fd571b40a15b95ea5a5d6033f377706ffd0fbAndy Huang } 12735c5fd571b40a15b95ea5a5d6033f377706ffd0fbAndy Huang } 12745c5fd571b40a15b95ea5a5d6033f377706ffd0fbAndy Huang 12755c5fd571b40a15b95ea5a5d6033f377706ffd0fbAndy Huang public void addAttachmentAndUpdateView(Attachment attachment) { 12765c5fd571b40a15b95ea5a5d6033f377706ffd0fbAndy Huang try { 12775c5fd571b40a15b95ea5a5d6033f377706ffd0fbAndy Huang long size = mAttachmentsView.addAttachment(mAccount, attachment); 12789932dee248718d2cec993d93b5115973d1389d0aMindy Pereira if (size > 0) { 12799932dee248718d2cec993d93b5115973d1389d0aMindy Pereira mAttachmentsChanged = true; 12809932dee248718d2cec993d93b5115973d1389d0aMindy Pereira updateSaveUi(); 1281013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira } 12829932dee248718d2cec993d93b5115973d1389d0aMindy Pereira } catch (AttachmentFailureException e) { 12839932dee248718d2cec993d93b5115973d1389d0aMindy Pereira LogUtils.e(LOG_TAG, e, "Error adding attachment"); 12843cd4f40dab2c0810cb5ecd77256abf022863b2b5Mindy Pereira showAttachmentTooBigToast(); 1285013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira } 1286013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira } 1287013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira 12883ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereira void initRecipientsFromRefMessage(String recipientAddress, Message refMessage, 128946ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira int action) { 12904a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira // Don't populate the address if this is a forward. 12914a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira if (action == ComposeActivity.FORWARD) { 12924a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira return; 12934a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira } 129433fe908589dca6a7f58aa9f56d73f74a48ac42f6Mindy Pereira initReplyRecipients(mAccount.name, refMessage, action); 12954a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira } 12964a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira 1297818143e2163648acc0c91f123b84777d65cd70cfMindy Pereira @VisibleForTesting 12983ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereira void initReplyRecipients(String account, Message refMessage, int action) { 12994a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira // This is the email address of the current user, i.e. the one composing 13004a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira // the reply. 13014a20b708dd9ff3fb2b96f29b0b59012194c6fa34Mindy Pereira final String accountEmail = Address.getEmailAddress(account).getAddress(); 13021469b4e00ea101bc86adef274cf6b4705425b7fcMindy Pereira String fromAddress = getAddress(refMessage.from); 13033ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereira String[] sentToAddresses = Utils.splitCommaSeparatedString(refMessage.to); 13043ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereira String replytoAddress = refMessage.replyTo; 1305a26b54e3a858de409be3746e65591bb8a0d6ea9aMindy Pereira final Collection<String> toAddresses; 13064a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira 13074a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira // If this is a reply, the Cc list is empty. If this is a reply-all, the 13084a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira // Cc list is the union of the To and Cc recipients of the original 13094a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira // message, excluding the current user's email address and any addresses 1310a26b54e3a858de409be3746e65591bb8a0d6ea9aMindy Pereira // already on the To list. 1311a26b54e3a858de409be3746e65591bb8a0d6ea9aMindy Pereira if (action == ComposeActivity.REPLY) { 13123ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereira toAddresses = initToRecipients(account, accountEmail, fromAddress, replytoAddress, 13131469b4e00ea101bc86adef274cf6b4705425b7fcMindy Pereira sentToAddresses); 1314a26b54e3a858de409be3746e65591bb8a0d6ea9aMindy Pereira addToAddresses(toAddresses); 1315a26b54e3a858de409be3746e65591bb8a0d6ea9aMindy Pereira } else if (action == ComposeActivity.REPLY_ALL) { 13164a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira final Set<String> ccAddresses = Sets.newHashSet(); 13173ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereira toAddresses = initToRecipients(account, accountEmail, fromAddress, replytoAddress, 13189b18a9a10538418f0280380e81452c52f5ce2542Mindy Pereira sentToAddresses); 1319154386a287a9bfffb2eb3a4c05445f2774e1d4f0Mindy Pereira addToAddresses(toAddresses); 13204a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira addRecipients(accountEmail, ccAddresses, sentToAddresses); 13213ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereira addRecipients(accountEmail, ccAddresses, 13223ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereira Utils.splitCommaSeparatedString(refMessage.cc)); 13234a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira addCcAddresses(ccAddresses, toAddresses); 13244a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira } 13254a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira } 13264a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira 13271469b4e00ea101bc86adef274cf6b4705425b7fcMindy Pereira private String getAddress(String toParse) { 13281469b4e00ea101bc86adef274cf6b4705425b7fcMindy Pereira if (!TextUtils.isEmpty(toParse)) { 13291469b4e00ea101bc86adef274cf6b4705425b7fcMindy Pereira Rfc822Token[] tokens = Rfc822Tokenizer.tokenize(toParse); 13301469b4e00ea101bc86adef274cf6b4705425b7fcMindy Pereira if (tokens.length > 0) { 13311469b4e00ea101bc86adef274cf6b4705425b7fcMindy Pereira return tokens[0].getAddress(); 13321469b4e00ea101bc86adef274cf6b4705425b7fcMindy Pereira } 13331469b4e00ea101bc86adef274cf6b4705425b7fcMindy Pereira } 13341469b4e00ea101bc86adef274cf6b4705425b7fcMindy Pereira return ""; 13351469b4e00ea101bc86adef274cf6b4705425b7fcMindy Pereira } 13361469b4e00ea101bc86adef274cf6b4705425b7fcMindy Pereira 13374a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira private void addToAddresses(Collection<String> addresses) { 13384a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira addAddressesToList(addresses, mTo); 13394a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira } 13404a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira 13414a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira private void addCcAddresses(Collection<String> addresses, Collection<String> toAddresses) { 13428eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira addCcAddressesToList(tokenizeAddressList(addresses), 13438eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira toAddresses != null ? tokenizeAddressList(toAddresses) : null, mCc); 13444a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira } 13454a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira 1346bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook private void addBccAddresses(Collection<String> addresses) { 1347bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook addAddressesToList(addresses, mBcc); 1348bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook } 1349bb87b7fa57f25fc9cee1f572dd253f33f58f81daPaul Westbrook 13504a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira @VisibleForTesting 13514a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira protected void addCcAddressesToList(List<Rfc822Token[]> addresses, 13524a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira List<Rfc822Token[]> compareToList, RecipientEditTextView list) { 13534a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira String address; 13544a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira 13558eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira if (compareToList == null) { 13568eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira for (Rfc822Token[] tokens : addresses) { 13578eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira for (int i = 0; i < tokens.length; i++) { 13588eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira address = tokens[i].toString(); 13594a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira list.append(address + END_TOKEN); 13604a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira } 13614a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira } 13628eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira } else { 13638eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira HashSet<String> compareTo = convertToHashSet(compareToList); 13648eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira for (Rfc822Token[] tokens : addresses) { 13658eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira for (int i = 0; i < tokens.length; i++) { 13668eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira address = tokens[i].toString(); 13678eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira // Check if this is a duplicate: 13688eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira if (!compareTo.contains(tokens[i].getAddress())) { 13698eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira // Get the address here 13708eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira list.append(address + END_TOKEN); 13718eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira } 13728eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira } 13738eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira } 13744a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira } 13754a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira } 13764a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira 13774a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira private HashSet<String> convertToHashSet(List<Rfc822Token[]> list) { 13784a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira HashSet<String> hash = new HashSet<String>(); 13794a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira for (Rfc822Token[] tokens : list) { 13804a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira for (int i = 0; i < tokens.length; i++) { 13814a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira hash.add(tokens[i].getAddress()); 13824a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira } 13834a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira } 13844a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira return hash; 13854a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira } 13864a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira 13874a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira protected List<Rfc822Token[]> tokenizeAddressList(Collection<String> addresses) { 13884a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira @VisibleForTesting 13894a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira List<Rfc822Token[]> tokenized = new ArrayList<Rfc822Token[]>(); 13904a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira 13914a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira for (String address: addresses) { 13924a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira tokenized.add(Rfc822Tokenizer.tokenize(address)); 13934a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira } 13944a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira return tokenized; 13954a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira } 13964a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira 13974a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira @VisibleForTesting 13984a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira void addAddressesToList(Collection<String> addresses, RecipientEditTextView list) { 13994a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira for (String address : addresses) { 14004a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira addAddressToList(address, list); 14014a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira } 14024a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira } 14034a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira 14044a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira private void addAddressToList(String address, RecipientEditTextView list) { 14054a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira if (address == null || list == null) 14064a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira return; 14074a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira 14084a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira Rfc822Token[] tokens = Rfc822Tokenizer.tokenize(address); 14094a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira 14104a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira for (int i = 0; i < tokens.length; i++) { 14114a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira list.append(tokens[i] + END_TOKEN); 14124a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira } 14134a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira } 14144a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira 14154a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira @VisibleForTesting 14164a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira protected Collection<String> initToRecipients(String account, String accountEmail, 14173ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereira String senderAddress, String replyToAddress, String[] inToAddresses) { 14184a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira // The To recipient is the reply-to address specified in the original 14194a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira // message, unless it is: 14204a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira // the current user OR a custom from of the current user, in which case 14214a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira // it's the To recipient list of the original message. 14224a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira // OR missing, in which case use the sender of the original message 14234a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira Set<String> toAddresses = Sets.newHashSet(); 14243ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereira if (!TextUtils.isEmpty(replyToAddress)) { 14253ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereira toAddresses.add(replyToAddress); 14264a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira } else { 1427cecc54a913a665af3556f3fcc11cfae4d54cb3beMindy Pereira if (!recipientMatchesThisAccount(account, senderAddress)) { 14281469b4e00ea101bc86adef274cf6b4705425b7fcMindy Pereira toAddresses.add(senderAddress); 14291469b4e00ea101bc86adef274cf6b4705425b7fcMindy Pereira } else { 14301469b4e00ea101bc86adef274cf6b4705425b7fcMindy Pereira // This happens if the user replies to a message they originally 14311883b346928322a9f045bc5b7426ddcd6af9beb3Mindy Pereira // wrote. In this case, "reply" really means "re-send," so we 14321883b346928322a9f045bc5b7426ddcd6af9beb3Mindy Pereira // target the original recipients. This works as expected even 14331883b346928322a9f045bc5b7426ddcd6af9beb3Mindy Pereira // if the user sent the original message to themselves. 14341469b4e00ea101bc86adef274cf6b4705425b7fcMindy Pereira toAddresses.addAll(Arrays.asList(inToAddresses)); 14351469b4e00ea101bc86adef274cf6b4705425b7fcMindy Pereira } 14364a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira } 14374a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira return toAddresses; 14384a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira } 14394a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira 1440cecc54a913a665af3556f3fcc11cfae4d54cb3beMindy Pereira private void addRecipients(String accountAddress, Set<String> recipients, String[] addresses) { 14414a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira for (String email : addresses) { 1442cecc54a913a665af3556f3fcc11cfae4d54cb3beMindy Pereira // Do not add this account, or any of its custom from addresses, to 1443cecc54a913a665af3556f3fcc11cfae4d54cb3beMindy Pereira // the list of recipients. 14444a20b708dd9ff3fb2b96f29b0b59012194c6fa34Mindy Pereira final String recipientAddress = Address.getEmailAddress(email).getAddress(); 1445cecc54a913a665af3556f3fcc11cfae4d54cb3beMindy Pereira if (!recipientMatchesThisAccount(accountAddress, recipientAddress)) { 14464a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira recipients.add(email.replace("\"\"", "")); 14474a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira } 14484a27ea93a9eb05558f97a05a5342afb10f3d92ddMindy Pereira } 144946ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira } 145046ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira 1451cecc54a913a665af3556f3fcc11cfae4d54cb3beMindy Pereira /** 1452cecc54a913a665af3556f3fcc11cfae4d54cb3beMindy Pereira * A recipient matches this account if it has the same address as the 1453cecc54a913a665af3556f3fcc11cfae4d54cb3beMindy Pereira * currently selected account OR one of the custom from addresses associated 1454cecc54a913a665af3556f3fcc11cfae4d54cb3beMindy Pereira * with the currently selected account. 1455cecc54a913a665af3556f3fcc11cfae4d54cb3beMindy Pereira * @param accountAddress currently selected account 1456cecc54a913a665af3556f3fcc11cfae4d54cb3beMindy Pereira * @param recipientAddress address we are comparing with the currently selected account 1457cecc54a913a665af3556f3fcc11cfae4d54cb3beMindy Pereira * @return 1458cecc54a913a665af3556f3fcc11cfae4d54cb3beMindy Pereira */ 1459cecc54a913a665af3556f3fcc11cfae4d54cb3beMindy Pereira protected boolean recipientMatchesThisAccount(String accountAddress, String recipientAddress) { 1460cecc54a913a665af3556f3fcc11cfae4d54cb3beMindy Pereira return accountAddress.equalsIgnoreCase(recipientAddress) 1461cecc54a913a665af3556f3fcc11cfae4d54cb3beMindy Pereira || ReplyFromAccount.isCustomFrom(recipientAddress, 1462cecc54a913a665af3556f3fcc11cfae4d54cb3beMindy Pereira mFromSpinner.getReplyFromAccounts()); 1463cecc54a913a665af3556f3fcc11cfae4d54cb3beMindy Pereira } 1464cecc54a913a665af3556f3fcc11cfae4d54cb3beMindy Pereira 14653ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereira private void setSubject(Message refMessage, int action) { 14663ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereira String subject = refMessage.subject; 146746ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira String prefix; 146846ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira String correctedSubject = null; 146946ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira if (action == ComposeActivity.COMPOSE) { 147046ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira prefix = ""; 147146ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira } else if (action == ComposeActivity.FORWARD) { 147246ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira prefix = getString(R.string.forward_subject_label); 147346ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira } else { 147446ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira prefix = getString(R.string.reply_subject_label); 147546ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira } 147646ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira 147746ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira // Don't duplicate the prefix 1478c7a36999abb396ac965a981e0a3f658b537213acMindy Pereira if (!TextUtils.isEmpty(subject) 1479c7a36999abb396ac965a981e0a3f658b537213acMindy Pereira && subject.toLowerCase().startsWith(prefix.toLowerCase())) { 148046ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira correctedSubject = subject; 148146ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira } else { 148246ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira correctedSubject = String 148346ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira .format(getString(R.string.formatted_subject), prefix, subject); 148446ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira } 148546ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira mSubject.setText(correctedSubject); 148646ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira } 148746ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira 1488818143e2163648acc0c91f123b84777d65cd70cfMindy Pereira private void initRecipients() { 1489818143e2163648acc0c91f123b84777d65cd70cfMindy Pereira setupRecipients(mTo); 1490818143e2163648acc0c91f123b84777d65cd70cfMindy Pereira setupRecipients(mCc); 1491818143e2163648acc0c91f123b84777d65cd70cfMindy Pereira setupRecipients(mBcc); 1492eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira } 1493eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira 1494818143e2163648acc0c91f123b84777d65cd70cfMindy Pereira private void setupRecipients(RecipientEditTextView view) { 1495679a8cc895ec75d3b578dbc77db1e9c04dd7f8b0Paul Westbrook view.setAdapter(new RecipientAdapter(this, mAccount)); 1496c17d073dd43871df36ea70b3dea55963bdb98384Mindy Pereira view.setTokenizer(new Rfc822Tokenizer()); 149782cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira if (mValidator == null) { 1498679a8cc895ec75d3b578dbc77db1e9c04dd7f8b0Paul Westbrook final String accountName = mAccount.name; 149933fe908589dca6a7f58aa9f56d73f74a48ac42f6Mindy Pereira int offset = accountName.indexOf("@") + 1; 150033fe908589dca6a7f58aa9f56d73f74a48ac42f6Mindy Pereira String account = accountName; 1501c17d073dd43871df36ea70b3dea55963bdb98384Mindy Pereira if (offset > -1) { 150233fe908589dca6a7f58aa9f56d73f74a48ac42f6Mindy Pereira account = account.substring(accountName.indexOf("@") + 1); 1503c17d073dd43871df36ea70b3dea55963bdb98384Mindy Pereira } 150482cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira mValidator = new Rfc822Validator(account); 1505c17d073dd43871df36ea70b3dea55963bdb98384Mindy Pereira } 150682cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira view.setValidator(mValidator); 15078e9305ec0bbe23cec01eb34a2aee76c55199a10aMindy Pereira } 15088e9305ec0bbe23cec01eb34a2aee76c55199a10aMindy Pereira 15098e9305ec0bbe23cec01eb34a2aee76c55199a10aMindy Pereira @Override 15108e9305ec0bbe23cec01eb34a2aee76c55199a10aMindy Pereira public void onClick(View v) { 15118e9305ec0bbe23cec01eb34a2aee76c55199a10aMindy Pereira int id = v.getId(); 15128e9305ec0bbe23cec01eb34a2aee76c55199a10aMindy Pereira switch (id) { 1513a26b54e3a858de409be3746e65591bb8a0d6ea9aMindy Pereira case R.id.add_cc_bcc: 15148e9305ec0bbe23cec01eb34a2aee76c55199a10aMindy Pereira // Verify that cc/ bcc aren't showing. 15158e9305ec0bbe23cec01eb34a2aee76c55199a10aMindy Pereira // Animate in cc/bcc. 1516a26b54e3a858de409be3746e65591bb8a0d6ea9aMindy Pereira showCcBccViews(); 15178e9305ec0bbe23cec01eb34a2aee76c55199a10aMindy Pereira break; 15181f93668e1186d48b507207841c1ca0529c3de292Mindy Pereira case R.id.add_attachment: 15198f1c01e908d5986e8222dfd45ab82d6895b1ff3bAndrew Sapperstein openAttachmentTypeSelectionDialog(); 15201f93668e1186d48b507207841c1ca0529c3de292Mindy Pereira break; 15218e9305ec0bbe23cec01eb34a2aee76c55199a10aMindy Pereira } 15228e9305ec0bbe23cec01eb34a2aee76c55199a10aMindy Pereira } 1523b47f3e286bcf78e85ab2d3389e38e99020d0634fMindy Pereira 1524b47f3e286bcf78e85ab2d3389e38e99020d0634fMindy Pereira @Override 1525b47f3e286bcf78e85ab2d3389e38e99020d0634fMindy Pereira public boolean onCreateOptionsMenu(Menu menu) { 1526b47f3e286bcf78e85ab2d3389e38e99020d0634fMindy Pereira super.onCreateOptionsMenu(menu); 1527b47f3e286bcf78e85ab2d3389e38e99020d0634fMindy Pereira MenuInflater inflater = getMenuInflater(); 1528b47f3e286bcf78e85ab2d3389e38e99020d0634fMindy Pereira inflater.inflate(R.menu.compose_menu, menu); 152982cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira mSave = menu.findItem(R.id.save); 153082cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira mSend = menu.findItem(R.id.send); 15313ca5bad62c075184920c5e331870280fc6acca16Mindy Pereira MenuItem helpItem = menu.findItem(R.id.help_info_menu_item); 15323ca5bad62c075184920c5e331870280fc6acca16Mindy Pereira MenuItem sendFeedbackItem = menu.findItem(R.id.feedback_menu_item); 15333ca5bad62c075184920c5e331870280fc6acca16Mindy Pereira if (helpItem != null) { 15343ca5bad62c075184920c5e331870280fc6acca16Mindy Pereira helpItem.setVisible(mAccount != null 15353ca5bad62c075184920c5e331870280fc6acca16Mindy Pereira && mAccount.supportsCapability(AccountCapabilities.HELP_CONTENT)); 15363ca5bad62c075184920c5e331870280fc6acca16Mindy Pereira } 15373ca5bad62c075184920c5e331870280fc6acca16Mindy Pereira if (sendFeedbackItem != null) { 15383ca5bad62c075184920c5e331870280fc6acca16Mindy Pereira sendFeedbackItem.setVisible(mAccount != null 15393ca5bad62c075184920c5e331870280fc6acca16Mindy Pereira && mAccount.supportsCapability(AccountCapabilities.SEND_FEEDBACK)); 15403ca5bad62c075184920c5e331870280fc6acca16Mindy Pereira } 1541b47f3e286bcf78e85ab2d3389e38e99020d0634fMindy Pereira return true; 1542b47f3e286bcf78e85ab2d3389e38e99020d0634fMindy Pereira } 1543b47f3e286bcf78e85ab2d3389e38e99020d0634fMindy Pereira 1544b47f3e286bcf78e85ab2d3389e38e99020d0634fMindy Pereira @Override 1545ec8b0edb23c0e0b7f1a8ce9558a919be31169d45Mindy Pereira public boolean onPrepareOptionsMenu(Menu menu) { 1546ec8b0edb23c0e0b7f1a8ce9558a919be31169d45Mindy Pereira MenuItem ccBcc = menu.findItem(R.id.add_cc_bcc); 1547818143e2163648acc0c91f123b84777d65cd70cfMindy Pereira if (ccBcc != null && mCc != null) { 1548ec8b0edb23c0e0b7f1a8ce9558a919be31169d45Mindy Pereira // Its possible there is a menu item OR a button. 1549ec8b0edb23c0e0b7f1a8ce9558a919be31169d45Mindy Pereira boolean ccFieldVisible = mCc.isShown(); 1550ec8b0edb23c0e0b7f1a8ce9558a919be31169d45Mindy Pereira boolean bccFieldVisible = mBcc.isShown(); 1551ec8b0edb23c0e0b7f1a8ce9558a919be31169d45Mindy Pereira if (!ccFieldVisible || !bccFieldVisible) { 1552ec8b0edb23c0e0b7f1a8ce9558a919be31169d45Mindy Pereira ccBcc.setVisible(true); 1553ec8b0edb23c0e0b7f1a8ce9558a919be31169d45Mindy Pereira ccBcc.setTitle(getString(!ccFieldVisible ? R.string.add_cc_label 1554ec8b0edb23c0e0b7f1a8ce9558a919be31169d45Mindy Pereira : R.string.add_bcc_label)); 1555ec8b0edb23c0e0b7f1a8ce9558a919be31169d45Mindy Pereira } else { 1556ec8b0edb23c0e0b7f1a8ce9558a919be31169d45Mindy Pereira ccBcc.setVisible(false); 1557ec8b0edb23c0e0b7f1a8ce9558a919be31169d45Mindy Pereira } 1558ec8b0edb23c0e0b7f1a8ce9558a919be31169d45Mindy Pereira } 155975f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira if (mSave != null) { 156075f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira mSave.setEnabled(shouldSave()); 156175f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira } 1562ec8b0edb23c0e0b7f1a8ce9558a919be31169d45Mindy Pereira return true; 1563ec8b0edb23c0e0b7f1a8ce9558a919be31169d45Mindy Pereira } 1564ec8b0edb23c0e0b7f1a8ce9558a919be31169d45Mindy Pereira 1565ec8b0edb23c0e0b7f1a8ce9558a919be31169d45Mindy Pereira @Override 1566b47f3e286bcf78e85ab2d3389e38e99020d0634fMindy Pereira public boolean onOptionsItemSelected(MenuItem item) { 1567b47f3e286bcf78e85ab2d3389e38e99020d0634fMindy Pereira int id = item.getItemId(); 156875f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira boolean handled = true; 1569b47f3e286bcf78e85ab2d3389e38e99020d0634fMindy Pereira switch (id) { 15707b56a61174eeb202eea468b7f68b79729737ded2Mindy Pereira case R.id.add_attachment: 15718f1c01e908d5986e8222dfd45ab82d6895b1ff3bAndrew Sapperstein openAttachmentTypeSelectionDialog(); 15727b56a61174eeb202eea468b7f68b79729737ded2Mindy Pereira break; 1573ec8b0edb23c0e0b7f1a8ce9558a919be31169d45Mindy Pereira case R.id.add_cc_bcc: 1574ec8b0edb23c0e0b7f1a8ce9558a919be31169d45Mindy Pereira showCcBccViews(); 1575b47f3e286bcf78e85ab2d3389e38e99020d0634fMindy Pereira break; 157633fe908589dca6a7f58aa9f56d73f74a48ac42f6Mindy Pereira case R.id.save: 157748e31b07b5ac7c83dc3a009242fa915afccddb9eMindy Pereira doSave(true); 157833fe908589dca6a7f58aa9f56d73f74a48ac42f6Mindy Pereira break; 157933fe908589dca6a7f58aa9f56d73f74a48ac42f6Mindy Pereira case R.id.send: 158033fe908589dca6a7f58aa9f56d73f74a48ac42f6Mindy Pereira doSend(); 158175f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira break; 1582efe3d25aa19da172fd5c3ec39539cdd91f29e927Mindy Pereira case R.id.discard: 1583efe3d25aa19da172fd5c3ec39539cdd91f29e927Mindy Pereira doDiscard(); 1584efe3d25aa19da172fd5c3ec39539cdd91f29e927Mindy Pereira break; 15851f93668e1186d48b507207841c1ca0529c3de292Mindy Pereira case R.id.settings: 15861f93668e1186d48b507207841c1ca0529c3de292Mindy Pereira Utils.showSettings(this, mAccount); 15871f93668e1186d48b507207841c1ca0529c3de292Mindy Pereira break; 1588fbe4019a262f6b1934a44e598009ae63dc5745eeMindy Pereira case android.R.id.home: 1589daecb4b9b20a609b27fc803390ecf4f524b76089Paul Westbrook onAppUpPressed(); 1590fbe4019a262f6b1934a44e598009ae63dc5745eeMindy Pereira break; 1591fbe4019a262f6b1934a44e598009ae63dc5745eeMindy Pereira case R.id.help_info_menu_item: 1592fbe4019a262f6b1934a44e598009ae63dc5745eeMindy Pereira // TODO: enable context sensitive help 1593498e76d7efccc92386fe57c65a2ef8d5a0172604Paul Westbrook Utils.showHelp(this, mAccount, null); 1594fbe4019a262f6b1934a44e598009ae63dc5745eeMindy Pereira break; 1595fbe4019a262f6b1934a44e598009ae63dc5745eeMindy Pereira case R.id.feedback_menu_item: 1596fbe4019a262f6b1934a44e598009ae63dc5745eeMindy Pereira Utils.sendFeedback(this, mAccount); 1597fbe4019a262f6b1934a44e598009ae63dc5745eeMindy Pereira break; 159875f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira default: 159975f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira handled = false; 160033fe908589dca6a7f58aa9f56d73f74a48ac42f6Mindy Pereira break; 1601b47f3e286bcf78e85ab2d3389e38e99020d0634fMindy Pereira } 1602b47f3e286bcf78e85ab2d3389e38e99020d0634fMindy Pereira return !handled ? super.onOptionsItemSelected(item) : handled; 1603b47f3e286bcf78e85ab2d3389e38e99020d0634fMindy Pereira } 1604326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira 1605daecb4b9b20a609b27fc803390ecf4f524b76089Paul Westbrook private void onAppUpPressed() { 1606daecb4b9b20a609b27fc803390ecf4f524b76089Paul Westbrook if (mLaunchedFromEmail) { 1607daecb4b9b20a609b27fc803390ecf4f524b76089Paul Westbrook // If this was started from Gmail, simply treat app up as the system back button, so 1608daecb4b9b20a609b27fc803390ecf4f524b76089Paul Westbrook // that the last view is restored. 1609daecb4b9b20a609b27fc803390ecf4f524b76089Paul Westbrook onBackPressed(); 1610daecb4b9b20a609b27fc803390ecf4f524b76089Paul Westbrook return; 1611daecb4b9b20a609b27fc803390ecf4f524b76089Paul Westbrook } 1612daecb4b9b20a609b27fc803390ecf4f524b76089Paul Westbrook 1613daecb4b9b20a609b27fc803390ecf4f524b76089Paul Westbrook // Fire the main activity to ensure it launches the "top" screen of mail. 1614daecb4b9b20a609b27fc803390ecf4f524b76089Paul Westbrook // Since the main Activity is singleTask, it should revive that task if it was already 1615daecb4b9b20a609b27fc803390ecf4f524b76089Paul Westbrook // started. 16165ad02918f663bc52522a2505de985df9ef5ea347Mindy Pereira Folder defaultInbox = new Folder(); 16175ad02918f663bc52522a2505de985df9ef5ea347Mindy Pereira defaultInbox.uri = mAccount.settings.defaultInbox; 1618daecb4b9b20a609b27fc803390ecf4f524b76089Paul Westbrook final Intent mailIntent = 161996a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira Utils.createViewFolderIntent(defaultInbox, mAccount); 1620daecb4b9b20a609b27fc803390ecf4f524b76089Paul Westbrook 1621daecb4b9b20a609b27fc803390ecf4f524b76089Paul Westbrook mailIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK | 1622daecb4b9b20a609b27fc803390ecf4f524b76089Paul Westbrook Intent.FLAG_ACTIVITY_TASK_ON_HOME); 1623daecb4b9b20a609b27fc803390ecf4f524b76089Paul Westbrook startActivity(mailIntent); 1624daecb4b9b20a609b27fc803390ecf4f524b76089Paul Westbrook finish(); 1625daecb4b9b20a609b27fc803390ecf4f524b76089Paul Westbrook } 1626daecb4b9b20a609b27fc803390ecf4f524b76089Paul Westbrook 162733fe908589dca6a7f58aa9f56d73f74a48ac42f6Mindy Pereira private void doSend() { 16288aa913bd66109f7a4252dd07d10f73132ce7beedMindy Pereira clearImeText(); 162982cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira sendOrSaveWithSanityChecks(false, true, false); 163033fe908589dca6a7f58aa9f56d73f74a48ac42f6Mindy Pereira } 163133fe908589dca6a7f58aa9f56d73f74a48ac42f6Mindy Pereira 163248e31b07b5ac7c83dc3a009242fa915afccddb9eMindy Pereira private void doSave(boolean showToast) { 163348e31b07b5ac7c83dc3a009242fa915afccddb9eMindy Pereira // Clear the IME composing suggestions from the body and subject before saving. 16348aa913bd66109f7a4252dd07d10f73132ce7beedMindy Pereira clearImeText(); 1635eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira sendOrSaveWithSanityChecks(true, showToast, false); 163648e31b07b5ac7c83dc3a009242fa915afccddb9eMindy Pereira } 163748e31b07b5ac7c83dc3a009242fa915afccddb9eMindy Pereira 16388aa913bd66109f7a4252dd07d10f73132ce7beedMindy Pereira private void clearImeText() { 16398aa913bd66109f7a4252dd07d10f73132ce7beedMindy Pereira mBodyView.clearComposingText(); 16408aa913bd66109f7a4252dd07d10f73132ce7beedMindy Pereira BaseInputConnection.removeComposingSpans(mBodyView.getEditableText()); 16418aa913bd66109f7a4252dd07d10f73132ce7beedMindy Pereira mSubject.clearComposingText(); 16428aa913bd66109f7a4252dd07d10f73132ce7beedMindy Pereira BaseInputConnection.removeComposingSpans(mSubject.getEditableText()); 164382cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira } 164482cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira 1645e011b1d1c8e2e674dfdf1985d9d13da8cc06d803Mindy Pereira @VisibleForTesting 1646e011b1d1c8e2e674dfdf1985d9d13da8cc06d803Mindy Pereira public interface SendOrSaveCallback { 164782cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira public void initializeSendOrSave(SendOrSaveTask sendOrSaveTask); 16487ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira public void notifyMessageIdAllocated(SendOrSaveMessage sendOrSaveMessage, Message message); 16497ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira public Message getMessage(); 165082cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira public void sendOrSaveFinished(SendOrSaveTask sendOrSaveTask, boolean success); 165182cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira } 165282cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira 1653e011b1d1c8e2e674dfdf1985d9d13da8cc06d803Mindy Pereira @VisibleForTesting 1654e011b1d1c8e2e674dfdf1985d9d13da8cc06d803Mindy Pereira public static class SendOrSaveTask implements Runnable { 165582cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira private final Context mContext; 165682cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira @VisibleForTesting 1657e011b1d1c8e2e674dfdf1985d9d13da8cc06d803Mindy Pereira public final SendOrSaveCallback mSendOrSaveCallback; 1658e011b1d1c8e2e674dfdf1985d9d13da8cc06d803Mindy Pereira @VisibleForTesting 1659e011b1d1c8e2e674dfdf1985d9d13da8cc06d803Mindy Pereira public final SendOrSaveMessage mSendOrSaveMessage; 166082cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira 166182cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira public SendOrSaveTask(Context context, SendOrSaveMessage message, 166282cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira SendOrSaveCallback callback) { 166382cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira mContext = context; 166482cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira mSendOrSaveCallback = callback; 166582cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira mSendOrSaveMessage = message; 166682cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira } 166782cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira 166882cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira @Override 166982cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira public void run() { 16707ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira final SendOrSaveMessage sendOrSaveMessage = mSendOrSaveMessage; 167182cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira 167292551d057965689f1952faeb06763f0762bc717fMindy Pereira final ReplyFromAccount selectedAccount = sendOrSaveMessage.mAccount; 16737ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira Message message = mSendOrSaveCallback.getMessage(); 16747ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira long messageId = message != null ? message.id : UIProvider.INVALID_MESSAGE_ID; 167582cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira // If a previous draft has been saved, in an account that is different 167682cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira // than what the user wants to send from, remove the old draft, and treat this 167782cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira // as a new message 16787ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira if (!selectedAccount.equals(sendOrSaveMessage.mAccount)) { 167982cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira if (messageId != UIProvider.INVALID_MESSAGE_ID) { 168082cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira ContentResolver resolver = mContext.getContentResolver(); 168182cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira ContentValues values = new ContentValues(); 168282cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira values.put(BaseColumns._ID, messageId); 168392551d057965689f1952faeb06763f0762bc717fMindy Pereira if (selectedAccount.account.expungeMessageUri != null) { 168492551d057965689f1952faeb06763f0762bc717fMindy Pereira resolver.update(selectedAccount.account.expungeMessageUri, values, null, 1685eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira null); 1686cfb7f33ff8ef9dc60b9143af32de64c7a3d71f36Mindy Pereira } else { 1687cfb7f33ff8ef9dc60b9143af32de64c7a3d71f36Mindy Pereira // TODO(mindyp) delete the conversation. 1688eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira } 168982cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira // reset messageId to 0, so a new message will be created 169082cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira messageId = UIProvider.INVALID_MESSAGE_ID; 169182cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira } 169282cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira } 169382cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira 169482cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira final long messageIdToSave = messageId; 169582cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira if (messageIdToSave != UIProvider.INVALID_MESSAGE_ID) { 16967ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira sendOrSaveMessage.mValues.put(BaseColumns._ID, messageIdToSave); 169782cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira mContext.getContentResolver().update( 16987ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira Uri.parse(sendOrSaveMessage.mSave ? message.saveUri : message.sendUri), 16997ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira sendOrSaveMessage.mValues, null, null); 170082cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira } else { 17017ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira ContentResolver resolver = mContext.getContentResolver(); 170292551d057965689f1952faeb06763f0762bc717fMindy Pereira Uri messageUri = resolver 170392551d057965689f1952faeb06763f0762bc717fMindy Pereira .insert(sendOrSaveMessage.mSave ? selectedAccount.account.saveDraftUri 170492551d057965689f1952faeb06763f0762bc717fMindy Pereira : selectedAccount.account.sendMessageUri, 170592551d057965689f1952faeb06763f0762bc717fMindy Pereira sendOrSaveMessage.mValues); 17067ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira if (sendOrSaveMessage.mSave && messageUri != null) { 17077ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira Cursor messageCursor = resolver.query(messageUri, 17087ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira UIProvider.MESSAGE_PROJECTION, null, null, null); 1709ba5584836c0a63c8dac96b10b569465bd56d5f7aPaul Westbrook if (messageCursor != null) { 1710ba5584836c0a63c8dac96b10b569465bd56d5f7aPaul Westbrook try { 1711ba5584836c0a63c8dac96b10b569465bd56d5f7aPaul Westbrook if (messageCursor.moveToFirst()) { 1712ba5584836c0a63c8dac96b10b569465bd56d5f7aPaul Westbrook // Broadcast notification that a new message has 1713ba5584836c0a63c8dac96b10b569465bd56d5f7aPaul Westbrook // been allocated 1714ba5584836c0a63c8dac96b10b569465bd56d5f7aPaul Westbrook mSendOrSaveCallback.notifyMessageIdAllocated(sendOrSaveMessage, 1715ba5584836c0a63c8dac96b10b569465bd56d5f7aPaul Westbrook new Message(messageCursor)); 1716ba5584836c0a63c8dac96b10b569465bd56d5f7aPaul Westbrook } 1717ba5584836c0a63c8dac96b10b569465bd56d5f7aPaul Westbrook } finally { 1718ba5584836c0a63c8dac96b10b569465bd56d5f7aPaul Westbrook messageCursor.close(); 1719ba5584836c0a63c8dac96b10b569465bd56d5f7aPaul Westbrook } 17207ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira } 17217ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira } 172282cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira } 172382cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira 17247ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira if (!sendOrSaveMessage.mSave) { 172582cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira UIProvider.incrementRecipientsTimesContacted(mContext, 17267ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira (String) sendOrSaveMessage.mValues.get(UIProvider.MessageColumns.TO)); 172782cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira UIProvider.incrementRecipientsTimesContacted(mContext, 17287ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira (String) sendOrSaveMessage.mValues.get(UIProvider.MessageColumns.CC)); 172982cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira UIProvider.incrementRecipientsTimesContacted(mContext, 17307ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira (String) sendOrSaveMessage.mValues.get(UIProvider.MessageColumns.BCC)); 173182cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira } 173282cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira mSendOrSaveCallback.sendOrSaveFinished(SendOrSaveTask.this, true); 173382cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira } 173482cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira } 173582cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira 173682cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira // Array of the outstanding send or save tasks. Access is synchronized 173782cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira // with the object itself 173882cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira /* package for testing */ 1739e011b1d1c8e2e674dfdf1985d9d13da8cc06d803Mindy Pereira @VisibleForTesting 1740e011b1d1c8e2e674dfdf1985d9d13da8cc06d803Mindy Pereira public ArrayList<SendOrSaveTask> mActiveTasks = Lists.newArrayList(); 174182cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira private int mRequestId; 1742bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira private String mSignature; 17438f1c01e908d5986e8222dfd45ab82d6895b1ff3bAndrew Sapperstein private AttachmentTypeSelectorAdapter mAttachmentTypeSelectorAdapter; 174482cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira 1745e011b1d1c8e2e674dfdf1985d9d13da8cc06d803Mindy Pereira @VisibleForTesting 1746e011b1d1c8e2e674dfdf1985d9d13da8cc06d803Mindy Pereira public static class SendOrSaveMessage { 174792551d057965689f1952faeb06763f0762bc717fMindy Pereira final ReplyFromAccount mAccount; 174882cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira final ContentValues mValues; 17493ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereira final String mRefMessageId; 1750e011b1d1c8e2e674dfdf1985d9d13da8cc06d803Mindy Pereira @VisibleForTesting 1751e011b1d1c8e2e674dfdf1985d9d13da8cc06d803Mindy Pereira public final boolean mSave; 175282cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira final int mRequestId; 175382cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira 175492551d057965689f1952faeb06763f0762bc717fMindy Pereira public SendOrSaveMessage(ReplyFromAccount account, ContentValues values, 17553ce64e7ceb6246130342385d91550bcf33b31cc8Mindy Pereira String refMessageId, boolean save) { 175682cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira mAccount = account; 175782cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira mValues = values; 175882cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira mRefMessageId = refMessageId; 175982cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira mSave = save; 176082cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira mRequestId = mValues.hashCode() ^ hashCode(); 176182cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira } 176282cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira 176382cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira int requestId() { 176482cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira return mRequestId; 176582cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira } 176682cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira } 176782cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira 176882cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira /** 176982cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira * Get the to recipients. 177082cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira */ 177182cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira public String[] getToAddresses() { 177282cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira return getAddressesFromList(mTo); 177382cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira } 177482cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira 177582cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira /** 177682cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira * Get the cc recipients. 177782cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira */ 177882cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira public String[] getCcAddresses() { 177982cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira return getAddressesFromList(mCc); 178082cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira } 178182cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira 178282cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira /** 178382cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira * Get the bcc recipients. 178482cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira */ 178582cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira public String[] getBccAddresses() { 178682cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira return getAddressesFromList(mBcc); 178782cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira } 178882cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira 178982cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira public String[] getAddressesFromList(RecipientEditTextView list) { 179082cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira if (list == null) { 179182cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira return new String[0]; 179282cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira } 179382cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira Rfc822Token[] tokens = Rfc822Tokenizer.tokenize(list.getText()); 179482cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira int count = tokens.length; 179582cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira String[] result = new String[count]; 179682cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira for (int i = 0; i < count; i++) { 179782cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira result[i] = tokens[i].toString(); 179882cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira } 179982cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira return result; 180082cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira } 180182cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira 180282cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira /** 180382cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira * Check for invalid email addresses. 180482cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira * @param to String array of email addresses to check. 180582cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira * @param wrongEmailsOut Emails addresses that were invalid. 180682cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira */ 180782cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira public void checkInvalidEmails(String[] to, List<String> wrongEmailsOut) { 1808e5f20bf1c293497625b0f2865302e6712a854959Mindy Pereira if (mValidator == null) { 1809e5f20bf1c293497625b0f2865302e6712a854959Mindy Pereira return; 1810e5f20bf1c293497625b0f2865302e6712a854959Mindy Pereira } 181182cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira for (String email : to) { 181282cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira if (!mValidator.isValid(email)) { 181382cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira wrongEmailsOut.add(email); 181482cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira } 181582cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira } 181682cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira } 181782cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira 181882cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira /** 181982cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira * Show an error because the user has entered an invalid recipient. 182082cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira * @param message 182182cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira */ 182282cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira public void showRecipientErrorDialog(String message) { 182382cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira // Only 1 invalid recipients error dialog should be allowed up at a 182482cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira // time. 182582cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira if (mRecipientErrorDialog != null) { 182682cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira mRecipientErrorDialog.dismiss(); 182782cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira } 182882cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira mRecipientErrorDialog = new AlertDialog.Builder(this).setMessage(message).setTitle( 182982cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira R.string.recipient_error_dialog_title) 183082cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira .setIconAttribute(android.R.attr.alertDialogIcon) 183182cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira .setPositiveButton( 183282cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira R.string.ok, new Dialog.OnClickListener() { 18330bbc858506c95005f2840fa5dff495a9216d2665Marc Blank @Override 183482cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira public void onClick(DialogInterface dialog, int which) { 183582cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira // after the user dismisses the recipient error 183682cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira // dialog we want to make sure to refocus the 183782cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira // recipient to field so they can fix the issue 183882cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira // easily 183982cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira if (mTo != null) { 184082cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira mTo.requestFocus(); 184182cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira } 184282cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira mRecipientErrorDialog = null; 184382cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira } 184482cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira }).show(); 184582cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira } 184682cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira 184782cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira /** 184882cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira * Update the state of the UI based on whether or not the current draft 184982cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira * needs to be saved and the message is not empty. 185082cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira */ 1851eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira public void updateSaveUi() { 185282cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira if (mSave != null) { 185382cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira mSave.setEnabled((shouldSave() && !isBlank())); 185482cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira } 185582cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira } 185682cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira 185782cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira /** 185882cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira * Returns true if we need to save the current draft. 185982cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira */ 186082cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira private boolean shouldSave() { 18617ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira synchronized (mDraftLock) { 186282cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira // The message should only be saved if: 186382cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira // It hasn't been sent AND 186482cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira // Some text has been added to the message OR 186582cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira // an attachment has been added or removed 1866a214833a75ba2b27cdd166ceee9a2529b13a17c4Mindy Pereira // AND there is actually something in the draft to save. 1867d47877e3860ea4249eddb3f6efefbc6cd39f2320Andy Huang return (mTextChanged || mAttachmentsChanged || mReplyFromChanged) 1868a214833a75ba2b27cdd166ceee9a2529b13a17c4Mindy Pereira && !isBlank(); 186982cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira } 187082cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira } 187182cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira 187282cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira /** 1873bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira * Check if all fields are blank. 187482cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira * @return boolean 187582cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira */ 187682cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira public boolean isBlank() { 187782cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira return mSubject.getText().length() == 0 1878bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira && (mBodyView.getText().length() == 0 || getSignatureStartPosition(mSignature, 1879bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira mBodyView.getText().toString()) == 0) 1880bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira && mTo.length() == 0 1881bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira && mCc.length() == 0 && mBcc.length() == 0 1882bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira && mAttachmentsView.getAttachments().size() == 0; 1883bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira } 1884bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira 1885bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira @VisibleForTesting 1886bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira protected int getSignatureStartPosition(String signature, String bodyText) { 1887bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira int startPos = -1; 1888bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira 1889bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira if (TextUtils.isEmpty(signature) || TextUtils.isEmpty(bodyText)) { 1890bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira return startPos; 1891bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira } 1892bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira 1893bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira int bodyLength = bodyText.length(); 1894bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira int signatureLength = signature.length(); 1895bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira String printableVersion = convertToPrintableSignature(signature); 1896bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira int printableLength = printableVersion.length(); 1897bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira 1898bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira if (bodyLength >= printableLength 1899bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira && bodyText.substring(bodyLength - printableLength) 1900bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira .equals(printableVersion)) { 1901bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira startPos = bodyLength - printableLength; 1902bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira } else if (bodyLength >= signatureLength 1903bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira && bodyText.substring(bodyLength - signatureLength) 1904bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira .equals(signature)) { 1905bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira startPos = bodyLength - signatureLength; 1906bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira } 1907bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira return startPos; 190882cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira } 190982cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira 191082cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira /** 191182cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira * Allows any changes made by the user to be ignored. Called when the user 191282cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira * decides to discard a draft. 191382cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira */ 191482cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira private void discardChanges() { 191582cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira mTextChanged = false; 1916eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira mAttachmentsChanged = false; 191782cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira mReplyFromChanged = false; 191833fe908589dca6a7f58aa9f56d73f74a48ac42f6Mindy Pereira } 191933fe908589dca6a7f58aa9f56d73f74a48ac42f6Mindy Pereira 192082cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira /** 1921181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira * @param body 1922181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira * @param save 1923181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira * @param showToast 1924181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira * @return Whether the send or save succeeded. 1925181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira */ 1926181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira protected boolean sendOrSaveWithSanityChecks(final boolean save, final boolean showToast, 1927181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira final boolean orientationChanged) { 1928181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira String[] to, cc, bcc; 1929181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira Editable body = mBodyView.getEditableText(); 1930181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira if (orientationChanged) { 1931181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira to = cc = bcc = new String[0]; 1932181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira } else { 1933181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira to = getToAddresses(); 1934181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira cc = getCcAddresses(); 1935181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira bcc = getBccAddresses(); 1936181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira } 1937181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira 1938181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira // Don't let the user send to nobody (but it's okay to save a message 1939181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira // with no recipients) 1940181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira if (!save && (to.length == 0 && cc.length == 0 && bcc.length == 0)) { 1941181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira showRecipientErrorDialog(getString(R.string.recipient_needed)); 1942181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira return false; 1943181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira } 1944181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira 1945181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira List<String> wrongEmails = new ArrayList<String>(); 1946181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira if (!save) { 1947181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira checkInvalidEmails(to, wrongEmails); 1948181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira checkInvalidEmails(cc, wrongEmails); 1949181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira checkInvalidEmails(bcc, wrongEmails); 1950181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira } 1951181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira 1952181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira // Don't let the user send an email with invalid recipients 1953181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira if (wrongEmails.size() > 0) { 1954181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira String errorText = String.format(getString(R.string.invalid_recipient), 1955181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira wrongEmails.get(0)); 1956181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira showRecipientErrorDialog(errorText); 1957181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira return false; 1958181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira } 1959181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira 1960181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira DialogInterface.OnClickListener listener = new DialogInterface.OnClickListener() { 19610bbc858506c95005f2840fa5dff495a9216d2665Marc Blank @Override 1962181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira public void onClick(DialogInterface dialog, int which) { 1963181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira sendOrSave(mBodyView.getEditableText(), save, showToast, orientationChanged); 1964181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira } 1965181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira }; 1966181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira 1967181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira // Show a warning before sending only if there are no attachments. 1968181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira if (!save) { 1969181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira if (mAttachmentsView.getAttachments().isEmpty() && showEmptyTextWarnings()) { 1970181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira boolean warnAboutEmptySubject = isSubjectEmpty(); 1971181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira boolean emptyBody = TextUtils.getTrimmedLength(body) == 0; 1972181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira 1973181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira // A warning about an empty body may not be warranted when 1974181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira // forwarding mails, since a common use case is to forward 1975181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira // quoted text and not append any more text. 1976181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira boolean warnAboutEmptyBody = emptyBody && (!mForward || isBodyEmpty()); 1977181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira 1978181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira // When we bring up a dialog warning the user about a send, 1979181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira // assume that they accept sending the message. If they do not, 1980181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira // the dialog listener is required to enable sending again. 1981181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira if (warnAboutEmptySubject) { 1982181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira showSendConfirmDialog(R.string.confirm_send_message_with_no_subject, listener); 1983181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira return true; 1984181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira } 1985181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira 1986181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira if (warnAboutEmptyBody) { 1987181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira showSendConfirmDialog(R.string.confirm_send_message_with_no_body, listener); 1988181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira return true; 1989181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira } 1990181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira } 1991181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira // Ask for confirmation to send (if always required) 1992181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira if (showSendConfirmation()) { 1993181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira showSendConfirmDialog(R.string.confirm_send_message, listener); 1994181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira return true; 1995181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira } 1996181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira } 1997181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira 1998181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira sendOrSave(body, save, showToast, false); 1999181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira return true; 2000181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira } 2001181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira 2002181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira /** 2003181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira * Returns a boolean indicating whether warnings should be shown for empty 2004181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira * subject and body fields 20055c5fd571b40a15b95ea5a5d6033f377706ffd0fbAndy Huang * 2006181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira * @return True if a warning should be shown for empty text fields 2007181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira */ 2008181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira protected boolean showEmptyTextWarnings() { 2009181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira return mAttachmentsView.getAttachments().size() == 0; 2010181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira } 2011181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira 2012181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira /** 2013181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira * Returns a boolean indicating whether the user should confirm each send 2014181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira * 2015181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira * @return True if a warning should be on each send 2016181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira */ 2017181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira protected boolean showSendConfirmation() { 2018181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira return mCachedSettings != null ? mCachedSettings.confirmSend : false; 2019181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira } 2020181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira 2021181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira private void showSendConfirmDialog(int messageId, DialogInterface.OnClickListener listener) { 2022181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira if (mSendConfirmDialog != null) { 2023181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira mSendConfirmDialog.dismiss(); 2024181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira mSendConfirmDialog = null; 2025181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira } 2026181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira mSendConfirmDialog = new AlertDialog.Builder(this).setMessage(messageId) 2027181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira .setTitle(R.string.confirm_send_title) 2028181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira .setIconAttribute(android.R.attr.alertDialogIcon) 2029181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira .setPositiveButton(R.string.send, listener) 20306edd597b1a6628660284f03442cce1f193af66dcMindy Pereira .setNegativeButton(R.string.cancel, this) 20316edd597b1a6628660284f03442cce1f193af66dcMindy Pereira .show(); 2032181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira } 2033181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira 2034181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira /** 2035181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira * Returns whether the ComposeArea believes there is any text in the body of 2036181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira * the composition. TODO: When ComposeArea controls the Body as well, add 2037181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira * that here. 2038181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira */ 2039181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira public boolean isBodyEmpty() { 2040181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira return !mQuotedTextView.isTextIncluded(); 2041181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira } 2042181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira 2043181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira /** 2044181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira * Test to see if the subject is empty. 2045181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira * 2046181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira * @return boolean. 2047181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira */ 2048181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira // TODO: this will likely go away when composeArea.focus() is implemented 2049181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira // after all the widget control is moved over. 2050181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira public boolean isSubjectEmpty() { 2051181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira return TextUtils.getTrimmedLength(mSubject.getText()) == 0; 2052181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira } 2053181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira 2054181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira /* package */ 2055e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira static int sendOrSaveInternal(Context context, ReplyFromAccount replyFromAccount, 205605b92b8ff275f85edae525623c71b65805ca3a51Paul Westbrook Message message, final Message refMessage, Spanned body, final CharSequence quotedText, 205705b92b8ff275f85edae525623c71b65805ca3a51Paul Westbrook SendOrSaveCallback callback, Handler handler, boolean save, int composeMode) { 205829ef1b89b158281ffb693dd5f2c5291a894109fcMindy Pereira ContentValues values = new ContentValues(); 205929ef1b89b158281ffb693dd5f2c5291a894109fcMindy Pereira 2060c203197908a95f707e93621e5eb5f0fb8bfc7d1fMindy Pereira String refMessageId = refMessage != null ? refMessage.uri.toString() : ""; 2061c203197908a95f707e93621e5eb5f0fb8bfc7d1fMindy Pereira 2062e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira MessageModification.putToAddresses(values, message.getToAddresses()); 2063e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira MessageModification.putCcAddresses(values, message.getCcAddresses()); 2064e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira MessageModification.putBccAddresses(values, message.getBccAddresses()); 206529ef1b89b158281ffb693dd5f2c5291a894109fcMindy Pereira 2066e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira MessageModification.putCustomFromAddress(values, message.from); 206792551d057965689f1952faeb06763f0762bc717fMindy Pereira 2068e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira MessageModification.putSubject(values, message.subject); 206929ef1b89b158281ffb693dd5f2c5291a894109fcMindy Pereira String htmlBody = Html.toHtml(body); 207005b92b8ff275f85edae525623c71b65805ca3a51Paul Westbrook 207129ef1b89b158281ffb693dd5f2c5291a894109fcMindy Pereira boolean includeQuotedText = !TextUtils.isEmpty(quotedText); 207229ef1b89b158281ffb693dd5f2c5291a894109fcMindy Pereira StringBuilder fullBody = new StringBuilder(htmlBody); 207329ef1b89b158281ffb693dd5f2c5291a894109fcMindy Pereira if (includeQuotedText) { 2074e8caf1279a1c6ae720215405f678172a5cbf68d7Mindy Pereira // HTML gets converted to text for now 2075e8caf1279a1c6ae720215405f678172a5cbf68d7Mindy Pereira final String text = quotedText.toString(); 2076e8caf1279a1c6ae720215405f678172a5cbf68d7Mindy Pereira if (QuotedTextView.containsQuotedText(text)) { 2077e8caf1279a1c6ae720215405f678172a5cbf68d7Mindy Pereira int pos = QuotedTextView.getQuotedTextOffset(text); 207855271cf624269a5a19bb1989e5904df7adec7ef7Paul Westbrook final int quoteStartPos = fullBody.length() + pos; 207955271cf624269a5a19bb1989e5904df7adec7ef7Paul Westbrook fullBody.append(text); 208055271cf624269a5a19bb1989e5904df7adec7ef7Paul Westbrook MessageModification.putQuoteStartPos(values, quoteStartPos); 208112575866e5526e45eaf773c6c98c93c3a06fe156Mindy Pereira MessageModification.putForward(values, composeMode == ComposeActivity.FORWARD); 2082e8caf1279a1c6ae720215405f678172a5cbf68d7Mindy Pereira MessageModification.putAppendRefMessageContent(values, includeQuotedText); 208329ef1b89b158281ffb693dd5f2c5291a894109fcMindy Pereira } else { 2084e8caf1279a1c6ae720215405f678172a5cbf68d7Mindy Pereira LogUtils.w(LOG_TAG, "Couldn't find quoted text"); 2085e8caf1279a1c6ae720215405f678172a5cbf68d7Mindy Pereira // This shouldn't happen, but just use what we have, 2086e8caf1279a1c6ae720215405f678172a5cbf68d7Mindy Pereira // and don't do server-side expansion 2087e8caf1279a1c6ae720215405f678172a5cbf68d7Mindy Pereira fullBody.append(text); 208829ef1b89b158281ffb693dd5f2c5291a894109fcMindy Pereira } 208929ef1b89b158281ffb693dd5f2c5291a894109fcMindy Pereira } 2090002ff5244800c32f2d70c96cc1110657020ee65cMindy Pereira int draftType = getDraftType(composeMode); 209112575866e5526e45eaf773c6c98c93c3a06fe156Mindy Pereira MessageModification.putDraftType(values, draftType); 2092c6f1e2a8690bd3d4722a2e9386cdc98691135063Mindy Pereira if (refMessage != null) { 2093c6f1e2a8690bd3d4722a2e9386cdc98691135063Mindy Pereira if (!TextUtils.isEmpty(refMessage.bodyHtml)) { 2094c6f1e2a8690bd3d4722a2e9386cdc98691135063Mindy Pereira MessageModification.putBodyHtml(values, fullBody.toString()); 2095c6f1e2a8690bd3d4722a2e9386cdc98691135063Mindy Pereira } 2096c6f1e2a8690bd3d4722a2e9386cdc98691135063Mindy Pereira if (!TextUtils.isEmpty(refMessage.bodyText)) { 2097c6f1e2a8690bd3d4722a2e9386cdc98691135063Mindy Pereira MessageModification.putBody(values, Html.fromHtml(fullBody.toString()).toString()); 2098c6f1e2a8690bd3d4722a2e9386cdc98691135063Mindy Pereira } 2099c6f1e2a8690bd3d4722a2e9386cdc98691135063Mindy Pereira } else { 2100c203197908a95f707e93621e5eb5f0fb8bfc7d1fMindy Pereira MessageModification.putBodyHtml(values, fullBody.toString()); 2101c203197908a95f707e93621e5eb5f0fb8bfc7d1fMindy Pereira MessageModification.putBody(values, Html.fromHtml(fullBody.toString()).toString()); 2102c203197908a95f707e93621e5eb5f0fb8bfc7d1fMindy Pereira } 2103e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira MessageModification.putAttachments(values, message.getAttachments()); 210412575866e5526e45eaf773c6c98c93c3a06fe156Mindy Pereira if (!TextUtils.isEmpty(refMessageId)) { 210512575866e5526e45eaf773c6c98c93c3a06fe156Mindy Pereira MessageModification.putRefMessageId(values, refMessageId); 210612575866e5526e45eaf773c6c98c93c3a06fe156Mindy Pereira } 210782cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira 210892551d057965689f1952faeb06763f0762bc717fMindy Pereira SendOrSaveMessage sendOrSaveMessage = new SendOrSaveMessage(replyFromAccount, 2109181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira values, refMessageId, save); 2110181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira SendOrSaveTask sendOrSaveTask = new SendOrSaveTask(context, sendOrSaveMessage, callback); 211182cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira 2112181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira callback.initializeSendOrSave(sendOrSaveTask); 211382cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira 2114181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira // Do the send/save action on the specified handler to avoid possible 2115181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira // ANRs 2116181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira handler.post(sendOrSaveTask); 211782cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira 2118181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira return sendOrSaveMessage.requestId(); 2119181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira } 212082cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira 2121002ff5244800c32f2d70c96cc1110657020ee65cMindy Pereira private static int getDraftType(int mode) { 2122002ff5244800c32f2d70c96cc1110657020ee65cMindy Pereira int draftType = -1; 2123002ff5244800c32f2d70c96cc1110657020ee65cMindy Pereira switch (mode) { 2124002ff5244800c32f2d70c96cc1110657020ee65cMindy Pereira case ComposeActivity.COMPOSE: 2125002ff5244800c32f2d70c96cc1110657020ee65cMindy Pereira draftType = DraftType.COMPOSE; 2126002ff5244800c32f2d70c96cc1110657020ee65cMindy Pereira break; 2127002ff5244800c32f2d70c96cc1110657020ee65cMindy Pereira case ComposeActivity.REPLY: 2128002ff5244800c32f2d70c96cc1110657020ee65cMindy Pereira draftType = DraftType.REPLY; 2129002ff5244800c32f2d70c96cc1110657020ee65cMindy Pereira break; 2130002ff5244800c32f2d70c96cc1110657020ee65cMindy Pereira case ComposeActivity.REPLY_ALL: 2131002ff5244800c32f2d70c96cc1110657020ee65cMindy Pereira draftType = DraftType.REPLY_ALL; 2132002ff5244800c32f2d70c96cc1110657020ee65cMindy Pereira break; 2133002ff5244800c32f2d70c96cc1110657020ee65cMindy Pereira case ComposeActivity.FORWARD: 2134002ff5244800c32f2d70c96cc1110657020ee65cMindy Pereira draftType = DraftType.FORWARD; 2135002ff5244800c32f2d70c96cc1110657020ee65cMindy Pereira break; 2136002ff5244800c32f2d70c96cc1110657020ee65cMindy Pereira } 2137002ff5244800c32f2d70c96cc1110657020ee65cMindy Pereira return draftType; 2138002ff5244800c32f2d70c96cc1110657020ee65cMindy Pereira } 2139002ff5244800c32f2d70c96cc1110657020ee65cMindy Pereira 2140181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira private void sendOrSave(Spanned body, boolean save, boolean showToast, 2141181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira boolean orientationChanged) { 2142181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira // Check if user is a monkey. Monkeys can compose and hit send 2143181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira // button but are not allowed to send anything off the device. 21443ae824c79ffba25b0cda8b0300f41a28cfbfca7fPaul Westbrook if (ActivityManager.isUserAMonkey()) { 2145181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira return; 2146181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira } 214782cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira 2148181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira String[] to, cc, bcc; 2149181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira if (orientationChanged) { 2150181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira to = cc = bcc = new String[0]; 2151181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira } else { 2152181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira to = getToAddresses(); 2153181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira cc = getCcAddresses(); 2154181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira bcc = getBccAddresses(); 2155181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira } 215682cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira 2157181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira SendOrSaveCallback callback = new SendOrSaveCallback() { 215882cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira private int mRestoredRequestId; 215982cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira 21600bbc858506c95005f2840fa5dff495a9216d2665Marc Blank @Override 216182cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira public void initializeSendOrSave(SendOrSaveTask sendOrSaveTask) { 2162181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira synchronized (mActiveTasks) { 2163181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira int numTasks = mActiveTasks.size(); 2164181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira if (numTasks == 0) { 2165181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira // Start service so we won't be killed if this app is 2166181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira // put in the background. 2167181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira startService(new Intent(ComposeActivity.this, EmptyService.class)); 2168181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira } 2169181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira 2170181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira mActiveTasks.add(sendOrSaveTask); 2171181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira } 2172181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira if (sTestSendOrSaveCallback != null) { 2173181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira sTestSendOrSaveCallback.initializeSendOrSave(sendOrSaveTask); 2174181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira } 2175181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira } 217682cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira 21770bbc858506c95005f2840fa5dff495a9216d2665Marc Blank @Override 21787ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira public void notifyMessageIdAllocated(SendOrSaveMessage sendOrSaveMessage, 21797ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira Message message) { 2180181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira synchronized (mDraftLock) { 2181181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira mDraftId = message.id; 2182181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira mDraft = message; 21837ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira if (sRequestMessageIdMap != null) { 21847ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira sRequestMessageIdMap.put(sendOrSaveMessage.requestId(), mDraftId); 21857ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira } 2186181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira // Cache request message map, in case the process is killed 2187181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira saveRequestMap(); 2188181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira } 2189181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira if (sTestSendOrSaveCallback != null) { 21907ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira sTestSendOrSaveCallback.notifyMessageIdAllocated(sendOrSaveMessage, message); 2191181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira } 2192181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira } 219382cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira 21940bbc858506c95005f2840fa5dff495a9216d2665Marc Blank @Override 21957ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira public Message getMessage() { 21967ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira synchronized (mDraftLock) { 21977ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira return mDraft; 21987ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira } 21997ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira } 220082cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira 22010bbc858506c95005f2840fa5dff495a9216d2665Marc Blank @Override 22027ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira public void sendOrSaveFinished(SendOrSaveTask task, boolean success) { 220347d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereira // Update the last sent from account. 220447d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereira if (mAccount != null) { 220547d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereira MailAppProvider.getInstance().setLastSentFromAccount(mAccount.uri.toString()); 220647d0e65536c55d7aad8c902aef31efb41fd05cf2Mindy Pereira } 22077ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira if (success) { 22087ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira // Successfully sent or saved so reset change markers 22097ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira discardChanges(); 22107ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira } else { 22117ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira // A failure happened with saving/sending the draft 22127ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira // TODO(pwestbro): add a better string that should be used 22137ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira // when failing to send or save 22147ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira Toast.makeText(ComposeActivity.this, R.string.send_failed, Toast.LENGTH_SHORT) 22157ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira .show(); 22167ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira } 221782cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira 22187ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira int numTasks; 22197ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira synchronized (mActiveTasks) { 22207ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira // Remove the task from the list of active tasks 22217ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira mActiveTasks.remove(task); 22227ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira numTasks = mActiveTasks.size(); 22237ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira } 222482cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira 22257ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira if (numTasks == 0) { 22267ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira // Stop service so we can be killed. 22277ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira stopService(new Intent(ComposeActivity.this, EmptyService.class)); 22287ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira } 22297ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira if (sTestSendOrSaveCallback != null) { 22307ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira sTestSendOrSaveCallback.sendOrSaveFinished(task, success); 22317ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira } 22327ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira } 2233181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira }; 2234181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira 2235181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira // Get the selected account if the from spinner has been setup. 223692551d057965689f1952faeb06763f0762bc717fMindy Pereira ReplyFromAccount selectedAccount = mReplyFromAccount; 2237181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira String fromAddress = selectedAccount.name; 2238181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira if (selectedAccount == null || fromAddress == null) { 2239181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira // We don't have either the selected account or from address, 2240181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira // use mAccount. 224192551d057965689f1952faeb06763f0762bc717fMindy Pereira selectedAccount = mReplyFromAccount; 2242181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira fromAddress = mAccount.name; 2243181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira } 2244181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira 2245181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira if (mSendSaveTaskHandler == null) { 2246181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira HandlerThread handlerThread = new HandlerThread("Send Message Task Thread"); 2247181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira handlerThread.start(); 2248181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira 2249181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira mSendSaveTaskHandler = new Handler(handlerThread.getLooper()); 2250181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira } 2251181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira 2252e8f94dc92567d8efa691860c38720d3ae753f429Mindy Pereira Message msg = createMessage(mReplyFromAccount, getMode()); 225305b92b8ff275f85edae525623c71b65805ca3a51Paul Westbrook mRequestId = sendOrSaveInternal(this, mReplyFromAccount, msg, mRefMessage, body, 225405b92b8ff275f85edae525623c71b65805ca3a51Paul Westbrook mQuotedTextView.getQuotedTextIfIncluded(), callback, 225512575866e5526e45eaf773c6c98c93c3a06fe156Mindy Pereira mSendSaveTaskHandler, save, mComposeMode); 2256181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira 2257181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira if (mRecipient != null && mRecipient.equals(mAccount.name)) { 2258181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira mRecipient = selectedAccount.name; 2259181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira } 2260b1f573c59ec20f9149443e1e0cc8b64ff3a07feaPaul Westbrook setAccount(selectedAccount.account); 2261181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira 2262181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira // Don't display the toast if the user is just changing the orientation, 2263181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira // but we still need to save the draft to the cursor because this is how we restore 2264181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira // the attachments when the configuration change completes. 2265181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira if (showToast && (getChangingConfigurations() & ActivityInfo.CONFIG_ORIENTATION) == 0) { 2266181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira Toast.makeText(this, save ? R.string.message_saved : R.string.sending_message, 2267181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira Toast.LENGTH_LONG).show(); 2268181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira } 2269181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira 2270181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira // Need to update variables here because the send or save completes 2271181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira // asynchronously even though the toast shows right away. 2272181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira discardChanges(); 2273181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira updateSaveUi(); 2274181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira 2275181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira // If we are sending, finish the activity 2276181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira if (!save) { 2277181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira finish(); 2278181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira } 2279181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira } 2280181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira 2281181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira /** 2282181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira * Save the state of the request messageid map. This allows for the Gmail 2283181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira * process to be killed, but and still allow for ComposeActivity instances 2284181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira * to be recreated correctly. 2285181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira */ 2286181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira private void saveRequestMap() { 2287181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira // TODO: store the request map in user preferences. 2288181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira } 228982cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira 22908f1c01e908d5986e8222dfd45ab82d6895b1ff3bAndrew Sapperstein public void openAttachmentTypeSelectionDialog() { 22918f1c01e908d5986e8222dfd45ab82d6895b1ff3bAndrew Sapperstein AlertDialog.Builder builder = new AlertDialog.Builder(this); 22928f1c01e908d5986e8222dfd45ab82d6895b1ff3bAndrew Sapperstein builder.setTitle(R.string.add_file_attachment); 22938f1c01e908d5986e8222dfd45ab82d6895b1ff3bAndrew Sapperstein builder.setAdapter(new AttachmentTypeSelectorAdapter(this), 22948f1c01e908d5986e8222dfd45ab82d6895b1ff3bAndrew Sapperstein new DialogInterface.OnClickListener() { 22958f1c01e908d5986e8222dfd45ab82d6895b1ff3bAndrew Sapperstein public void onClick(DialogInterface dialog, int position) { 22968f1c01e908d5986e8222dfd45ab82d6895b1ff3bAndrew Sapperstein doAttach(position); 22978f1c01e908d5986e8222dfd45ab82d6895b1ff3bAndrew Sapperstein } 22988f1c01e908d5986e8222dfd45ab82d6895b1ff3bAndrew Sapperstein }); 22998f1c01e908d5986e8222dfd45ab82d6895b1ff3bAndrew Sapperstein builder.show(); 23008f1c01e908d5986e8222dfd45ab82d6895b1ff3bAndrew Sapperstein } 23018f1c01e908d5986e8222dfd45ab82d6895b1ff3bAndrew Sapperstein 23028f1c01e908d5986e8222dfd45ab82d6895b1ff3bAndrew Sapperstein private void doAttach(int position) { 2303013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira Intent i = new Intent(Intent.ACTION_GET_CONTENT); 2304013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira i.addCategory(Intent.CATEGORY_OPENABLE); 2305d6a9a3f94c69d05f23349a09d71cd36c6fb03613Paul Westbrook i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET); 23068f1c01e908d5986e8222dfd45ab82d6895b1ff3bAndrew Sapperstein i.setType(AttachmentTypeSelectorAdapter.ITEMS.get(position).mMimeType); 2307013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira mAddingAttachment = true; 2308181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira startActivityForResult(Intent.createChooser(i, getText(R.string.select_attachment_type)), 2309181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira RESULT_PICK_ATTACHMENT); 2310013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira } 2311013194caeba8848ba89a68c77843bed2bf7a38e5Mindy Pereira 2312ec8b0edb23c0e0b7f1a8ce9558a919be31169d45Mindy Pereira private void showCcBccViews() { 2313a26b54e3a858de409be3746e65591bb8a0d6ea9aMindy Pereira mCcBccView.show(true, true, true); 2314ec8b0edb23c0e0b7f1a8ce9558a919be31169d45Mindy Pereira if (mCcBccButton != null) { 2315ec8b0edb23c0e0b7f1a8ce9558a919be31169d45Mindy Pereira mCcBccButton.setVisibility(View.GONE); 2316ec8b0edb23c0e0b7f1a8ce9558a919be31169d45Mindy Pereira } 2317ec8b0edb23c0e0b7f1a8ce9558a919be31169d45Mindy Pereira } 2318ec8b0edb23c0e0b7f1a8ce9558a919be31169d45Mindy Pereira 2319326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira @Override 2320326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira public boolean onNavigationItemSelected(int position, long itemId) { 2321a26b54e3a858de409be3746e65591bb8a0d6ea9aMindy Pereira int initialComposeMode = mComposeMode; 2322326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira if (position == ComposeActivity.REPLY) { 2323326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira mComposeMode = ComposeActivity.REPLY; 2324326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } else if (position == ComposeActivity.REPLY_ALL) { 2325326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira mComposeMode = ComposeActivity.REPLY_ALL; 2326326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } else if (position == ComposeActivity.FORWARD) { 2327326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira mComposeMode = ComposeActivity.FORWARD; 2328326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } 2329cbfb75a0f92a3ef5cf10ab94b451e4898cc78bfcMindy Pereira clearChangeListeners(); 2330a26b54e3a858de409be3746e65591bb8a0d6ea9aMindy Pereira if (initialComposeMode != mComposeMode) { 2331154386a287a9bfffb2eb3a4c05445f2774e1d4f0Mindy Pereira resetMessageForModeChange(); 2332ef38830943dac17adb4cade670b5ae0c6b4442c6Mindy Pereira if (mDraft == null && mRefMessage != null) { 233396a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira setFieldsFromRefMessage(mComposeMode, mAccount.name); 23348eca57a78ae01d9c8f55226734131aac1ff3c8aeMindy Pereira } 2335ef38830943dac17adb4cade670b5ae0c6b4442c6Mindy Pereira boolean showCc = false; 2336ef38830943dac17adb4cade670b5ae0c6b4442c6Mindy Pereira boolean showBcc = false; 2337ef38830943dac17adb4cade670b5ae0c6b4442c6Mindy Pereira if (mDraft != null) { 2338ef38830943dac17adb4cade670b5ae0c6b4442c6Mindy Pereira // Following desktop behavior, if the user has added a BCC 2339ef38830943dac17adb4cade670b5ae0c6b4442c6Mindy Pereira // field to a draft, we show it regardless of compose mode. 2340ef38830943dac17adb4cade670b5ae0c6b4442c6Mindy Pereira showBcc = !TextUtils.isEmpty(mDraft.bcc); 2341ef38830943dac17adb4cade670b5ae0c6b4442c6Mindy Pereira // Use the draft to determine what to populate. 2342ef38830943dac17adb4cade670b5ae0c6b4442c6Mindy Pereira // If the Bcc field is showing, show the Cc field whether it is populated or not. 2343ef38830943dac17adb4cade670b5ae0c6b4442c6Mindy Pereira showCc = showBcc || (!TextUtils.isEmpty(mDraft.cc) && mComposeMode == REPLY_ALL); 2344ef38830943dac17adb4cade670b5ae0c6b4442c6Mindy Pereira } else if (mRefMessage != null) { 2345ef38830943dac17adb4cade670b5ae0c6b4442c6Mindy Pereira showCc = mComposeMode == REPLY_ALL && !TextUtils.isEmpty(mRefMessage.cc); 2346ef38830943dac17adb4cade670b5ae0c6b4442c6Mindy Pereira } 2347ef38830943dac17adb4cade670b5ae0c6b4442c6Mindy Pereira mCcBccView.show(false, showCc, showBcc); 2348a26b54e3a858de409be3746e65591bb8a0d6ea9aMindy Pereira } 2349ef38830943dac17adb4cade670b5ae0c6b4442c6Mindy Pereira updateHideOrShowCcBcc(); 2350cbfb75a0f92a3ef5cf10ab94b451e4898cc78bfcMindy Pereira initChangeListeners(); 2351326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira return true; 2352326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } 2353326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira 2354b3112a2bf7b805695259e412b0e2bc0e0e73e9d6Mindy Pereira @VisibleForTesting 2355b3112a2bf7b805695259e412b0e2bc0e0e73e9d6Mindy Pereira protected void resetMessageForModeChange() { 2356154386a287a9bfffb2eb3a4c05445f2774e1d4f0Mindy Pereira // When switching between reply, reply all, forward, 2357154386a287a9bfffb2eb3a4c05445f2774e1d4f0Mindy Pereira // follow the behavior of webview. 2358154386a287a9bfffb2eb3a4c05445f2774e1d4f0Mindy Pereira // The contents of the following fields are cleared 2359154386a287a9bfffb2eb3a4c05445f2774e1d4f0Mindy Pereira // so that they can be populated directly from the 2360154386a287a9bfffb2eb3a4c05445f2774e1d4f0Mindy Pereira // ref message: 2361154386a287a9bfffb2eb3a4c05445f2774e1d4f0Mindy Pereira // 1) Any recipient fields 2362154386a287a9bfffb2eb3a4c05445f2774e1d4f0Mindy Pereira // 2) The subject 2363154386a287a9bfffb2eb3a4c05445f2774e1d4f0Mindy Pereira mTo.setText(""); 2364154386a287a9bfffb2eb3a4c05445f2774e1d4f0Mindy Pereira mCc.setText(""); 2365154386a287a9bfffb2eb3a4c05445f2774e1d4f0Mindy Pereira mBcc.setText(""); 2366154386a287a9bfffb2eb3a4c05445f2774e1d4f0Mindy Pereira // Any edits to the subject are replaced with the original subject. 2367154386a287a9bfffb2eb3a4c05445f2774e1d4f0Mindy Pereira mSubject.setText(""); 2368154386a287a9bfffb2eb3a4c05445f2774e1d4f0Mindy Pereira 2369154386a287a9bfffb2eb3a4c05445f2774e1d4f0Mindy Pereira // Any changes to the contents of the following fields are kept: 2370154386a287a9bfffb2eb3a4c05445f2774e1d4f0Mindy Pereira // 1) Body 2371154386a287a9bfffb2eb3a4c05445f2774e1d4f0Mindy Pereira // 2) Attachments 2372154386a287a9bfffb2eb3a4c05445f2774e1d4f0Mindy Pereira // If the user made changes to attachments, keep their changes. 2373154386a287a9bfffb2eb3a4c05445f2774e1d4f0Mindy Pereira if (!mAttachmentsChanged) { 2374154386a287a9bfffb2eb3a4c05445f2774e1d4f0Mindy Pereira mAttachmentsView.deleteAllAttachments(); 2375154386a287a9bfffb2eb3a4c05445f2774e1d4f0Mindy Pereira } 2376154386a287a9bfffb2eb3a4c05445f2774e1d4f0Mindy Pereira } 2377154386a287a9bfffb2eb3a4c05445f2774e1d4f0Mindy Pereira 2378326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira private class ComposeModeAdapter extends ArrayAdapter<String> { 2379326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira 2380326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira private LayoutInflater mInflater; 2381326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira 2382326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira public ComposeModeAdapter(Context context) { 2383326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira super(context, R.layout.compose_mode_item, R.id.mode, getResources() 2384326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira .getStringArray(R.array.compose_modes)); 2385326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } 2386326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira 2387326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira private LayoutInflater getInflater() { 2388326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira if (mInflater == null) { 2389326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira mInflater = LayoutInflater.from(getContext()); 2390326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } 2391326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira return mInflater; 2392326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } 2393326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira 2394326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira @Override 2395326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira public View getView(int position, View convertView, ViewGroup parent) { 2396326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira if (convertView == null) { 2397326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira convertView = getInflater().inflate(R.layout.compose_mode_display_item, null); 2398326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } 2399326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira ((TextView) convertView.findViewById(R.id.mode)).setText(getItem(position)); 2400326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira return super.getView(position, convertView, parent); 2401326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } 2402326c660df0a0a36a52ae74d8bafaa22d6f253561Mindy Pereira } 240346ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira 240446ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira @Override 240546ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira public void onRespondInline(String text) { 240646ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira appendToBody(text, false); 240746ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira } 240846ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira 240946ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira /** 241046ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira * Append text to the body of the message. If there is no existing body 241146ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira * text, just sets the body to text. 241246ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira * 241346ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira * @param text 241446ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira * @param withSignature True to append a signature. 241546ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira */ 241646ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira public void appendToBody(CharSequence text, boolean withSignature) { 2417eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira Editable bodyText = mBodyView.getEditableText(); 241846ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira if (bodyText != null && bodyText.length() > 0) { 241946ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira bodyText.append(text); 242046ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira } else { 242146ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira setBody(text, withSignature); 242246ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira } 242346ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira } 242446ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira 242546ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira /** 242646ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira * Set the body of the message. 2427bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira * 242846ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira * @param text 242946ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira * @param withSignature True to append a signature. 243046ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira */ 243146ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira public void setBody(CharSequence text, boolean withSignature) { 2432eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira mBodyView.setText(text); 2433bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira if (withSignature) { 2434bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira appendSignature(); 2435bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira } 2436bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira } 2437bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira 2438bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira private void appendSignature() { 2439b13917c3d753c6674db2a226668a7f3048ddc4b5Mindy Pereira String newSignature = mCachedSettings != null ? mCachedSettings.signature : null; 2440433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira boolean hasFocus = mBodyView.hasFocus(); 2441b13917c3d753c6674db2a226668a7f3048ddc4b5Mindy Pereira if (!TextUtils.equals(newSignature, mSignature)) { 2442b13917c3d753c6674db2a226668a7f3048ddc4b5Mindy Pereira mSignature = newSignature; 2443b13917c3d753c6674db2a226668a7f3048ddc4b5Mindy Pereira if (!TextUtils.isEmpty(mSignature) 2444b13917c3d753c6674db2a226668a7f3048ddc4b5Mindy Pereira && getSignatureStartPosition(mSignature, 2445b13917c3d753c6674db2a226668a7f3048ddc4b5Mindy Pereira mBodyView.getText().toString()) < 0) { 2446b13917c3d753c6674db2a226668a7f3048ddc4b5Mindy Pereira // Appending a signature does not count as changing text. 2447b13917c3d753c6674db2a226668a7f3048ddc4b5Mindy Pereira mBodyView.removeTextChangedListener(this); 2448b13917c3d753c6674db2a226668a7f3048ddc4b5Mindy Pereira mBodyView.append(convertToPrintableSignature(mSignature)); 2449b13917c3d753c6674db2a226668a7f3048ddc4b5Mindy Pereira mBodyView.addTextChangedListener(this); 2450b13917c3d753c6674db2a226668a7f3048ddc4b5Mindy Pereira } 2451433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira if (hasFocus) { 2452433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira focusBody(); 2453433b198e1a9385d1ca1284db0a168734768e0455Mindy Pereira } 2454bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira } 2455bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira } 2456bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira 2457bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira private String convertToPrintableSignature(String signature) { 2458bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira String signatureResource = getResources().getString(R.string.signature); 2459bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira if (signature == null) { 2460bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira signature = ""; 2461bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira } 2462bdf7a40583381ae26d11dcd0fca40bca230f96f3Mindy Pereira return String.format(signatureResource, signature); 246346ce0b13c33d1ade0e4537e780b41fea5e2a6be9Mindy Pereira } 24641a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira 24655a85e2b7485a5c407c581219fe1b44417f050529Mindy Pereira @Override 24665a85e2b7485a5c407c581219fe1b44417f050529Mindy Pereira public void onAccountChanged() { 246792551d057965689f1952faeb06763f0762bc717fMindy Pereira mReplyFromAccount = mFromSpinner.getCurrentAccount(); 246892551d057965689f1952faeb06763f0762bc717fMindy Pereira if (!mAccount.equals(mReplyFromAccount.account)) { 2469b1f573c59ec20f9149443e1e0cc8b64ff3a07feaPaul Westbrook setAccount(mReplyFromAccount.account); 2470b1f573c59ec20f9149443e1e0cc8b64ff3a07feaPaul Westbrook 2471181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira // TODO: handle discarding attachments when switching accounts. 2472181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira // Only enable save for this draft if there is any other content 2473181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira // in the message. 2474181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira if (!isBlank()) { 2475181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira enableSave(true); 2476181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira } 2477181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira mReplyFromChanged = true; 2478181df7851bd1eba4b6a3255073a8b731de23ae8fMindy Pereira initRecipients(); 247982cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira } 24801a95a57f39da84cd7daf4e2161e50e518df51f13Mindy Pereira } 248182cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira 248282cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira public void enableSave(boolean enabled) { 248382cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira if (mSave != null) { 248482cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira mSave.setEnabled(enabled); 248582cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira } 248682cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira } 248782cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira 248882cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira public void enableSend(boolean enabled) { 248982cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira if (mSend != null) { 249082cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira mSend.setEnabled(enabled); 249182cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira } 249282cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira } 249382cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira 249482cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira /** 249582cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira * Handles button clicks from any error dialogs dealing with sending 249682cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira * a message. 249782cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira */ 249882cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira @Override 249982cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira public void onClick(DialogInterface dialog, int which) { 250082cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira switch (which) { 250182cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira case DialogInterface.BUTTON_POSITIVE: { 250282cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira doDiscardWithoutConfirmation(true /* show toast */ ); 250382cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira break; 250482cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira } 250582cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira case DialogInterface.BUTTON_NEGATIVE: { 250682cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira // If the user cancels the send, re-enable the send button. 250782cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira enableSend(true); 250882cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira break; 250982cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira } 251082cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira } 251182cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira 251282cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira } 251382cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira 2514efe3d25aa19da172fd5c3ec39539cdd91f29e927Mindy Pereira private void doDiscard() { 2515efe3d25aa19da172fd5c3ec39539cdd91f29e927Mindy Pereira new AlertDialog.Builder(this).setMessage(R.string.confirm_discard_text) 2516efe3d25aa19da172fd5c3ec39539cdd91f29e927Mindy Pereira .setPositiveButton(R.string.ok, this) 2517efe3d25aa19da172fd5c3ec39539cdd91f29e927Mindy Pereira .setNegativeButton(R.string.cancel, null) 2518efe3d25aa19da172fd5c3ec39539cdd91f29e927Mindy Pereira .create().show(); 2519efe3d25aa19da172fd5c3ec39539cdd91f29e927Mindy Pereira } 252082cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira /** 252182cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira * Effectively discard the current message. 252282cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira * 252382cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira * This method is either invoked from the menu or from the dialog 252482cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira * once the user has confirmed that they want to discard the message. 252582cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira * @param showToast show "Message discarded" toast if true 252682cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira */ 252782cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira private void doDiscardWithoutConfirmation(boolean showToast) { 25287ed1c1122c5677344a1ce176be2c03972fed26f5Mindy Pereira synchronized (mDraftLock) { 252982cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira if (mDraftId != UIProvider.INVALID_MESSAGE_ID) { 253082cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira ContentValues values = new ContentValues(); 2531b7050e62aab7133dea300d7fb3266311da99ec80Paul Westbrook values.put(BaseColumns._ID, mDraftId); 253278ea8e20c7d678c79153a1f814d0740f2bf3e462Marc Blank if (!mAccount.expungeMessageUri.equals(Uri.EMPTY)) { 2533cfb7f33ff8ef9dc60b9143af32de64c7a3d71f36Mindy Pereira getContentResolver().update(mAccount.expungeMessageUri, values, null, null); 2534cfb7f33ff8ef9dc60b9143af32de64c7a3d71f36Mindy Pereira } else { 25350bbc858506c95005f2840fa5dff495a9216d2665Marc Blank getContentResolver().delete(mDraft.uri, null, null); 2536cfb7f33ff8ef9dc60b9143af32de64c7a3d71f36Mindy Pereira } 253782cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira // This is not strictly necessary (since we should not try to 253882cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira // save the draft after calling this) but it ensures that if we 253982cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira // do save again for some reason we make a new draft rather than 254082cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira // trying to resave an expunged draft. 254182cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira mDraftId = UIProvider.INVALID_MESSAGE_ID; 254282cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira } 254382cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira } 254482cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira 254582cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira if (showToast) { 254682cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira // Display a toast to let the user know 254782cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira Toast.makeText(this, R.string.message_discarded, Toast.LENGTH_SHORT).show(); 254882cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira } 254982cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira 255082cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira // This prevents the draft from being saved in onPause(). 255182cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira discardChanges(); 255282cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira finish(); 255382cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira } 255482cc5665cb18801022cd60cd52abcd16a50debdcMindy Pereira 2555eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira private void saveIfNeeded() { 2556eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira if (mAccount == null) { 2557eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira // We have not chosen an account yet so there's no way that we can save. This is ok, 2558eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira // though, since we are saving our state before AccountsActivity is activated. Thus, the 2559eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira // user has not interacted with us yet and there is no real state to save. 2560eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira return; 2561eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira } 2562eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira 2563eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira if (shouldSave()) { 256448e31b07b5ac7c83dc3a009242fa915afccddb9eMindy Pereira doSave(!mAddingAttachment /* show toast */); 2565eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira } 2566eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira } 2567eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira 2568eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira @Override 2569eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira public void onAttachmentDeleted() { 2570eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira mAttachmentsChanged = true; 2571eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira updateSaveUi(); 2572eaea9f16b2b61eed6b62fe9a5c567bfbe0d75d80Mindy Pereira } 257375f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira 257475f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira 257575f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira /** 257675f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira * This is called any time one of our text fields changes. 257775f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira */ 25780bbc858506c95005f2840fa5dff495a9216d2665Marc Blank @Override 257975f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira public void afterTextChanged(Editable s) { 258075f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira mTextChanged = true; 258175f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira updateSaveUi(); 258275f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira } 258375f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira 258475f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira @Override 258575f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira public void beforeTextChanged(CharSequence s, int start, int count, int after) { 258675f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira // Do nothing. 258775f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira } 258875f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira 25890bbc858506c95005f2840fa5dff495a9216d2665Marc Blank @Override 259075f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira public void onTextChanged(CharSequence s, int start, int before, int count) { 259175f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira // Do nothing. 259275f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira } 259375f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira 259475f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira 259575f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira // There is a big difference between the text associated with an address changing 259675f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira // to add the display name or to format properly and a recipient being added or deleted. 259775f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira // Make sure we only notify of changes when a recipient has been added or deleted. 259875f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira private class RecipientTextWatcher implements TextWatcher { 259975f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira private HashMap<String, Integer> mContent = new HashMap<String, Integer>(); 260075f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira 260175f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira private RecipientEditTextView mView; 260275f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira 260375f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira private TextWatcher mListener; 260475f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira 260575f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira public RecipientTextWatcher(RecipientEditTextView view, TextWatcher listener) { 260675f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira mView = view; 260775f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira mListener = listener; 260875f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira } 260975f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira 261075f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira @Override 261175f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira public void afterTextChanged(Editable s) { 261275f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira if (hasChanged()) { 261375f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira mListener.afterTextChanged(s); 261475f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira } 261575f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira } 261675f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira 261775f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira private boolean hasChanged() { 261875f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira String[] currRecips = tokenizeRecips(getAddressesFromList(mView)); 261975f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira int totalCount = currRecips.length; 262075f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira int totalPrevCount = 0; 262175f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira for (Entry<String, Integer> entry : mContent.entrySet()) { 262275f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira totalPrevCount += entry.getValue(); 262375f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira } 262475f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira if (totalCount != totalPrevCount) { 262575f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira return true; 262675f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira } 262775f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira 262875f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira for (String recip : currRecips) { 262975f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira if (!mContent.containsKey(recip)) { 263075f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira return true; 263175f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira } else { 263275f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira int count = mContent.get(recip) - 1; 263375f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira if (count < 0) { 263475f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira return true; 263575f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira } else { 263675f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira mContent.put(recip, count); 263775f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira } 263875f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira } 263975f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira } 264075f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira return false; 264175f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira } 264275f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira 264375f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira private String[] tokenizeRecips(String[] recips) { 264475f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira // Tokenize them all and put them in the list. 264575f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira String[] recipAddresses = new String[recips.length]; 264675f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira for (int i = 0; i < recips.length; i++) { 264775f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira recipAddresses[i] = Rfc822Tokenizer.tokenize(recips[i])[0].getAddress(); 264875f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira } 264975f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira return recipAddresses; 265075f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira } 265175f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira 265275f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira @Override 265375f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira public void beforeTextChanged(CharSequence s, int start, int count, int after) { 265475f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira String[] recips = tokenizeRecips(getAddressesFromList(mView)); 265575f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira for (String recip : recips) { 265675f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira if (!mContent.containsKey(recip)) { 265775f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira mContent.put(recip, 1); 265875f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira } else { 265975f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira mContent.put(recip, (mContent.get(recip)) + 1); 266075f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira } 266175f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira } 266275f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira } 266375f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira 266475f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira @Override 266575f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira public void onTextChanged(CharSequence s, int start, int before, int count) { 266675f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira // Do nothing. 266775f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira } 266875f66634dd18cc8d8e6f40c4573c0edf0a0343efMindy Pereira } 2669e011b1d1c8e2e674dfdf1985d9d13da8cc06d803Mindy Pereira 2670e011b1d1c8e2e674dfdf1985d9d13da8cc06d803Mindy Pereira public static void registerTestSendOrSaveCallback(SendOrSaveCallback testCallback) { 2671e011b1d1c8e2e674dfdf1985d9d13da8cc06d803Mindy Pereira if (sTestSendOrSaveCallback != null && testCallback != null) { 2672e011b1d1c8e2e674dfdf1985d9d13da8cc06d803Mindy Pereira throw new IllegalStateException("Attempting to register more than one test callback"); 2673e011b1d1c8e2e674dfdf1985d9d13da8cc06d803Mindy Pereira } 2674e011b1d1c8e2e674dfdf1985d9d13da8cc06d803Mindy Pereira sTestSendOrSaveCallback = testCallback; 2675e011b1d1c8e2e674dfdf1985d9d13da8cc06d803Mindy Pereira } 2676bddd6f39f34aa15fed2e757f7d3e4163272ca02cMindy Pereira 2677bddd6f39f34aa15fed2e757f7d3e4163272ca02cMindy Pereira @VisibleForTesting 2678bddd6f39f34aa15fed2e757f7d3e4163272ca02cMindy Pereira protected ArrayList<Attachment> getAttachments() { 2679bddd6f39f34aa15fed2e757f7d3e4163272ca02cMindy Pereira return mAttachmentsView.getAttachments(); 2680bddd6f39f34aa15fed2e757f7d3e4163272ca02cMindy Pereira } 268196a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira 268296a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira @Override 268396a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira public Loader<Cursor> onCreateLoader(int id, Bundle args) { 268496a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira switch (id) { 268596a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira case REFERENCE_MESSAGE_LOADER: 268696a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira return new CursorLoader(this, mRefMessageUri, UIProvider.MESSAGE_PROJECTION, null, 268796a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira null, null); 268896a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira } 268996a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira return null; 269096a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira } 269196a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira 269296a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira @Override 269396a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira public void onLoadFinished(Loader<Cursor> loader, Cursor data) { 269496a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira if (data != null && data.moveToFirst()) { 269596a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira mRefMessage = new Message(data); 269696a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira // We set these based on EXTRA_TO. 269796a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira mRefMessage.to = null; 269896a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira mRefMessage.from = null; 269996a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira Intent intent = getIntent(); 270096a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira int action = intent.getIntExtra(EXTRA_ACTION, COMPOSE); 270196a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira initFromRefMessage(action, mAccount.name); 270296a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira finishSetup(action, intent, null, true); 270396a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira if (action != FORWARD) { 270496a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira String to = intent.getStringExtra(EXTRA_TO); 270596a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira if (!TextUtils.isEmpty(to)) { 270696a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira clearChangeListeners(); 270796a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira mTo.append(to); 270896a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira initChangeListeners(); 270996a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira } 271096a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira } 271196a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira } else { 271296a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira finish(); 271396a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira } 271496a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira } 271596a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira 271696a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira @Override 271796a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira public void onLoaderReset(Loader<Cursor> arg0) { 271896a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira // Do nothing. 271996a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira } 272096a7f7aa2de33b1722009a9ee77d2b7b18a8e3e9Mindy Pereira}